/* ====================================================================
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to You under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
==================================================================== */
package org.apache.poi.xwpf.usermodel;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.util.Internal;
import org.apache.poi.wp.usermodel.Paragraph;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

/**
 * <p>A Paragraph within a Document, Table, Header etc.</p>
 * <p/>
 * <p>A paragraph has a lot of styling information, but the
 * actual text (possibly along with more styling) is held on
 * the child {@link XWPFRun}s.</p>
 */
public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Paragraph {
    private final CTP paragraph;
    protected IBody part;
    /**
     * For access to the document's hyperlink, comments, tables etc
     */
    protected XWPFDocument document;
    protected List<XWPFRun> runs;
    protected List<IRunElement> iruns;

    private StringBuffer footnoteText = new StringBuffer();

    public XWPFParagraph(CTP prgrph, IBody part) {
        this.paragraph = prgrph;
        this.part = part;

        this.document = part.getXWPFDocument();

        if (document == null) {
            throw new NullPointerException();
        }

        // Build up the character runs
        runs = new ArrayList<XWPFRun>();
        iruns = new ArrayList<IRunElement>();
        buildRunsInOrderFromXml(paragraph);

        // Look for bits associated with the runs
        for (XWPFRun run : runs) {
            CTR r = run.getCTR();

            // Check for bits that only apply when attached to a core document
            // TODO Make this nicer by tracking the XWPFFootnotes directly
            XmlCursor c = r.newCursor();
            c.selectPath("child::*");
            while (c.toNextSelection()) {
                XmlObject o = c.getObject();
                if (o instanceof CTFtnEdnRef) {
                    CTFtnEdnRef ftn = (CTFtnEdnRef) o;
                    footnoteText.append(" [").append(ftn.getId()).append(": ");
                    XWPFFootnote footnote =
                            ftn.getDomNode().getLocalName().equals("footnoteReference") ?
                                    document.getFootnoteByID(ftn.getId().intValue()) :
                                    document.getEndnoteByID(ftn.getId().intValue());

                    boolean first = true;
                    for (XWPFParagraph p : footnote.getParagraphs()) {
                        if (!first) {
                            footnoteText.append("\n");
                        }
                        first = false;
                        footnoteText.append(p.getText());
                    }

                    footnoteText.append("] ");
                }
            }
            c.dispose();
        }
    }

    /**
     * Identifies (in order) the parts of the paragraph /
     * sub-paragraph that correspond to character text
     * runs, and builds the appropriate runs for these.
     */
    @SuppressWarnings("deprecation")
    private void buildRunsInOrderFromXml(XmlObject object) {
        XmlCursor c = object.newCursor();
        c.selectPath("child::*");
        while (c.toNextSelection()) {
            XmlObject o = c.getObject();
            if (o instanceof CTR) {
                XWPFRun r = new XWPFRun((CTR) o, this);
                runs.add(r);
                iruns.add(r);
            }
            if (o instanceof CTHyperlink) {
                CTHyperlink link = (CTHyperlink)o;
                for (CTR r : link.getRArray()) {
                    XWPFHyperlinkRun hr = new XWPFHyperlinkRun(link, r, this);
                    runs.add(hr);
                    iruns.add(hr);
                }
            }
            if (o instanceof CTSimpleField) {
                CTSimpleField field = (CTSimpleField)o;
                for (CTR r : field.getRArray()) {
                    XWPFFieldRun fr = new XWPFFieldRun(field, r, this);
                    runs.add(fr);
                    iruns.add(fr);
                }
            }
            if (o instanceof CTSdtBlock) {
                XWPFSDT cc = new XWPFSDT((CTSdtBlock) o, part);
                iruns.add(cc);
            }
            if (o instanceof CTSdtRun) {
                XWPFSDT cc = new XWPFSDT((CTSdtRun) o, part);
                iruns.add(cc);
            }
            if (o instanceof CTRunTrackChange) {
                for (CTR r : ((CTRunTrackChange) o).getRArray()) {
                    XWPFRun cr = new XWPFRun(r, this);
                    runs.add(cr);
                    iruns.add(cr);
                }
            }
            if (o instanceof CTSmartTagRun) {
                // Smart Tags can be nested many times.
                // This implementation does not preserve the tagging information
                buildRunsInOrderFromXml(o);
            }
        }
        c.dispose();
    }

    @Internal
    public CTP getCTP() {
        return paragraph;
    }

    public List<XWPFRun> getRuns() {
        return Collections.unmodifiableList(runs);
    }

    /**
     * Return literal runs and sdt/content control objects.
     *
     * @return List<IRunElement>
     */
    public List<IRunElement> getIRuns() {
        return Collections.unmodifiableList(iruns);
    }

    public boolean isEmpty() {
        return !paragraph.getDomNode().hasChildNodes();
    }

    @Override
    public XWPFDocument getDocument() {
        return document;
    }

    /**
     * Return the textual content of the paragraph, including text from pictures
     * and sdt elements in it.
     */
    public String getText() {
        StringBuffer out = new StringBuffer();
        for (IRunElement run : iruns) {
            if (run instanceof XWPFRun) {
                XWPFRun xRun = (XWPFRun) run;
                // don't include the text if reviewing is enabled and this is a deleted run
                if (!xRun.getCTR().isSetRsidDel()) {
                    out.append(xRun.toString());
                }
            } else if (run instanceof XWPFSDT) {
                out.append(((XWPFSDT) run).getContent().getText());
            } else {
                out.append(run.toString());
            }
        }
        out.append(footnoteText);
        return out.toString();
    }

    /**
     * Return styleID of the paragraph if style exist for this paragraph
     * if not, null will be returned
     *
     * @return styleID as String
     */
    public String getStyleID() {
        if (paragraph.getPPr() != null) {
            if (paragraph.getPPr().getPStyle() != null) {
                if (paragraph.getPPr().getPStyle().getVal() != null) {
                    return paragraph.getPPr().getPStyle().getVal();
                }
            }
        }
        return null;
    }

    /**
     * If style exist for this paragraph
     * NumId of the paragraph will be returned.
     * If style not exist null will be returned
     *
     * @return NumID as BigInteger
     */
    public BigInteger getNumID() {
        if (paragraph.getPPr() != null) {
            if (paragraph.getPPr().getNumPr() != null) {
                if (paragraph.getPPr().getNumPr().getNumId() != null) {
                    return paragraph.getPPr().getNumPr().getNumId().getVal();
                }
            }
        }
        return null;
    }

    /**
     * setNumID of Paragraph
     *
     * @param numPos
     */
    public void setNumID(BigInteger numPos) {
        if (paragraph.getPPr() == null) {
            paragraph.addNewPPr();
        }
        if (paragraph.getPPr().getNumPr() == null) {
            paragraph.getPPr().addNewNumPr();
        }
        if (paragraph.getPPr().getNumPr().getNumId() == null) {
            paragraph.getPPr().getNumPr().addNewNumId();
        }
        paragraph.getPPr().getNumPr().getNumId().setVal(numPos);
    }

    /**
     * Returns Ilvl of the numeric style for this paragraph.
     * Returns null if this paragraph does not have numeric style.
     *
     * @return Ilvl as BigInteger
     */
    public BigInteger getNumIlvl() {
        if (paragraph.getPPr() != null) {
            if (paragraph.getPPr().getNumPr() != null) {
                if (paragraph.getPPr().getNumPr().getIlvl() != null) {
                    return paragraph.getPPr().getNumPr().getIlvl().getVal();
                }
            }
        }
        return null;
    }

    /**
     * Returns numbering format for this paragraph, eg bullet or
     * lowerLetter.
     * Returns null if this paragraph does not have numeric style.
     */
    public String getNumFmt() {
        BigInteger numID = getNumID();
        XWPFNumbering numbering = document.getNumbering();
        if (numID != null && numbering != null) {
            XWPFNum num = numbering.getNum(numID);
            if (num != null) {
                BigInteger ilvl = getNumIlvl();
                BigInteger abstractNumId = num.getCTNum().getAbstractNumId().getVal();
                CTAbstractNum anum = numbering.getAbstractNum(abstractNumId).getAbstractNum();
                CTLvl level = null;
                for (int i = 0; i < anum.sizeOfLvlArray(); i++) {
                    CTLvl lvl = anum.getLvlArray(i);
                    if (lvl.getIlvl().equals(ilvl)) {
                        level = lvl;
                        break;
                    }
                }
                if (level != null && level.getNumFmt() != null
                        && level.getNumFmt().getVal() != null) {
                    return level.getNumFmt().getVal().toString();
                }
            }
        }
        return null;
    }

    /**
     * Returns the text that should be used around the paragraph level numbers.
     *
     * @return a string (e.g. "%1.") or null if the value is not found.
     */
    public String getNumLevelText() {
        BigInteger numID = getNumID();
        XWPFNumbering numbering = document.getNumbering();
        if (numID != null && numbering != null) {
            XWPFNum num = numbering.getNum(numID);
            if (num != null) {
                BigInteger ilvl = getNumIlvl();
                CTNum ctNum = num.getCTNum();
                if (ctNum == null) {
                    return null;
                }

                CTDecimalNumber ctDecimalNumber = ctNum.getAbstractNumId();
                if (ctDecimalNumber == null) {
                    return null;
                }

                BigInteger abstractNumId = ctDecimalNumber.getVal();
                if (abstractNumId == null) {
                    return null;
                }

                XWPFAbstractNum xwpfAbstractNum = numbering.getAbstractNum(abstractNumId);

                if (xwpfAbstractNum == null) {
                    return null;
                }

                CTAbstractNum anum = xwpfAbstractNum.getCTAbstractNum();

                if (anum == null) {
                    return null;
                }

                CTLvl level = null;
                for (int i = 0; i < anum.sizeOfLvlArray(); i++) {
                    CTLvl lvl = anum.getLvlArray(i);
                    if (lvl != null && lvl.getIlvl() != null && lvl.getIlvl().equals(ilvl)) {
                        level = lvl;
                        break;
                    }
                }
                if (level != null && level.getLvlText() != null
                        && level.getLvlText().getVal() != null) {
                    return level.getLvlText().getVal().toString();
                }
            }
        }
        return null;
    }

    /**
     * Gets the numstartOverride for the paragraph numbering for this paragraph.
     *
     * @return returns the overridden start number or null if there is no override for this paragraph.
     */
    public BigInteger getNumStartOverride() {
        BigInteger numID = getNumID();
        XWPFNumbering numbering = document.getNumbering();
        if (numID != null && numbering != null) {
            XWPFNum num = numbering.getNum(numID);

            if (num != null) {
                CTNum ctNum = num.getCTNum();
                if (ctNum == null) {
                    return null;
                }
                BigInteger ilvl = getNumIlvl();
                CTNumLvl level = null;
                for (int i = 0; i < ctNum.sizeOfLvlOverrideArray(); i++) {
                    CTNumLvl ctNumLvl = ctNum.getLvlOverrideArray(i);
                    if (ctNumLvl != null && ctNumLvl.getIlvl() != null &&
                            ctNumLvl.getIlvl().equals(ilvl)) {
                        level = ctNumLvl;
                        break;
                    }
                }
                if (level != null && level.getStartOverride() != null) {
                    return level.getStartOverride().getVal();
                }
            }
        }
        return null;
    }

    /**
     * Returns the text of the paragraph, but not of any objects in the
     * paragraph
     */
    public String getParagraphText() {
        StringBuffer out = new StringBuffer();
        for (XWPFRun run : runs) {
            out.append(run.toString());
        }
        return out.toString();
    }

    /**
     * Returns any text from any suitable pictures in the paragraph
     */
    public String getPictureText() {
        StringBuffer out = new StringBuffer();
        for (XWPFRun run : runs) {
            out.append(run.getPictureText());
        }
        return out.toString();
    }

    /**
     * Returns the footnote text of the paragraph
     *
     * @return the footnote text or empty string if the paragraph does not have footnotes
     */
    public String getFootnoteText() {
        return footnoteText.toString();
    }

    /**
     * Returns the paragraph alignment which shall be applied to text in this
     * paragraph.
     * <p/>
     * <p/>
     * If this element is not set on a given paragraph, its value is determined
     * by the setting previously set at any level of the style hierarchy (i.e.
     * that previous setting remains unchanged). If this setting is never
     * specified in the style hierarchy, then no alignment is applied to the
     * paragraph.
     * </p>
     *
     * @return the paragraph alignment of this paragraph.
     */
    public ParagraphAlignment getAlignment() {
        CTPPr pr = getCTPPr();
        return pr == null || !pr.isSetJc() ? ParagraphAlignment.LEFT
                : ParagraphAlignment.valueOf(pr.getJc().getVal().intValue());
    }

    /**
     * Specifies the paragraph alignment which shall be applied to text in this
     * paragraph.
     * <p/>
     * <p/>
     * If this element is not set on a given paragraph, its value is determined
     * by the setting previously set at any level of the style hierarchy (i.e.
     * that previous setting remains unchanged). If this setting is never
     * specified in the style hierarchy, then no alignment is applied to the
     * paragraph.
     * </p>
     *
     * @param align the paragraph alignment to apply to this paragraph.
     */
    public void setAlignment(ParagraphAlignment align) {
        CTPPr pr = getCTPPr();
        CTJc jc = pr.isSetJc() ? pr.getJc() : pr.addNewJc();
        STJc.Enum en = STJc.Enum.forInt(align.getValue());
        jc.setVal(en);
    }

    /**
     * @return The raw alignment value, {@link #getAlignment()} is suggested
     */
    @Override
    public int getFontAlignment() {
        return getAlignment().getValue();
    }

    @Override
    public void setFontAlignment(int align) {
        ParagraphAlignment pAlign = ParagraphAlignment.valueOf(align);
        setAlignment(pAlign);
    }

    /**
     * Returns the text vertical alignment which shall be applied to text in
     * this paragraph.
     * <p/>
     * If the line height (before any added spacing) is larger than one or more
     * characters on the line, all characters will be aligned to each other as
     * specified by this element.
     * </p>
     * <p/>
     * If this element is omitted on a given paragraph, its value is determined
     * by the setting previously set at any level of the style hierarchy (i.e.
     * that previous setting remains unchanged). If this setting is never
     * specified in the style hierarchy, then the vertical alignment of all
     * characters on the line shall be automatically determined by the consumer.
     * </p>
     *
     * @return the vertical alignment of this paragraph.
     */
    public TextAlignment getVerticalAlignment() {
        CTPPr pr = getCTPPr();
        return (pr == null || !pr.isSetTextAlignment()) ? TextAlignment.AUTO
                : TextAlignment.valueOf(pr.getTextAlignment().getVal()
                .intValue());
    }

    /**
     * Specifies the text vertical alignment which shall be applied to text in
     * this paragraph.
     * <p/>
     * If the line height (before any added spacing) is larger than one or more
     * characters on the line, all characters will be aligned to each other as
     * specified by this element.
     * </p>
     * <p/>
     * If this element is omitted on a given paragraph, its value is determined
     * by the setting previously set at any level of the style hierarchy (i.e.
     * that previous setting remains unchanged). If this setting is never
     * specified in the style hierarchy, then the vertical alignment of all
     * characters on the line shall be automatically determined by the consumer.
     * </p>
     *
     * @param valign the paragraph vertical alignment to apply to this
     *               paragraph.
     */
    public void setVerticalAlignment(TextAlignment valign) {
        CTPPr pr = getCTPPr();
        CTTextAlignment textAlignment = pr.isSetTextAlignment() ? pr
                .getTextAlignment() : pr.addNewTextAlignment();
        STTextAlignment.Enum en = STTextAlignment.Enum
                .forInt(valign.getValue());
        textAlignment.setVal(en);
    }

    /**
     * Specifies the border which shall be displayed above a set of paragraphs
     * which have the same set of paragraph border settings.
     *
     * @return paragraphBorder - the top border for the paragraph
     * @see #setBorderTop(Borders)
     * @see Borders a list of all types of borders
     */
    public Borders getBorderTop() {
        CTPBdr border = getCTPBrd(false);
        CTBorder ct = null;
        if (border != null) {
            ct = border.getTop();
        }
        STBorder.Enum ptrn = (ct != null) ? ct.getVal() : STBorder.NONE;
        return Borders.valueOf(ptrn.intValue());
    }

    /**
     * Specifies the border which shall be displayed above a set of paragraphs
     * which have the same set of paragraph border settings.
     * <p/>
     * <p/>
     * To determine if any two adjoining paragraphs shall have an individual top
     * and bottom border or a between border, the set of borders on the two
     * adjoining paragraphs are compared. If the border information on those two
     * paragraphs is identical for all possible paragraphs borders, then the
     * between border is displayed. Otherwise, the final paragraph shall use its
     * bottom border and the following paragraph shall use its top border,
     * respectively. If this border specifies a space attribute, that value
     * determines the space above the text (ignoring any spacing above) which
     * should be left before this border is drawn, specified in points.
     * </p>
     * <p/>
     * If this element is omitted on a given paragraph, its value is determined
     * by the setting previously set at any level of the style hierarchy (i.e.
     * that previous setting remains unchanged). If this setting is never
     * specified in the style hierarchy, then no between border shall be applied
     * above identical paragraphs.
     * </p>
     * <b>This border can only be a line border.</b>
     *
     * @param border
     * @see Borders for a list of all types of borders
     */
    public void setBorderTop(Borders border) {
        CTPBdr ct = getCTPBrd(true);
        if (ct == null) {
            throw new RuntimeException("invalid paragraph state");
        }

        CTBorder pr = (ct.isSetTop()) ? ct.getTop() : ct.addNewTop();
        if (border.getValue() == Borders.NONE.getValue()) {
            ct.unsetTop();
        } else {
            pr.setVal(STBorder.Enum.forInt(border.getValue()));
        }
    }

    /**
     * Specifies the border which shall be displayed below a set of
     * paragraphs which have the same set of paragraph border settings.
     *
     * @return paragraphBorder - the bottom border for the paragraph
     * @see #setBorderBottom(Borders)
     * @see Borders a list of all types of borders
     */
    public Borders getBorderBottom() {
        CTPBdr border = getCTPBrd(false);
        CTBorder ct = null;
        if (border != null) {
            ct = border.getBottom();
        }
        STBorder.Enum ptrn = ct != null ? ct.getVal() : STBorder.NONE;
        return Borders.valueOf(ptrn.intValue());
    }

    /**
     * Specifies the border which shall be displayed below a set of paragraphs
     * which have the same set of paragraph border settings.
     * <p/>
     * To determine if any two adjoining paragraphs shall have an individual top
     * and bottom border or a between border, the set of borders on the two
     * adjoining paragraphs are compared. If the border information on those two
     * paragraphs is identical for all possible paragraphs borders, then the
     * between border is displayed. Otherwise, the final paragraph shall use its
     * bottom border and the following paragraph shall use its top border,
     * respectively. If this border specifies a space attribute, that value
     * determines the space after the bottom of the text (ignoring any space
     * below) which should be left before this border is drawn, specified in
     * points.
     * </p>
     * <p/>
     * If this element is omitted on a given paragraph, its value is determined
     * by the setting previously set at any level of the style hierarchy (i.e.
     * that previous setting remains unchanged). If this setting is never
     * specified in the style hierarchy, then no between border shall be applied
     * below identical paragraphs.
     * </p>
     * <b>This border can only be a line border.</b>
     *
     * @param border
     * @see Borders a list of all types of borders
     */
    public void setBorderBottom(Borders border) {
        CTPBdr ct = getCTPBrd(true);
        CTBorder pr = ct.isSetBottom() ? ct.getBottom() : ct.addNewBottom();
        if (border.getValue() == Borders.NONE.getValue()) {
            ct.unsetBottom();
        } else {
            pr.setVal(STBorder.Enum.forInt(border.getValue()));
        }
    }

    /**
     * Specifies the border which shall be displayed on the left side of the
     * page around the specified paragraph.
     *
     * @return ParagraphBorder - the left border for the paragraph
     * @see #setBorderLeft(Borders)
     * @see Borders for a list of all possible borders
     */
    public Borders getBorderLeft() {
        CTPBdr border = getCTPBrd(false);
        CTBorder ct = null;
        if (border != null) {
            ct = border.getLeft();
        }
        STBorder.Enum ptrn = ct != null ? ct.getVal() : STBorder.NONE;
        return Borders.valueOf(ptrn.intValue());
    }

    /**
     * Specifies the border which shall be displayed on the left side of the
     * page around the specified paragraph.
     * <p/>
     * To determine if any two adjoining paragraphs should have a left border
     * which spans the full line height or not, the left border shall be drawn
     * between the top border or between border at the top (whichever would be
     * rendered for the current paragraph), and the bottom border or between
     * border at the bottom (whichever would be rendered for the current
     * paragraph).
     * </p>
     * <p/>
     * If this element is omitted on a given paragraph, its value is determined
     * by the setting previously set at any level of the style hierarchy (i.e.
     * that previous setting remains unchanged). If this setting is never
     * specified in the style hierarchy, then no left border shall be applied.
     * </p>
     * <b>This border can only be a line border.</b>
     *
     * @param border
     * @see Borders for a list of all possible borders
     */
    public void setBorderLeft(Borders border) {
        CTPBdr ct = getCTPBrd(true);
        CTBorder pr = ct.isSetLeft() ? ct.getLeft() : ct.addNewLeft();
        if (border.getValue() == Borders.NONE.getValue()) {
            ct.unsetLeft();
        } else {
            pr.setVal(STBorder.Enum.forInt(border.getValue()));
        }
    }

    /**
     * Specifies the border which shall be displayed on the right side of the
     * page around the specified paragraph.
     *
     * @return ParagraphBorder - the right border for the paragraph
     * @see #setBorderRight(Borders)
     * @see Borders for a list of all possible borders
     */
    public Borders getBorderRight() {
        CTPBdr border = getCTPBrd(false);
        CTBorder ct = null;
        if (border != null) {
            ct = border.getRight();
        }
        STBorder.Enum ptrn = ct != null ? ct.getVal() : STBorder.NONE;
        return Borders.valueOf(ptrn.intValue());
    }

    /**
     * Specifies the border which shall be displayed on the right side of the
     * page around the specified paragraph.
     * <p/>
     * To determine if any two adjoining paragraphs should have a right border
     * which spans the full line height or not, the right border shall be drawn
     * between the top border or between border at the top (whichever would be
     * rendered for the current paragraph), and the bottom border or between
     * border at the bottom (whichever would be rendered for the current
     * paragraph).
     * </p>
     * <p/>
     * If this element is omitted on a given paragraph, its value is determined
     * by the setting previously set at any level of the style hierarchy (i.e.
     * that previous setting remains unchanged). If this setting is never
     * specified in the style hierarchy, then no right border shall be applied.
     * </p>
     * <b>This border can only be a line border.</b>
     *
     * @param border
     * @see Borders for a list of all possible borders
     */
    public void setBorderRight(Borders border) {
        CTPBdr ct = getCTPBrd(true);
        CTBorder pr = ct.isSetRight() ? ct.getRight() : ct.addNewRight();
        if (border.getValue() == Borders.NONE.getValue()) {
            ct.unsetRight();
        } else {
            pr.setVal(STBorder.Enum.forInt(border.getValue()));
        }
    }

    /**
     * Specifies the border which shall be displayed between each paragraph in a
     * set of paragraphs which have the same set of paragraph border settings.
     *
     * @return ParagraphBorder - the between border for the paragraph
     * @see #setBorderBetween(Borders)
     * @see Borders for a list of all possible borders
     */
    public Borders getBorderBetween() {
        CTPBdr border = getCTPBrd(false);
        CTBorder ct = null;
        if (border != null) {
            ct = border.getBetween();
        }
        STBorder.Enum ptrn = ct != null ? ct.getVal() : STBorder.NONE;
        return Borders.valueOf(ptrn.intValue());
    }

    /**
     * Specifies the border which shall be displayed between each paragraph in a
     * set of paragraphs which have the same set of paragraph border settings.
     * <p/>
     * To determine if any two adjoining paragraphs should have a between border
     * or an individual top and bottom border, the set of borders on the two
     * adjoining paragraphs are compared. If the border information on those two
     * paragraphs is identical for all possible paragraphs borders, then the
     * between border is displayed. Otherwise, each paragraph shall use its
     * bottom and top border, respectively. If this border specifies a space
     * attribute, that value is ignored - this border is always located at the
     * bottom of each paragraph with an identical following paragraph, taking
     * into account any space after the line pitch.
     * </p>
     * <p/>
     * If this element is omitted on a given paragraph, its value is determined
     * by the setting previously set at any level of the style hierarchy (i.e.
     * that previous setting remains unchanged). If this setting is never
     * specified in the style hierarchy, then no between border shall be applied
     * between identical paragraphs.
     * </p>
     * <b>This border can only be a line border.</b>
     *
     * @param border
     * @see Borders for a list of all possible borders
     */
    public void setBorderBetween(Borders border) {
        CTPBdr ct = getCTPBrd(true);
        CTBorder pr = ct.isSetBetween() ? ct.getBetween() : ct.addNewBetween();
        if (border.getValue() == Borders.NONE.getValue()) {
            ct.unsetBetween();
        } else {
            pr.setVal(STBorder.Enum.forInt(border.getValue()));
        }
    }

    /**
     * Specifies that when rendering this document in a paginated
     * view, the contents of this paragraph are rendered on the start of a new
     * page in the document.
     * <p/>
     * If this element is omitted on a given paragraph,
     * its value is determined by the setting previously set at any level of the
     * style hierarchy (i.e. that previous setting remains unchanged). If this
     * setting is never specified in the style hierarchy, then this property
     * shall not be applied. Since the paragraph is specified to start on a new
     * page, it begins page two even though it could have fit on page one.
     * </p>
     *
     * @return boolean - if page break is set
     */
    public boolean isPageBreak() {
        CTPPr ppr = getCTPPr();
        CTOnOff ctPageBreak = ppr.isSetPageBreakBefore() ? ppr
                .getPageBreakBefore() : null;
        if (ctPageBreak != null
                && ctPageBreak.getVal().intValue() == STOnOff.INT_TRUE) {
            return true;
        }
        return false;
    }

    /**
     * Specifies that when rendering this document in a paginated
     * view, the contents of this paragraph are rendered on the start of a new
     * page in the document.
     * <p/>
     * If this element is omitted on a given paragraph,
     * its value is determined by the setting previously set at any level of the
     * style hierarchy (i.e. that previous setting remains unchanged). If this
     * setting is never specified in the style hierarchy, then this property
     * shall not be applied. Since the paragraph is specified to start on a new
     * page, it begins page two even though it could have fit on page one.
     * </p>
     *
     * @param pageBreak -
     *                  boolean value
     */
    public void setPageBreak(boolean pageBreak) {
        CTPPr ppr = getCTPPr();
        CTOnOff ctPageBreak = ppr.isSetPageBreakBefore() ? ppr
                .getPageBreakBefore() : ppr.addNewPageBreakBefore();
        if (pageBreak) {
            ctPageBreak.setVal(STOnOff.TRUE);
        } else {
            ctPageBreak.setVal(STOnOff.FALSE);
        }
    }

    /**
     * Specifies the spacing that should be added after the last line in this
     * paragraph in the document in absolute units.
     *
     * @return int - value representing the spacing after the paragraph
     */
    public int getSpacingAfter() {
        CTSpacing spacing = getCTSpacing(false);
        return (spacing != null && spacing.isSetAfter()) ? spacing.getAfter().intValue() : -1;
    }

    /**
     * Specifies the spacing that should be added after the last line in this
     * paragraph in the document in absolute units.
     * <p/>
     * If the afterLines attribute or the afterAutoSpacing attribute is also
     * specified, then this attribute value is ignored.
     * </p>
     *
     * @param spaces -
     *               a positive whole number, whose contents consist of a
     *               measurement in twentieths of a point.
     */
    public void setSpacingAfter(int spaces) {
        CTSpacing spacing = getCTSpacing(true);
        if (spacing != null) {
            BigInteger bi = new BigInteger("" + spaces);
            spacing.setAfter(bi);
        }

    }

    /**
     * Specifies the spacing that should be added after the last line in this
     * paragraph in the document in absolute units.
     *
     * @return int - value representing the spacing after the paragraph
     * @see #setSpacingAfterLines(int)
     */
    public int getSpacingAfterLines() {
        CTSpacing spacing = getCTSpacing(false);
        return (spacing != null && spacing.isSetAfterLines()) ? spacing.getAfterLines().intValue() : -1;
    }

    /**
     * Specifies the spacing that should be added after the last line in this
     * paragraph in the document in line units.
     * <b>The value of this attribute is
     * specified in one hundredths of a line.
     * </b>
     * <p/>
     * If the afterAutoSpacing attribute
     * is also specified, then this attribute value is ignored. If this setting
     * is never specified in the style hierarchy, then its value shall be zero
     * (if needed)
     * </p>
     *
     * @param spaces -
     *               a positive whole number, whose contents consist of a
     *               measurement in hundredths of a line
     */
    public void setSpacingAfterLines(int spaces) {
        CTSpacing spacing = getCTSpacing(true);
        BigInteger bi = new BigInteger("" + spaces);
        spacing.setAfterLines(bi);
    }

    /**
     * Specifies the spacing that should be added above the first line in this
     * paragraph in the document in absolute units.
     *
     * @return the spacing that should be added above the first line
     * @see #setSpacingBefore(int)
     */
    public int getSpacingBefore() {
        CTSpacing spacing = getCTSpacing(false);
        return (spacing != null && spacing.isSetBefore()) ? spacing.getBefore().intValue() : -1;
    }

    /**
     * Specifies the spacing that should be added above the first line in this
     * paragraph in the document in absolute units.
     * <p/>
     * If the beforeLines attribute or the beforeAutoSpacing attribute is also
     * specified, then this attribute value is ignored.
     * </p>
     *
     * @param spaces
     */
    public void setSpacingBefore(int spaces) {
        CTSpacing spacing = getCTSpacing(true);
        BigInteger bi = new BigInteger("" + spaces);
        spacing.setBefore(bi);
    }

    /**
     * Specifies the spacing that should be added before the first line in this paragraph in the
     * document in line units.
     * The value of this attribute is specified in one hundredths of a line.
     *
     * @return the spacing that should be added before the first line in this paragraph
     * @see #setSpacingBeforeLines(int)
     */
    public int getSpacingBeforeLines() {
        CTSpacing spacing = getCTSpacing(false);
        return (spacing != null && spacing.isSetBeforeLines()) ? spacing.getBeforeLines().intValue() : -1;
    }

    /**
     * Specifies the spacing that should be added before the first line in this
     * paragraph in the document in line units. <b> The value of this attribute
     * is specified in one hundredths of a line. </b>
     * <p/>
     * If the beforeAutoSpacing attribute is also specified, then this attribute
     * value is ignored. If this setting is never specified in the style
     * hierarchy, then its value shall be zero.
     * </p>
     *
     * @param spaces
     */
    public void setSpacingBeforeLines(int spaces) {
        CTSpacing spacing = getCTSpacing(true);
        BigInteger bi = new BigInteger("" + spaces);
        spacing.setBeforeLines(bi);
    }

    /**
     * Specifies how the spacing between lines is calculated as stored in the
     * line attribute. If this attribute is omitted, then it shall be assumed to
     * be of a value auto if a line attribute value is present.
     *
     * @return rule
     * @see LineSpacingRule
     * @see #setSpacingLineRule(LineSpacingRule)
     */
    public LineSpacingRule getSpacingLineRule() {
        CTSpacing spacing = getCTSpacing(false);
        return (spacing != null && spacing.isSetLineRule()) ? LineSpacingRule.valueOf(spacing
                .getLineRule().intValue()) : LineSpacingRule.AUTO;
    }

    /**
     * Specifies how the spacing between lines is calculated as stored in the
     * line attribute. If this attribute is omitted, then it shall be assumed to
     * be of a value auto if a line attribute value is present.
     *
     * @param rule
     * @see LineSpacingRule
     */
     // TODO Fix this to convert line to equivalent value, or deprecate this in
     //      favor of setSpacingLine(double, LineSpacingRule)
    public void setSpacingLineRule(LineSpacingRule rule) {
        CTSpacing spacing = getCTSpacing(true);
        spacing.setLineRule(STLineSpacingRule.Enum.forInt(rule.getValue()));
    }

    /**
     * Return the spacing between lines of a paragraph. The units of the return value depends on the
     * {@link LineSpacingRule}. If AUTO, the return value is in lines, otherwise the return
     * value is in points
     *
     * @return a double specifying points or lines.
     */
    public double getSpacingBetween() {
        CTSpacing spacing = getCTSpacing(false);
        if (spacing == null || !spacing.isSetLine()) {
            return -1;
        } else if (spacing.getLineRule() == null || spacing.getLineRule() == STLineSpacingRule.AUTO) {
            BigInteger[] val = spacing.getLine().divideAndRemainder(BigInteger.valueOf(240L));
            return val[0].doubleValue() + (val[1].doubleValue() / 240L);
        }
        BigInteger[] val = spacing.getLine().divideAndRemainder(BigInteger.valueOf(20L));
        return val[0].doubleValue() + (val[1].doubleValue() / 20L);        
    }

    /**
     * Sets the spacing between lines in a paragraph
     *
     * @param spacing - A double specifying spacing in inches or lines. If rule is
     *                  AUTO, then spacing is in lines. Otherwise spacing is in points.
     * @param rule - {@link LineSpacingRule} indicating how spacing is interpreted. If
     *               AUTO, then spacing value is in lines, and the height depends on the
     *               font size. If AT_LEAST, then spacing value is in inches, and is the
     *               minimum size of the line. If the line height is taller, then the
     *               line expands to match. If EXACT, then spacing is the exact line
     *               height. If the text is taller than the line height, then it is 
     *               clipped at the top. 
     */
    public void setSpacingBetween(double spacing, LineSpacingRule rule) {
        CTSpacing ctSp = getCTSpacing(true);
        switch (rule) {
        case AUTO:
            ctSp.setLine(new BigInteger(String.valueOf(Math.round(spacing * 240.0))));
            break;
        default:
            ctSp.setLine(new BigInteger(String.valueOf(Math.round(spacing * 20.0))));
        }
        ctSp.setLineRule(STLineSpacingRule.Enum.forInt(rule.getValue()));
    }
    
    /**
     * Sets the spacing between lines in a paragraph
     *
     * @param spacing - A double specifying spacing in lines.
     */
    public void setSpacingBetween(double spacing) {
        setSpacingBetween(spacing, LineSpacingRule.AUTO);
    }
    
    /**
     * Specifies the indentation which shall be placed between the left text
     * margin for this paragraph and the left edge of that paragraph's content
     * in a left to right paragraph, and the right text margin and the right
     * edge of that paragraph's text in a right to left paragraph
     * <p/>
     * If this attribute is omitted, its value shall be assumed to be zero.
     * Negative values are defined such that the text is moved past the text margin,
     * positive values move the text inside the text margin.
     * </p>
     *
     * @return indentation or null if indentation is not set
     */
    public int getIndentationLeft() {
        CTInd indentation = getCTInd(false);
        return (indentation != null && indentation.isSetLeft()) ? indentation.getLeft().intValue()
                : -1;
    }

    /**
     * Specifies the indentation which shall be placed between the left text
     * margin for this paragraph and the left edge of that paragraph's content
     * in a left to right paragraph, and the right text margin and the right
     * edge of that paragraph's text in a right to left paragraph
     * <p/>
     * If this attribute is omitted, its value shall be assumed to be zero.
     * Negative values are defined such that the text is moved past the text margin,
     * positive values move the text inside the text margin.
     * </p>
     *
     * @param indentation
     */
    public void setIndentationLeft(int indentation) {
        CTInd indent = getCTInd(true);
        BigInteger bi = new BigInteger("" + indentation);
        indent.setLeft(bi);
    }

    /**
     * Specifies the indentation which shall be placed between the right text
     * margin for this paragraph and the right edge of that paragraph's content
     * in a left to right paragraph, and the right text margin and the right
     * edge of that paragraph's text in a right to left paragraph
     * <p/>
     * If this attribute is omitted, its value shall be assumed to be zero.
     * Negative values are defined such that the text is moved past the text margin,
     * positive values move the text inside the text margin.
     * </p>
     *
     * @return indentation or null if indentation is not set
     */

    public int getIndentationRight() {
        CTInd indentation = getCTInd(false);
        return (indentation != null && indentation.isSetRight()) ? indentation.getRight().intValue()
                : -1;
    }

    /**
     * Specifies the indentation which shall be placed between the right text
     * margin for this paragraph and the right edge of that paragraph's content
     * in a left to right paragraph, and the right text margin and the right
     * edge of that paragraph's text in a right to left paragraph
     * <p/>
     * If this attribute is omitted, its value shall be assumed to be zero.
     * Negative values are defined such that the text is moved past the text margin,
     * positive values move the text inside the text margin.
     * </p>
     *
     * @param indentation
     */
    public void setIndentationRight(int indentation) {
        CTInd indent = getCTInd(true);
        BigInteger bi = new BigInteger("" + indentation);
        indent.setRight(bi);
    }

    /**
     * Specifies the indentation which shall be removed from the first line of
     * the parent paragraph, by moving the indentation on the first line back
     * towards the beginning of the direction of text flow.
     * This indentation is
     * specified relative to the paragraph indentation which is specified for
     * all other lines in the parent paragraph.
     * The firstLine and hanging
     * attributes are mutually exclusive, if both are specified, then the
     * firstLine value is ignored.
     *
     * @return indentation or null if indentation is not set
     */
    public int getIndentationHanging() {
        CTInd indentation = getCTInd(false);
        return (indentation != null && indentation.isSetHanging()) ? indentation.getHanging().intValue() : -1;
    }

    /**
     * Specifies the indentation which shall be removed from the first line of
     * the parent paragraph, by moving the indentation on the first line back
     * towards the beginning of the direction of text flow.
     * This indentation is specified relative to the paragraph indentation which is specified for
     * all other lines in the parent paragraph.
     * <p/>
     * The firstLine and hanging attributes are mutually exclusive, if both are specified, then the
     * firstLine value is ignored.
     * </p>
     *
     * @param indentation
     */

    public void setIndentationHanging(int indentation) {
        CTInd indent = getCTInd(true);
        BigInteger bi = new BigInteger("" + indentation);
        indent.setHanging(bi);
    }

    /**
     * Specifies the additional indentation which shall be applied to the first
     * line of the parent paragraph. This additional indentation is specified
     * relative to the paragraph indentation which is specified for all other
     * lines in the parent paragraph.
     * The firstLine and hanging attributes are
     * mutually exclusive, if both are specified, then the firstLine value is
     * ignored.
     * If the firstLineChars attribute is also specified, then this
     * value is ignored.
     * If this attribute is omitted, then its value shall be
     * assumed to be zero (if needed).
     *
     * @return indentation or null if indentation is not set
     */
    public int getIndentationFirstLine() {
        CTInd indentation = getCTInd(false);
        return (indentation != null && indentation.isSetFirstLine()) ? indentation.getFirstLine().intValue()
                : -1;
    }

    /**
     * Specifies the additional indentation which shall be applied to the first
     * line of the parent paragraph. This additional indentation is specified
     * relative to the paragraph indentation which is specified for all other
     * lines in the parent paragraph.
     * The firstLine and hanging attributes are
     * mutually exclusive, if both are specified, then the firstLine value is
     * ignored.
     * If the firstLineChars attribute is also specified, then this
     * value is ignored. If this attribute is omitted, then its value shall be
     * assumed to be zero (if needed).
     *
     * @param indentation
     */
    public void setIndentationFirstLine(int indentation) {
        CTInd indent = getCTInd(true);
        BigInteger bi = new BigInteger("" + indentation);
        indent.setFirstLine(bi);
    }

    @Override
    public int getIndentFromLeft() {
        return getIndentationLeft();
    }

    @Override
    public void setIndentFromLeft(int dxaLeft) {
        setIndentationLeft(dxaLeft);
    }

    @Override
    public int getIndentFromRight() {
        return getIndentationRight();
    }

    @Override
    public void setIndentFromRight(int dxaRight) {
        setIndentationRight(dxaRight);
    }

    @Override
    public int getFirstLineIndent() {
        return getIndentationFirstLine();
    }

    @Override
    public void setFirstLineIndent(int first) {
        setIndentationFirstLine(first);
    }

    /**
     * This element specifies whether a consumer shall break Latin text which
     * exceeds the text extents of a line by breaking the word across two lines
     * (breaking on the character level) or by moving the word to the following
     * line (breaking on the word level).
     *
     * @return boolean
     */
    @Override
    public boolean isWordWrapped() {
        CTOnOff wordWrap = getCTPPr().isSetWordWrap() ? getCTPPr()
                .getWordWrap() : null;
        if (wordWrap != null) {
            return (wordWrap.getVal() == STOnOff.ON
                    || wordWrap.getVal() == STOnOff.TRUE || wordWrap.getVal() == STOnOff.X_1) ? true
                    : false;
        }
        return false;
    }

    /**
     * This element specifies whether a consumer shall break Latin text which
     * exceeds the text extents of a line by breaking the word across two lines
     * (breaking on the character level) or by moving the word to the following
     * line (breaking on the word level).
     *
     * @param wrap - boolean
     */
    @Override
    public void setWordWrapped(boolean wrap) {
        CTOnOff wordWrap = getCTPPr().isSetWordWrap() ? getCTPPr()
                .getWordWrap() : getCTPPr().addNewWordWrap();
        if (wrap) {
            wordWrap.setVal(STOnOff.TRUE);
        } else {
            wordWrap.unsetVal();
        }
    }

    public boolean isWordWrap() {
        return isWordWrapped();
    }

    @Deprecated
    public void setWordWrap(boolean wrap) {
        setWordWrapped(wrap);
    }

    /**
     * @return the style of the paragraph
     */
    public String getStyle() {
        CTPPr pr = getCTPPr();
        CTString style = pr.isSetPStyle() ? pr.getPStyle() : null;
        return style != null ? style.getVal() : null;
    }

    /**
     * This method provides a style to the paragraph
     * This is useful when, e.g. an Heading style has to be assigned
     *
     * @param newStyle
     */
    public void setStyle(String newStyle) {
        CTPPr pr = getCTPPr();
        CTString style = pr.getPStyle() != null ? pr.getPStyle() : pr.addNewPStyle();
        style.setVal(newStyle);
    }

    /**
     * Get a <b>copy</b> of the currently used CTPBrd, if none is used, return
     * a new instance.
     */
    private CTPBdr getCTPBrd(boolean create) {
        CTPPr pr = getCTPPr();
        CTPBdr ct = pr.isSetPBdr() ? pr.getPBdr() : null;
        if (create && ct == null) {
            ct = pr.addNewPBdr();
        }
        return ct;
    }

    /**
     * Get a <b>copy</b> of the currently used CTSpacing, if none is used,
     * return a new instance.
     */
    private CTSpacing getCTSpacing(boolean create) {
        CTPPr pr = getCTPPr();
        CTSpacing ct = pr.getSpacing() == null ? null : pr.getSpacing();
        if (create && ct == null) {
            ct = pr.addNewSpacing();
        }
        return ct;
    }

    /**
     * Get a <b>copy</b> of the currently used CTPInd, if none is used, return
     * a new instance.
     */
    private CTInd getCTInd(boolean create) {
        CTPPr pr = getCTPPr();
        CTInd ct = pr.getInd() == null ? null : pr.getInd();
        if (create && ct == null) {
            ct = pr.addNewInd();
        }
        return ct;
    }

    /**
     * Get a <b>copy</b> of the currently used CTPPr, if none is used, return
     * a new instance.
     */
    private CTPPr getCTPPr() {
        CTPPr pr = paragraph.getPPr() == null ? paragraph.addNewPPr()
                : paragraph.getPPr();
        return pr;
    }


    /**
     * add a new run at the end of the position of
     * the content of parameter run
     *
     * @param run
     */
    protected void addRun(CTR run) {
        int pos;
        pos = paragraph.sizeOfRArray();
        paragraph.addNewR();
        paragraph.setRArray(pos, run);
    }

    /**
     * Appends a new run to this paragraph
     *
     * @return a new text run
     */
    public XWPFRun createRun() {
        XWPFRun xwpfRun = new XWPFRun(paragraph.addNewR(), (IRunBody)this);
        runs.add(xwpfRun);
        iruns.add(xwpfRun);
        return xwpfRun;
    }

    /**
     * insert a new Run in RunArray
     *
     * @param pos The position at which the new run should be added.
     * 
     * @return the inserted run or null if the given pos is out of bounds.
     */
    public XWPFRun insertNewRun(int pos) {
        if (pos >= 0 && pos <= runs.size()) {
            // calculate the correct pos as our run/irun list contains
            // hyperlinks
            // and fields so it is different to the paragraph R array.
            int rPos = 0;
            for (int i = 0; i < pos; i++) {
                XWPFRun currRun = runs.get(i);
                if (!(currRun instanceof XWPFHyperlinkRun
                        || currRun instanceof XWPFFieldRun)) {
                    rPos++;
                }
            }

            CTR ctRun = paragraph.insertNewR(rPos);
            XWPFRun newRun = new XWPFRun(ctRun, (IRunBody) this);

            // To update the iruns, find where we're going
            // in the normal runs, and go in there
            int iPos = iruns.size();
            if (pos < runs.size()) {
                XWPFRun oldAtPos = runs.get(pos);
                int oldAt = iruns.indexOf(oldAtPos);
                if (oldAt != -1) {
                    iPos = oldAt;
                }
            }
            iruns.add(iPos, newRun);

            // Runs itself is easy to update
            runs.add(pos, newRun);

            return newRun;
        }

        return null;
    }
    // TODO Add methods to allow adding a HyperlinkRun or a FieldRun

    /**
     * this methods parse the paragraph and search for the string searched.
     * If it finds the string, it will return true and the position of the String
     * will be saved in the parameter startPos.
     *
     * @param searched
     * @param startPos
     */
    public TextSegement searchText(String searched, PositionInParagraph startPos) {
        int startRun = startPos.getRun(),
            startText = startPos.getText(),
            startChar = startPos.getChar();
        int beginRunPos = 0, candCharPos = 0;
        boolean newList = false;
        
        CTR[] rArray = paragraph.getRArray();
        for (int runPos = startRun; runPos < rArray.length; runPos++) {
            int beginTextPos = 0, beginCharPos = 0, textPos = 0, charPos = 0;
            CTR ctRun = rArray[runPos];
            XmlCursor c = ctRun.newCursor();
            c.selectPath("./*");
            try {
                while (c.toNextSelection()) {
                    XmlObject o = c.getObject();
                    if (o instanceof CTText) {
                        if (textPos >= startText) {
                            String candidate = ((CTText) o).getStringValue();
                            if (runPos == startRun) {
                                charPos = startChar;
                            } else {
                                charPos = 0;
                            }
    
                            for (; charPos < candidate.length(); charPos++) {
                                if ((candidate.charAt(charPos) == searched.charAt(0)) && (candCharPos == 0)) {
                                    beginTextPos = textPos;
                                    beginCharPos = charPos;
                                    beginRunPos = runPos;
                                    newList = true;
                                }
                                if (candidate.charAt(charPos) == searched.charAt(candCharPos)) {
                                    if (candCharPos + 1 < searched.length()) {
                                        candCharPos++;
                                    } else if (newList) {
                                        TextSegement segement = new TextSegement();
                                        segement.setBeginRun(beginRunPos);
                                        segement.setBeginText(beginTextPos);
                                        segement.setBeginChar(beginCharPos);
                                        segement.setEndRun(runPos);
                                        segement.setEndText(textPos);
                                        segement.setEndChar(charPos);
                                        return segement;
                                    }
                                } else {
                                    candCharPos = 0;
                                }
                            }
                        }
                        textPos++;
                    } else if (o instanceof CTProofErr) {
                        c.removeXml();
                    } else if (o instanceof CTRPr) {
                        //do nothing
                    } else {
                        candCharPos = 0;
                    }
                }
            } finally {
                c.dispose();
            }
        }
        return null;
    }

    /**
     * get a Text
     *
     * @param segment
     */
    public String getText(TextSegement segment) {
        int runBegin = segment.getBeginRun();
        int textBegin = segment.getBeginText();
        int charBegin = segment.getBeginChar();
        int runEnd = segment.getEndRun();
        int textEnd = segment.getEndText();
        int charEnd = segment.getEndChar();
        StringBuilder out = new StringBuilder();
        CTR[] rArray = paragraph.getRArray();
        for (int i = runBegin; i <= runEnd; i++) {
            CTText[] tArray = rArray[i].getTArray();
            int startText = 0, endText = tArray.length - 1;
            if (i == runBegin) {
                startText = textBegin;
            }
            if (i == runEnd) {
                endText = textEnd;
            }
            for (int j = startText; j <= endText; j++) {
                String tmpText = tArray[j].getStringValue();
                int startChar = 0, endChar = tmpText.length() - 1;
                if ((j == textBegin) && (i == runBegin)) {
                    startChar = charBegin;
                }
                if ((j == textEnd) && (i == runEnd)) {
                    endChar = charEnd;
                }
                out.append(tmpText.substring(startChar, endChar + 1));
            }
        }
        return out.toString();
    }

    /**
     * removes a Run at the position pos in the paragraph
     *
     * @param pos
     * @return true if the run was removed
     */
    public boolean removeRun(int pos) {
        if (pos >= 0 && pos < runs.size()) {
            // Remove the run from our high level lists
            XWPFRun run = runs.get(pos);
            if (run instanceof XWPFHyperlinkRun ||
                run instanceof XWPFFieldRun) {
                // TODO Add support for removing these kinds of nested runs,
                //  which aren't on the CTP -> R array, but CTP -> XXX -> R array
                throw new IllegalArgumentException("Removing Field or Hyperlink runs not yet supported");
            }
            runs.remove(pos);
            iruns.remove(run);
            // Remove the run from the low-level XML
            //calculate the correct pos as our run/irun list contains hyperlinks and fields so is different to the paragraph R array.
            int rPos = 0;
            for(int i=0;i<pos;i++) {
              XWPFRun currRun = runs.get(i);
              if(!(currRun instanceof XWPFHyperlinkRun || currRun instanceof XWPFFieldRun)) {
                rPos++;
              }
            }
            getCTP().removeR(rPos);
            return true;
        }
        return false;
    }

    /**
     * returns the type of the BodyElement Paragraph
     *
     * @see org.apache.poi.xwpf.usermodel.IBodyElement#getElementType()
     */
    @Override
    public BodyElementType getElementType() {
        return BodyElementType.PARAGRAPH;
    }

    @Override
    public IBody getBody() {
        return part;
    }

    /**
     * returns the part of the bodyElement
     *
     * @see org.apache.poi.xwpf.usermodel.IBody#getPart()
     */
    @Override
    public POIXMLDocumentPart getPart() {
        if (part != null) {
            return part.getPart();
        }
        return null;
    }

    /**
     * returns the partType of the bodyPart which owns the bodyElement
     *
     * @see org.apache.poi.xwpf.usermodel.IBody#getPartType()
     */
    @Override
    public BodyType getPartType() {
        return part.getPartType();
    }

    /**
     * adds a new Run to the Paragraph
     *
     * @param r
     */
    public void addRun(XWPFRun r) {
        if (!runs.contains(r)) {
            runs.add(r);
        }
    }

    /**
     * return the XWPFRun-Element which owns the CTR run-Element
     *
     * @param r
     */
    public XWPFRun getRun(CTR r) {
        for (int i = 0; i < getRuns().size(); i++) {
            if (getRuns().get(i).getCTR() == r) {
                return getRuns().get(i);
            }
        }
        return null;
    }
}
