1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885 |
- /* ====================================================================
- 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 java.util.function.Function;
-
- import org.apache.poi.ooxml.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 StringBuilder footnoteText = new StringBuilder(64);
-
- 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<>();
- iruns = new ArrayList<>();
- 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(": ");
- XWPFAbstractFootnoteEndnote footnote =
- ftn.getDomNode().getLocalName().equals("footnoteReference") ?
- document.getFootnoteByID(ftn.getId().intValue()) :
- document.getEndnoteByID(ftn.getId().intValue());
- if (null != footnote) {
- boolean first = true;
- for (XWPFParagraph p : footnote.getParagraphs()) {
- if (!first) {
- footnoteText.append("\n");
- }
- first = false;
- footnoteText.append(p.getText());
- }
- } else {
- footnoteText.append("!!! End note with ID \"").append(ftn.getId()).append("\" not found in document.");
- }
- 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);
- }
- if (o instanceof CTRunTrackChange) {
- // add all the insertions as text
- for (CTRunTrackChange change : ((CTRunTrackChange) o).getInsArray()) {
- buildRunsInOrderFromXml(change);
- }
- }
- }
- 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() {
- StringBuilder out = new StringBuilder(64);
- 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().getDelTextArray().length == 0) {
- out.append(xRun);
- }
- } else if (run instanceof XWPFSDT) {
- out.append(((XWPFSDT) run).getContent().getText());
- } else {
- out.append(run);
- }
- }
- 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);
- }
-
- /**
- * setNumILvl of Paragraph
- *
- * @param iLvl
- * @since 4.1.2
- */
- public void setNumILvl(BigInteger iLvl) {
- if (paragraph.getPPr() == null) {
- paragraph.addNewPPr();
- }
- if (paragraph.getPPr().getNumPr() == null) {
- paragraph.getPPr().addNewNumPr();
- }
- if (paragraph.getPPr().getNumPr().getIlvl() == null) {
- paragraph.getPPr().getNumPr().addNewIlvl();
- }
- paragraph.getPPr().getNumPr().getIlvl().setVal(iLvl);
- }
-
- /**
- * 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();
- }
- }
- }
- 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;
- }
-
- /**
- * Indicates whether this paragraph should be kept on the same page as the next one.
- *
- * @since POI 4.1.1
- */
- public boolean isKeepNext() {
- if (getCTP() != null && getCTP().getPPr() != null && getCTP().getPPr().isSetKeepNext()) {
- return getCTP().getPPr().getKeepNext().getVal() == STOnOff.ON;
- }
- return false;
- }
-
- /**
- * Sets this paragraph to be kept on the same page as the next one or not.
- *
- * @since POI 4.1.1
- */
- public void setKeepNext(boolean keepNext) {
- CTOnOff state = CTOnOff.Factory.newInstance();
- state.setVal(keepNext ? STOnOff.ON : STOnOff.OFF);
- getCTP().getPPr().setKeepNext(state);
- }
-
- /**
- * Returns the text of the paragraph, but not of any objects in the
- * paragraph
- */
- public String getParagraphText() {
- StringBuilder out = new StringBuilder(64);
- for (XWPFRun run : runs) {
- out.append(run);
- }
- return out.toString();
- }
-
- /**
- * Returns any text from any suitable pictures in the paragraph
- */
- public String getPictureText() {
- StringBuilder out = new StringBuilder(64);
- 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 one of the defined Border styles, see {@link Borders}
- * @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 one of the defined Border styles, see {@link Borders}
- * @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 one of the defined Border styles, see {@link Borders}
- * @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 one of the defined Border styles, see {@link Borders}
- * @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 one of the defined Border styles, see {@link Borders}
- * @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() {
- final CTPPr ppr = getCTPPr();
- final CTOnOff ctPageBreak = ppr.isSetPageBreakBefore() ? ppr.getPageBreakBefore() : null;
- if (ctPageBreak == null) {
- return false;
- }
- return isTruelike(ctPageBreak.getVal());
- }
-
- private static boolean isTruelike(final STOnOff.Enum value) {
- if (value == null) {
- return false;
- }
- switch (value.intValue()) {
- case STOnOff.INT_TRUE:
- case STOnOff.INT_X_1:
- case STOnOff.INT_ON:
- return true;
- /*STOnOff.INT_FALSE:
- STOnOff.INT_X_0:
- STOnOff.INT_OFF:*/
- default:
- 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(Integer.toString(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(Integer.toString(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 a positive whole number, whose contents consist of a
- * measurement in twentieths of a point.
- */
- public void setSpacingBefore(int spaces) {
- CTSpacing spacing = getCTSpacing(true);
- BigInteger bi = new BigInteger(Integer.toString(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 a positive whole number, whose contents consist of a
- * measurement in hundredths of a line
- */
- public void setSpacingBeforeLines(int spaces) {
- CTSpacing spacing = getCTSpacing(true);
- BigInteger bi = new BigInteger(Integer.toString(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 one of the defined rules, see {@link LineSpacingRule}
- * @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);
- if (rule == LineSpacingRule.AUTO) {
- ctSp.setLine(new BigInteger(String.valueOf(Math.round(spacing * 240.0))));
- } else {
- 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 in twips 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 in twips
- */
- public void setIndentationLeft(int indentation) {
- CTInd indent = getCTInd(true);
- BigInteger bi = new BigInteger(Integer.toString(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 in twips 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 in twips
- */
- public void setIndentationRight(int indentation) {
- CTInd indent = getCTInd(true);
- BigInteger bi = new BigInteger(Integer.toString(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 in twips 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 in twips
- */
-
- public void setIndentationHanging(int indentation) {
- CTInd indent = getCTInd(true);
- BigInteger bi = new BigInteger(Integer.toString(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 in twips 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 in twips
- */
- public void setIndentationFirstLine(int indentation) {
- CTInd indent = getCTInd(true);
- BigInteger bi = new BigInteger(Integer.toString(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 isTruelike(wordWrap.getVal());
- }
- 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;
- }
-
- /**
- * Set the style ID for the paragraph
- *
- * @param styleId ID (not name) of the style to set for the paragraph, e.g. "Heading1" (not "Heading 1").
- */
- public void setStyle(String styleId) {
- CTPPr pr = getCTPPr();
- CTString style = pr.getPStyle() != null ? pr.getPStyle() : pr.addNewPStyle();
- style.setVal(styleId);
- }
-
- /**
- * 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();
- 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();
- 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() {
- return paragraph.getPPr() == null ? paragraph.addNewPPr()
- : paragraph.getPPr();
- }
-
-
- /**
- * 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;
- }
-
- /**
- * Appends a new hyperlink run to this paragraph
- *
- * @return a new hyperlink run
- * @since POI 4.1.1
- */
- public XWPFHyperlinkRun createHyperlinkRun(String uri) {
- // Create a relationship ID for this link.
- String rId = getPart().getPackagePart().addExternalRelationship(
- uri, XWPFRelation.HYPERLINK.getRelation()
- ).getId();
-
- // Create the run.
- CTHyperlink ctHyperLink = getCTP().addNewHyperlink();
- ctHyperLink.setId(rId);
- ctHyperLink.addNewR();
-
- // Append this run to the paragraph.
- XWPFHyperlinkRun link = new XWPFHyperlinkRun(ctHyperLink, ctHyperLink.getRArray(0), this);
- runs.add(link);
- iruns.add(link);
- return link;
- }
-
- /**
- * Appends a new field run to this paragraph
- *
- * @return a new field run
- */
- public XWPFFieldRun createFieldRun() {
- CTSimpleField ctSimpleField = paragraph.addNewFldSimple();
- XWPFFieldRun newRun = new XWPFFieldRun(ctSimpleField, ctSimpleField.addNewR(), this);
- runs.add(newRun);
- iruns.add(newRun);
- return newRun;
- }
-
- /**
- * insert a new Run in all runs
- *
- * @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 == runs.size()) {
- return createRun();
- }
- return insertNewProvidedRun(pos, newCursor -> {
- String uri = CTR.type.getName().getNamespaceURI();
- String localPart = "r";
- // creates a new run, cursor is positioned inside the new
- // element
- newCursor.beginElement(localPart, uri);
- // move the cursor to the START token to the run just created
- newCursor.toParent();
- CTR r = (CTR) newCursor.getObject();
- return new XWPFRun(r, (IRunBody)this);
- });
- }
-
- /**
- * insert a new hyperlink Run in all runs
- *
- * @param pos The position at which the new run should be added.
- * @param uri hyperlink uri
- *
- * @return the inserted run or null if the given pos is out of bounds.
- */
- public XWPFHyperlinkRun insertNewHyperlinkRun(int pos, String uri) {
- if (pos == runs.size()) {
- return createHyperlinkRun(uri);
- }
- XWPFHyperlinkRun newRun = insertNewProvidedRun(pos, newCursor -> {
- String namespaceURI = CTHyperlink.type.getName().getNamespaceURI();
- String localPart = "hyperlink";
- newCursor.beginElement(localPart, namespaceURI);
- // move the cursor to the START token to the hyperlink just created
- newCursor.toParent();
- CTHyperlink ctHyperLink = (CTHyperlink) newCursor.getObject();
- return new XWPFHyperlinkRun(ctHyperLink, ctHyperLink.addNewR(), this);
- });
-
- if (newRun != null) {
- String rId = getPart().getPackagePart().addExternalRelationship(
- uri, XWPFRelation.HYPERLINK.getRelation()
- ).getId();
- newRun.getCTHyperlink().setId(rId);
- }
-
- return newRun;
- }
-
- /**
- * insert a new field Run in all runs
- *
- * @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 XWPFFieldRun insertNewFieldRun(int pos) {
- if (pos == runs.size()) {
- return createFieldRun();
- }
- return insertNewProvidedRun(pos, newCursor -> {
- String uri = CTSimpleField.type.getName().getNamespaceURI();
- String localPart = "fldSimple";
- newCursor.beginElement(localPart, uri);
- // move the cursor to the START token to the field just created
- newCursor.toParent();
- CTSimpleField ctSimpleField = (CTSimpleField) newCursor.getObject();
- return new XWPFFieldRun(ctSimpleField, ctSimpleField.addNewR(), this);
- });
- }
-
- /**
- * insert a new run provided by in all runs
- *
- * @param <T> XWPFRun or XWPFHyperlinkRun or XWPFFieldRun
- * @param pos The position at which the new run should be added.
- * @param provider provide a new run at position of the given cursor.
- * @return the inserted run or null if the given pos is out of bounds.
- */
- private <T extends XWPFRun> T insertNewProvidedRun(int pos, Function<XmlCursor, T> provider) {
- if (pos >= 0 && pos < runs.size()) {
- XWPFRun run = runs.get(pos);
- CTR ctr = run.getCTR();
- XmlCursor newCursor = ctr.newCursor();
- if (!isCursorInParagraph(newCursor)) {
- // look up correct position for CTP -> XXX -> R array
- newCursor.toParent();
- }
- if (isCursorInParagraph(newCursor)) {
- // provide a new run
- T newRun = provider.apply(newCursor);
-
- // To update the iruns, find where we're going
- // in the normal runs, and go in there
- int iPos = iruns.size();
- int oldAt = iruns.indexOf(run);
- if (oldAt != -1) {
- iPos = oldAt;
- }
- iruns.add(iPos, newRun);
- // Runs itself is easy to update
- runs.add(pos, newRun);
- return newRun;
- }
- newCursor.dispose();
- }
- return null;
- }
-
- /**
- * verifies that cursor is on the right position
- *
- * @param cursor
- * @return
- */
- private boolean isCursorInParagraph(XmlCursor cursor) {
- XmlCursor verify = cursor.newCursor();
- verify.toParent();
- boolean result = (verify.getObject() == this.paragraph);
- verify.dispose();
- return result;
- }
-
- /**
- * 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 TextSegment 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;
- 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) {
- TextSegment segment = new TextSegment();
- segment.setBeginRun(beginRunPos);
- segment.setBeginText(beginTextPos);
- segment.setBeginChar(beginCharPos);
- segment.setEndRun(runPos);
- segment.setEndText(textPos);
- segment.setEndChar(charPos);
- return segment;
- }
- } 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(TextSegment 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, 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()) {
- XWPFRun run = runs.get(pos);
- // CTP -> CTHyperlink -> R array
- if (run instanceof XWPFHyperlinkRun
- && isTheOnlyCTHyperlinkInRuns((XWPFHyperlinkRun) run)) {
- XmlCursor c = ((XWPFHyperlinkRun) run).getCTHyperlink()
- .newCursor();
- c.removeXml();
- c.dispose();
- runs.remove(pos);
- iruns.remove(run);
- return true;
- }
- // CTP -> CTField -> R array
- if (run instanceof XWPFFieldRun
- && isTheOnlyCTFieldInRuns((XWPFFieldRun) run)) {
- XmlCursor c = ((XWPFFieldRun) run).getCTField().newCursor();
- c.removeXml();
- c.dispose();
- runs.remove(pos);
- iruns.remove(run);
- return true;
- }
- XmlCursor c = run.getCTR().newCursor();
- c.removeXml();
- c.dispose();
- runs.remove(pos);
- iruns.remove(run);
- return true;
- }
- return false;
- }
-
- /**
- * Is there only one ctHyperlink in all runs
- *
- * @param run
- * hyperlink run
- * @return
- */
- private boolean isTheOnlyCTHyperlinkInRuns(XWPFHyperlinkRun run) {
- CTHyperlink ctHyperlink = run.getCTHyperlink();
- long count = runs.stream().filter(r -> (r instanceof XWPFHyperlinkRun
- && ctHyperlink == ((XWPFHyperlinkRun) r).getCTHyperlink()))
- .count();
- return count <= 1;
- }
-
- /**
- * Is there only one ctField in all runs
- *
- * @param run
- * field run
- * @return
- */
- private boolean isTheOnlyCTFieldInRuns(XWPFFieldRun run) {
- CTSimpleField ctField = run.getCTField();
- long count = runs.stream().filter(r -> (r instanceof XWPFFieldRun
- && ctField == ((XWPFFieldRun) r).getCTField())).count();
- return count <= 1;
- }
-
- /**
- * 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;
- }
-
- /**
- * Add a new run with a reference to the specified footnote.
- * The footnote reference run will have the style name "FootnoteReference".
- *
- * @param footnote Footnote to which to add a reference.
- * @since 4.0.0
- */
- public void addFootnoteReference(XWPFAbstractFootnoteEndnote footnote) {
- XWPFRun run = createRun();
- CTR ctRun = run.getCTR();
- ctRun.addNewRPr().addNewRStyle().setVal("FootnoteReference");
- if (footnote instanceof XWPFEndnote) {
- ctRun.addNewEndnoteReference().setId(footnote.getId());
- } else {
- ctRun.addNewFootnoteReference().setId(footnote.getId());
- }
- }
- }
|