You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ab...@apache.org on 2018/08/26 21:33:16 UTC

svn commit: r1839259 [2/2] - in /poi/trunk: ./ src/ooxml/java/org/apache/poi/xslf/usermodel/ src/ooxml/java/org/apache/poi/xssf/usermodel/ src/ooxml/testcases/org/apache/poi/xddf/usermodel/text/ src/ooxml/testcases/org/apache/poi/xslf/usermodel/ src/oo...

Modified: poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java?rev=1839259&r1=1839258&r2=1839259&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java (original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java Sun Aug 26 21:33:16 2018
@@ -21,13 +21,44 @@ import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
+import java.util.Optional;
+import java.util.function.Function;
 
 import org.apache.poi.hssf.util.HSSFColor;
 import org.apache.poi.ss.usermodel.SimpleShape;
 import org.apache.poi.ss.usermodel.VerticalAlignment;
+import org.apache.poi.util.Beta;
 import org.apache.poi.util.Internal;
-import org.apache.poi.util.Units;
-import org.openxmlformats.schemas.drawingml.x2006.main.*;
+import org.apache.poi.xddf.usermodel.XDDFColor;
+import org.apache.poi.xddf.usermodel.XDDFColorRgbBinary;
+import org.apache.poi.xddf.usermodel.XDDFFillProperties;
+import org.apache.poi.xddf.usermodel.XDDFSolidFillProperties;
+import org.apache.poi.xddf.usermodel.text.TextContainer;
+import org.apache.poi.xddf.usermodel.text.XDDFRunProperties;
+import org.apache.poi.xddf.usermodel.text.XDDFTextBody;
+import org.apache.poi.xddf.usermodel.text.XDDFTextParagraph;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextFont;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
+import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType;
+import org.openxmlformats.schemas.drawingml.x2006.main.STTextAnchoringType;
+import org.openxmlformats.schemas.drawingml.x2006.main.STTextHorzOverflowType;
+import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType;
+import org.openxmlformats.schemas.drawingml.x2006.main.STTextVertOverflowType;
+import org.openxmlformats.schemas.drawingml.x2006.main.STTextVerticalType;
+import org.openxmlformats.schemas.drawingml.x2006.main.STTextWrappingType;
 import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTShape;
 import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTShapeNonVisual;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRElt;
@@ -36,12 +67,17 @@ import org.openxmlformats.schemas.spread
 
 /**
  * Represents a shape with a predefined geometry in a SpreadsheetML drawing.
- * Possible shape types are defined in {@link org.apache.poi.ss.usermodel.ShapeTypes}
+ * Possible shape types are defined in
+ * {@link org.apache.poi.ss.usermodel.ShapeTypes}
  */
-public class XSSFSimpleShape extends XSSFShape implements Iterable<XSSFTextParagraph>, SimpleShape {
-	/**
-	 * List of the paragraphs that make up the text in this shape
-	 */
+public class XSSFSimpleShape extends XSSFShape implements Iterable<XSSFTextParagraph>, SimpleShape, TextContainer {
+    /**
+     * The text body containing the paragraphs for this shape.
+     */
+    private final XDDFTextBody _textBody;
+    /**
+     * List of the paragraphs that make up the text in this shape
+     */
     private final List<XSSFTextParagraph> _paragraphs;
     /**
      * A default instance of CTShape used for creating new shapes.
@@ -49,22 +85,26 @@ public class XSSFSimpleShape extends XSS
     private static CTShape prototype;
 
     /**
-     *  Xml bean that stores properties of this shape
+     * Xml bean that stores properties of this shape
      */
     private CTShape ctShape;
 
     protected XSSFSimpleShape(XSSFDrawing drawing, CTShape ctShape) {
         this.drawing = drawing;
         this.ctShape = ctShape;
-        
+
         _paragraphs = new ArrayList<>();
-        
-        // initialize any existing paragraphs - this will be the default body paragraph in a new shape, 
+
+        // initialize any existing paragraphs - this will be the default body
+        // paragraph in a new shape,
         // or existing paragraphs that have been loaded from the file
         CTTextBody body = ctShape.getTxBody();
-        if(body != null) {
-            for(int i = 0; i < body.sizeOfPArray(); i++) {
-                _paragraphs.add(new XSSFTextParagraph(body.getPArray(i), ctShape));        	
+        if (body == null) {
+            _textBody = null;
+        } else {
+            _textBody = new XDDFTextBody(this, body);
+            for (int i = 0; i < body.sizeOfPArray(); i++) {
+                _paragraphs.add(new XSSFTextParagraph(body.getPArray(i), ctShape));
             }
         }
     }
@@ -73,7 +113,7 @@ public class XSSFSimpleShape extends XSS
      * Prototype with the default structure of a new auto-shape.
      */
     protected static CTShape prototype() {
-        if(prototype == null) {
+        if (prototype == null) {
             CTShape shape = CTShape.Factory.newInstance();
 
             CTShapeNonVisual nv = shape.addNewNvSpPr();
@@ -95,19 +135,12 @@ public class XSSFSimpleShape extends XSS
             geom.setPrst(STShapeType.RECT);
             geom.addNewAvLst();
 
-            CTTextBody body = shape.addNewTxBody();
-            CTTextBodyProperties bodypr = body.addNewBodyPr();
-            bodypr.setAnchor(STTextAnchoringType.T);
-            bodypr.setRtlCol(false);
-            CTTextParagraph p = body.addNewP();
-            p.addNewPPr().setAlgn(STTextAlignType.L);
-            CTTextCharacterProperties endPr = p.addNewEndParaRPr();
-            endPr.setLang("en-US");
-            endPr.setSz(1100);   
-            CTSolidColorFillProperties scfpr = endPr.addNewSolidFill();
-            scfpr.addNewSrgbClr().setVal(new byte[] { 0, 0, 0 });
-                        
-            body.addNewLstStyle();
+            XDDFTextBody body = new XDDFTextBody(null, shape.addNewTxBody());
+            XDDFTextParagraph p = body.initialize();
+            XDDFRunProperties rp = p.getAfterLastRunProperties();
+            XDDFColor black = new XDDFColorRgbBinary(new byte[] { 0, 0, 0 });
+            XDDFFillProperties fp = new XDDFSolidFillProperties(black);
+            rp.setFillProperties(fp);
 
             prototype = shape;
         }
@@ -115,119 +148,147 @@ public class XSSFSimpleShape extends XSS
     }
 
     @Internal
-    public CTShape getCTShape(){
+    public CTShape getCTShape() {
         return ctShape;
     }
 
+    @Beta
+    public XDDFTextBody getTextBody() {
+        return _textBody;
+    }
 
-    public Iterator<XSSFTextParagraph> iterator(){
+    protected void setXfrm(CTTransform2D t2d) {
+        ctShape.getSpPr().setXfrm(t2d);
+    }
+
+    @Override
+    public Iterator<XSSFTextParagraph> iterator() {
         return _paragraphs.iterator();
     }
 
     /**
-     * Returns the text from all paragraphs in the shape. Paragraphs are separated by new lines.
-     * 
-     * @return  text contained within this shape or empty string
+     * Returns the text from all paragraphs in the shape. Paragraphs are
+     * separated by new lines.
+     *
+     * @return text contained within this shape or empty string
      */
     public String getText() {
         final int MAX_LEVELS = 9;
         StringBuilder out = new StringBuilder();
-        List<Integer> levelCount = new ArrayList<>(MAX_LEVELS);	// maximum 9 levels
+        List<Integer> levelCount = new ArrayList<>(MAX_LEVELS); // maximum 9
+                                                                // levels
         XSSFTextParagraph p = null;
-        
-        // initialise the levelCount array - this maintains a record of the numbering to be used at each level
-        for (int k = 0; k < MAX_LEVELS; k++){
-        	levelCount.add(0);
+
+        // initialise the levelCount array - this maintains a record of the
+        // numbering to be used at each level
+        for (int k = 0; k < MAX_LEVELS; k++) {
+            levelCount.add(0);
         }
 
-        for(int i = 0; i < _paragraphs.size(); i++) {
-            if (out.length() > 0) out.append('\n');
+        for (int i = 0; i < _paragraphs.size(); i++) {
+            if (out.length() > 0) {
+                out.append('\n');
+            }
             p = _paragraphs.get(i);
 
-            if(p.isBullet() && p.getText().length() > 0){
-               
+            if (p.isBullet() && p.getText().length() > 0) {
+
                 int level = Math.min(p.getLevel(), MAX_LEVELS - 1);
-                
-                if(p.isBulletAutoNumber()){
+
+                if (p.isBulletAutoNumber()) {
                     i = processAutoNumGroup(i, level, levelCount, out);
                 } else {
                     // indent appropriately for the level
-                    for(int j = 0; j < level; j++){
+                    for (int j = 0; j < level; j++) {
                         out.append('\t');
-                    }               
+                    }
                     String character = p.getBulletCharacter();
                     out.append(character.length() > 0 ? character + " " : "- ");
                     out.append(p.getText());
-                }               
+                }
             } else {
                 out.append(p.getText());
-                
+
                 // this paragraph is not a bullet, so reset the count array
-                for (int k = 0; k < MAX_LEVELS; k++){
+                for (int k = 0; k < MAX_LEVELS; k++) {
                     levelCount.set(k, 0);
                 }
-            }            
+            }
         }
 
         return out.toString();
     }
 
     /**
-     * 
+     *
      */
-    private int processAutoNumGroup(int index, int level, List<Integer> levelCount, StringBuilder out){
+    private int processAutoNumGroup(int index, int level, List<Integer> levelCount, StringBuilder out) {
         XSSFTextParagraph p = null;
         XSSFTextParagraph nextp = null;
         ListAutoNumber scheme, nextScheme;
         int startAt, nextStartAt;
-        
+
         p = _paragraphs.get(index);
-        
-        // The rules for generating the auto numbers are as follows. If the following paragraph is also
-        // an auto-number, has the same type/scheme (and startAt if defined on this paragraph) then they are
-        // considered part of the same group. An empty bullet paragraph is counted as part of the same
-        // group but does not increment the count for the group. A change of type, startAt or the paragraph
+
+        // The rules for generating the auto numbers are as follows. If the
+        // following paragraph is also
+        // an auto-number, has the same type/scheme (and startAt if defined on
+        // this paragraph) then they are
+        // considered part of the same group. An empty bullet paragraph is
+        // counted as part of the same
+        // group but does not increment the count for the group. A change of
+        // type, startAt or the paragraph
         // not being a bullet resets the count for that level to 1.
-        
-        // first auto-number paragraph so initialise to 1 or the bullets startAt if present
+
+        // first auto-number paragraph so initialise to 1 or the bullets startAt
+        // if present
         startAt = p.getBulletAutoNumberStart();
         scheme = p.getBulletAutoNumberScheme();
-        if(levelCount.get(level) == 0) {
+        if (levelCount.get(level) == 0) {
             levelCount.set(level, startAt == 0 ? 1 : startAt);
         }
         // indent appropriately for the level
-        for(int j = 0; j < level; j++){
+        for (int j = 0; j < level; j++) {
             out.append('\t');
         }
-        if (p.getText().length() > 0){
+        if (p.getText().length() > 0) {
             out.append(getBulletPrefix(scheme, levelCount.get(level)));
             out.append(p.getText());
         }
-        while(true) {                        
+        while (true) {
             nextp = (index + 1) == _paragraphs.size() ? null : _paragraphs.get(index + 1);
-            if(nextp == null) break; // out of paragraphs
-            if(!(nextp.isBullet() && p.isBulletAutoNumber())) break; // not an auto-number bullet                      
-            if(nextp.getLevel() > level) { 
+            if (nextp == null) {
+                break; // out of paragraphs
+            }
+            if (!(nextp.isBullet() && p.isBulletAutoNumber())) {
+                break; // not an auto-number bullet
+            }
+            if (nextp.getLevel() > level) {
                 // recurse into the new level group
-                if (out.length() > 0) out.append('\n');
+                if (out.length() > 0) {
+                    out.append('\n');
+                }
                 index = processAutoNumGroup(index + 1, nextp.getLevel(), levelCount, out);
                 continue; // restart the loop given the new index
-            } else if(nextp.getLevel() < level) {
-                break; // changed level   
+            } else if (nextp.getLevel() < level) {
+                break; // changed level
             }
             nextScheme = nextp.getBulletAutoNumberScheme();
             nextStartAt = nextp.getBulletAutoNumberStart();
-            
-            if(nextScheme == scheme && nextStartAt == startAt) {
-                // bullet is valid, so increment i 
+
+            if (nextScheme == scheme && nextStartAt == startAt) {
+                // bullet is valid, so increment i
                 ++index;
-                if (out.length() > 0) out.append('\n');
+                if (out.length() > 0) {
+                    out.append('\n');
+                }
                 // indent for the level
-                for(int j = 0; j < level; j++){
+                for (int j = 0; j < level; j++) {
                     out.append('\t');
                 }
-                // check for empty text - only output a bullet if there is text, but it is still part of the group
-                if(nextp.getText().length() > 0) {
+                // check for empty text - only output a bullet if there is text,
+                // but it is still part of the group
+                if (nextp.getText().length() > 0) {
                     // increment the count for this level
                     levelCount.set(level, levelCount.get(level) + 1);
                     out.append(getBulletPrefix(nextScheme, levelCount.get(level)));
@@ -235,36 +296,45 @@ public class XSSFSimpleShape extends XSS
                 }
             } else {
                 // something doesn't match so stop
-                break; 
+                break;
             }
         }
-        // end of the group so reset the count for this level 
-        levelCount.set(level, 0);      
-        
-        return index; 
+        // end of the group so reset the count for this level
+        levelCount.set(level, 0);
+
+        return index;
     }
+
     /**
-     * Returns a string containing an appropriate prefix for an auto-numbering bullet
-     * @param scheme the auto-numbering scheme used by the bullet
-     * @param value the value of the bullet
+     * Returns a string containing an appropriate prefix for an auto-numbering
+     * bullet
+     *
+     * @param scheme
+     *            the auto-numbering scheme used by the bullet
+     * @param value
+     *            the value of the bullet
      * @return appropriate prefix for an auto-numbering bullet
      */
-    private String getBulletPrefix(ListAutoNumber scheme, int value){
+    private String getBulletPrefix(ListAutoNumber scheme, int value) {
         StringBuilder out = new StringBuilder();
-        
-        switch(scheme) {
+
+        switch (scheme) {
         case ALPHA_LC_PARENT_BOTH:
         case ALPHA_LC_PARENT_R:
-            if(scheme == ListAutoNumber.ALPHA_LC_PARENT_BOTH) out.append('(');
+            if (scheme == ListAutoNumber.ALPHA_LC_PARENT_BOTH) {
+                out.append('(');
+            }
             out.append(valueToAlpha(value).toLowerCase(Locale.ROOT));
             out.append(')');
             break;
         case ALPHA_UC_PARENT_BOTH:
         case ALPHA_UC_PARENT_R:
-            if(scheme == ListAutoNumber.ALPHA_UC_PARENT_BOTH) out.append('(');
+            if (scheme == ListAutoNumber.ALPHA_UC_PARENT_BOTH) {
+                out.append('(');
+            }
             out.append(valueToAlpha(value));
             out.append(')');
-            break;        
+            break;
         case ALPHA_LC_PERIOD:
             out.append(valueToAlpha(value).toLowerCase(Locale.ROOT));
             out.append('.');
@@ -275,7 +345,9 @@ public class XSSFSimpleShape extends XSS
             break;
         case ARABIC_PARENT_BOTH:
         case ARABIC_PARENT_R:
-            if(scheme == ListAutoNumber.ARABIC_PARENT_BOTH) out.append('(');
+            if (scheme == ListAutoNumber.ARABIC_PARENT_BOTH) {
+                out.append('(');
+            }
             out.append(value);
             out.append(')');
             break;
@@ -285,19 +357,23 @@ public class XSSFSimpleShape extends XSS
             break;
         case ARABIC_PLAIN:
             out.append(value);
-            break;            
+            break;
         case ROMAN_LC_PARENT_BOTH:
         case ROMAN_LC_PARENT_R:
-            if(scheme == ListAutoNumber.ROMAN_LC_PARENT_BOTH) out.append('(');
+            if (scheme == ListAutoNumber.ROMAN_LC_PARENT_BOTH) {
+                out.append('(');
+            }
             out.append(valueToRoman(value).toLowerCase(Locale.ROOT));
             out.append(')');
             break;
         case ROMAN_UC_PARENT_BOTH:
         case ROMAN_UC_PARENT_R:
-            if(scheme == ListAutoNumber.ROMAN_UC_PARENT_BOTH) out.append('(');
+            if (scheme == ListAutoNumber.ROMAN_UC_PARENT_BOTH) {
+                out.append('(');
+            }
             out.append(valueToRoman(value));
             out.append(')');
-            break;        
+            break;
         case ROMAN_LC_PERIOD:
             out.append(valueToRoman(value).toLowerCase(Locale.ROOT));
             out.append('.');
@@ -307,13 +383,14 @@ public class XSSFSimpleShape extends XSS
             out.append('.');
             break;
         default:
-            out.append('\u2022');   // can't set the font to wingdings so use the default bullet character
-            break;            
+            out.append('\u2022'); // can't set the font to wingdings so use the
+                                  // default bullet character
+            break;
         }
-        out.append(" ");        
+        out.append(" ");
         return out.toString();
     }
-    
+
     /**
      * Convert an integer to its alpha equivalent e.g. 1 = A, 2 = B, 27 = AA etc
      */
@@ -322,59 +399,66 @@ public class XSSFSimpleShape extends XSS
         int modulo;
         while (value > 0) {
             modulo = (value - 1) % 26;
-            alpha = (char)(65 + modulo) + alpha;
+            alpha = (char) (65 + modulo) + alpha;
             value = (value - modulo) / 26;
         }
         return alpha;
     }
-    
-    private static String[] _romanChars = new String[] { "M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I" };
-    private static int[] _romanAlphaValues = new int[] { 1000,900,500,400,100,90,50,40,10,9,5,4,1 };
-        
+
+    private static String[] _romanChars = new String[] { "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V",
+            "IV", "I" };
+    private static int[] _romanAlphaValues = new int[] { 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 };
+
     /**
      * Convert an integer to its roman equivalent e.g. 1 = I, 9 = IX etc
      */
     private String valueToRoman(int value) {
         StringBuilder out = new StringBuilder();
-        for(int i = 0; value > 0 && i < _romanChars.length; i++) {
-            while(_romanAlphaValues[i] <= value) {
+        for (int i = 0; value > 0 && i < _romanChars.length; i++) {
+            while (_romanAlphaValues[i] <= value) {
                 out.append(_romanChars[i]);
                 value -= _romanAlphaValues[i];
             }
         }
         return out.toString();
     }
-    
+
     /**
      * Clear all text from this shape
      */
-    public void clearText(){
+    public void clearText() {
         _paragraphs.clear();
         CTTextBody txBody = ctShape.getTxBody();
         txBody.setPArray(null); // remove any existing paragraphs
     }
-    
+
     /**
-     * Set a single paragraph of text on the shape. Note this will replace all existing paragraphs created on the shape.
-     * @param text	string representing the paragraph text
+     * Set a single paragraph of text on the shape. Note this will replace all
+     * existing paragraphs created on the shape.
+     *
+     * @param text
+     *            string representing the paragraph text
      */
-    public void setText(String text){
+    public void setText(String text) {
         clearText();
 
         addNewTextParagraph().addNewTextRun().setText(text);
     }
 
     /**
-     * Set a single paragraph of text on the shape. Note this will replace all existing paragraphs created on the shape.
-     * @param str	rich text string representing the paragraph text
+     * Set a single paragraph of text on the shape. Note this will replace all
+     * existing paragraphs created on the shape.
+     *
+     * @param str
+     *            rich text string representing the paragraph text
      */
-    public void setText(XSSFRichTextString str){
+    public void setText(XSSFRichTextString str) {
 
-        XSSFWorkbook wb = (XSSFWorkbook)getDrawing().getParent().getParent();
+        XSSFWorkbook wb = (XSSFWorkbook) getDrawing().getParent().getParent();
         str.setStylesTableReference(wb.getStylesSource());
 
         CTTextParagraph p = CTTextParagraph.Factory.newInstance();
-        if(str.numFormattingRuns() == 0){
+        if (str.numFormattingRuns() == 0) {
             CTRegularTextRun r = p.addNewR();
             CTTextCharacterProperties rPr = r.addNewRPr();
             rPr.setLang("en-US");
@@ -385,7 +469,9 @@ public class XSSFSimpleShape extends XSS
             for (int i = 0; i < str.getCTRst().sizeOfRArray(); i++) {
                 CTRElt lt = str.getCTRst().getRArray(i);
                 CTRPrElt ltPr = lt.getRPr();
-                if(ltPr == null) ltPr = lt.addNewRPr();
+                if (ltPr == null) {
+                    ltPr = lt.addNewRPr();
+                }
 
                 CTRegularTextRun r = p.addNewR();
                 CTTextCharacterProperties rPr = r.addNewRPr();
@@ -396,15 +482,16 @@ public class XSSFSimpleShape extends XSS
                 r.setT(lt.getT());
             }
         }
-        
-        clearText();                
-        ctShape.getTxBody().setPArray(new CTTextParagraph[]{p});
+
+        clearText();
+        ctShape.getTxBody().setPArray(new CTTextParagraph[] { p });
         _paragraphs.add(new XSSFTextParagraph(ctShape.getTxBody().getPArray(0), ctShape));
-    }    
-    
+    }
+
     /**
-     * Returns a collection of the XSSFTextParagraphs that are attached to this shape
-     * 
+     * Returns a collection of the XSSFTextParagraphs that are attached to this
+     * shape
+     *
      * @return text paragraphs in this shape
      */
     public List<XSSFTextParagraph> getTextParagraphs() {
@@ -422,7 +509,7 @@ public class XSSFSimpleShape extends XSS
         XSSFTextParagraph paragraph = new XSSFTextParagraph(p, ctShape);
         _paragraphs.add(paragraph);
         return paragraph;
-    }    
+    }
 
     /**
      * Add a new paragraph run to this shape, set to the provided string
@@ -433,18 +520,19 @@ public class XSSFSimpleShape extends XSS
         XSSFTextParagraph paragraph = addNewTextParagraph();
         paragraph.addNewTextRun().setText(text);
         return paragraph;
-    }   
-    
+    }
+
     /**
-     * Add a new paragraph run to this shape, set to the provided rich text string 
+     * Add a new paragraph run to this shape, set to the provided rich text
+     * string
      *
      * @return created paragraph run
      */
     public XSSFTextParagraph addNewTextParagraph(XSSFRichTextString str) {
         CTTextBody txBody = ctShape.getTxBody();
         CTTextParagraph p = txBody.addNewP();
-       
-        if(str.numFormattingRuns() == 0){
+
+        if (str.numFormattingRuns() == 0) {
             CTRegularTextRun r = p.addNewR();
             CTTextCharacterProperties rPr = r.addNewRPr();
             rPr.setLang("en-US");
@@ -455,7 +543,9 @@ public class XSSFSimpleShape extends XSS
             for (int i = 0; i < str.getCTRst().sizeOfRArray(); i++) {
                 CTRElt lt = str.getCTRst().getRArray(i);
                 CTRPrElt ltPr = lt.getRPr();
-                if(ltPr == null) ltPr = lt.addNewRPr();
+                if (ltPr == null) {
+                    ltPr = lt.addNewRPr();
+                }
 
                 CTRegularTextRun r = p.addNewR();
                 CTTextCharacterProperties rPr = r.addNewRPr();
@@ -466,25 +556,29 @@ public class XSSFSimpleShape extends XSS
                 r.setT(lt.getT());
             }
         }
-        
-        // Note: the XSSFTextParagraph constructor will create its required XSSFTextRuns from the provided CTTextParagraph
+
+        // Note: the XSSFTextParagraph constructor will create its required
+        // XSSFTextRuns from the provided CTTextParagraph
         XSSFTextParagraph paragraph = new XSSFTextParagraph(p, ctShape);
         _paragraphs.add(paragraph);
-        
+
         return paragraph;
     }
 
     /**
      * Sets the type of horizontal overflow for the text.
      *
-     * @param overflow - the type of horizontal overflow.
-     * A <code>null</code> values unsets this property.
+     * @param overflow
+     *            - the type of horizontal overflow. A <code>null</code> values
+     *            unsets this property.
      */
-    public void setTextHorizontalOverflow(TextHorizontalOverflow overflow){
+    public void setTextHorizontalOverflow(TextHorizontalOverflow overflow) {
         CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
         if (bodyPr != null) {
-             if(overflow == null) {
-                if(bodyPr.isSetHorzOverflow()) bodyPr.unsetHorzOverflow();
+            if (overflow == null) {
+                if (bodyPr.isSetHorzOverflow()) {
+                    bodyPr.unsetHorzOverflow();
+                }
             } else {
                 bodyPr.setHorzOverflow(STTextHorzOverflowType.Enum.forInt(overflow.ordinal() + 1));
             }
@@ -496,27 +590,30 @@ public class XSSFSimpleShape extends XSS
      *
      * @return the type of horizontal overflow
      */
-    public TextHorizontalOverflow getTextHorizontalOverflow(){
-    	CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
-    	if(bodyPr != null) {
-    		if(bodyPr.isSetHorzOverflow()){
-    			return TextHorizontalOverflow.values()[bodyPr.getHorzOverflow().intValue() - 1];
-    		}    			
-    	}
-    	return TextHorizontalOverflow.OVERFLOW;
-    }    
-    
+    public TextHorizontalOverflow getTextHorizontalOverflow() {
+        CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
+        if (bodyPr != null) {
+            if (bodyPr.isSetHorzOverflow()) {
+                return TextHorizontalOverflow.values()[bodyPr.getHorzOverflow().intValue() - 1];
+            }
+        }
+        return TextHorizontalOverflow.OVERFLOW;
+    }
+
     /**
      * Sets the type of vertical overflow for the text.
      *
-     * @param overflow - the type of vertical overflow.
-     * A <code>null</code> values unsets this property.
+     * @param overflow
+     *            - the type of vertical overflow. A <code>null</code> values
+     *            unsets this property.
      */
-    public void setTextVerticalOverflow(TextVerticalOverflow overflow){
+    public void setTextVerticalOverflow(TextVerticalOverflow overflow) {
         CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
         if (bodyPr != null) {
-             if(overflow == null) {
-                if(bodyPr.isSetVertOverflow()) bodyPr.unsetVertOverflow();
+            if (overflow == null) {
+                if (bodyPr.isSetVertOverflow()) {
+                    bodyPr.unsetVertOverflow();
+                }
             } else {
                 bodyPr.setVertOverflow(STTextVertOverflowType.Enum.forInt(overflow.ordinal() + 1));
             }
@@ -528,27 +625,30 @@ public class XSSFSimpleShape extends XSS
      *
      * @return the type of vertical overflow
      */
-    public TextVerticalOverflow getTextVerticalOverflow(){
-    	CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
-    	if(bodyPr != null) {
-    		if(bodyPr.isSetVertOverflow()){
-    			return TextVerticalOverflow.values()[bodyPr.getVertOverflow().intValue() - 1];
-    		}    			
-    	}
-    	return TextVerticalOverflow.OVERFLOW;
-    }   
-    
+    public TextVerticalOverflow getTextVerticalOverflow() {
+        CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
+        if (bodyPr != null) {
+            if (bodyPr.isSetVertOverflow()) {
+                return TextVerticalOverflow.values()[bodyPr.getVertOverflow().intValue() - 1];
+            }
+        }
+        return TextVerticalOverflow.OVERFLOW;
+    }
+
     /**
      * Sets the type of vertical alignment for the text within the shape.
      *
-     * @param anchor - the type of alignment.
-     * A <code>null</code> values unsets this property.
+     * @param anchor
+     *            - the type of alignment. A <code>null</code> values unsets
+     *            this property.
      */
-    public void setVerticalAlignment(VerticalAlignment anchor){
+    public void setVerticalAlignment(VerticalAlignment anchor) {
         CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
         if (bodyPr != null) {
-             if(anchor == null) {
-                if(bodyPr.isSetAnchor()) bodyPr.unsetAnchor();
+            if (anchor == null) {
+                if (bodyPr.isSetAnchor()) {
+                    bodyPr.unsetAnchor();
+                }
             } else {
                 bodyPr.setAnchor(STTextAnchoringType.Enum.forInt(anchor.ordinal() + 1));
             }
@@ -560,27 +660,30 @@ public class XSSFSimpleShape extends XSS
      *
      * @return the type of vertical alignment
      */
-    public VerticalAlignment getVerticalAlignment(){
-    	CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
-    	if(bodyPr != null) {
-    		if(bodyPr.isSetAnchor()){
-    			return VerticalAlignment.values()[bodyPr.getAnchor().intValue() - 1];
-    		}    			
-    	}
-    	return VerticalAlignment.TOP;
+    public VerticalAlignment getVerticalAlignment() {
+        CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
+        if (bodyPr != null) {
+            if (bodyPr.isSetAnchor()) {
+                return VerticalAlignment.values()[bodyPr.getAnchor().intValue() - 1];
+            }
+        }
+        return VerticalAlignment.TOP;
     }
 
     /**
      * Sets the vertical orientation of the text
-     * 
-     * @param orientation vertical orientation of the text
-     * A <code>null</code> values unsets this property.
+     *
+     * @param orientation
+     *            vertical orientation of the text A <code>null</code> values
+     *            unsets this property.
      */
-    public void setTextDirection(TextDirection orientation){
+    public void setTextDirection(TextDirection orientation) {
         CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
         if (bodyPr != null) {
-            if(orientation == null) {
-                if(bodyPr.isSetVert()) bodyPr.unsetVert();
+            if (orientation == null) {
+                if (bodyPr.isSetVert()) {
+                    bodyPr.unsetVert();
+                }
             } else {
                 bodyPr.setVert(STTextVerticalType.Enum.forInt(orientation.ordinal() + 1));
             }
@@ -589,170 +692,174 @@ public class XSSFSimpleShape extends XSS
 
     /**
      * Gets the vertical orientation of the text
-     * 
+     *
      * @return vertical orientation of the text
      */
-    public TextDirection getTextDirection(){
+    public TextDirection getTextDirection() {
         CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
         if (bodyPr != null) {
             STTextVerticalType.Enum val = bodyPr.getVert();
-            if(val != null){
+            if (val != null) {
                 return TextDirection.values()[val.intValue() - 1];
             }
         }
         return TextDirection.HORIZONTAL;
     }
 
-
     /**
-     * Returns the distance (in points) between the bottom of the text frame
-     * and the bottom of the inscribed rectangle of the shape that contains the text.
+     * Returns the distance (in points) between the bottom of the text frame and
+     * the bottom of the inscribed rectangle of the shape that contains the
+     * text.
      *
      * @return the bottom inset in points
      */
-    public double getBottomInset(){
-        CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
-        if (bodyPr != null) {
-        	if(bodyPr.isSetBIns()){
-        		return Units.toPoints(bodyPr.getBIns());
-        	}
+    public double getBottomInset() {
+        Double inset = _textBody.getBodyProperties().getBottomInset();
+        if (inset == null) {
+            // If this attribute is omitted, then a value of 0.05 inches is
+            // implied
+            return 3.6;
+        } else {
+            return inset;
         }
-        // If this attribute is omitted, then a value of 0.05 inches is implied
-        return 3.6;	
     }
 
     /**
-     *  Returns the distance (in points) between the left edge of the text frame
-     *  and the left edge of the inscribed rectangle of the shape that contains
-     *  the text.
+     * Returns the distance (in points) between the left edge of the text frame
+     * and the left edge of the inscribed rectangle of the shape that contains
+     * the text.
      *
      * @return the left inset in points
      */
-    public double getLeftInset(){
-        CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
-        if (bodyPr != null) {
-        	if(bodyPr.isSetLIns()){
-        		return Units.toPoints(bodyPr.getLIns());
-        	}
+    public double getLeftInset() {
+        Double inset = _textBody.getBodyProperties().getLeftInset();
+        if (inset == null) {
+            // If this attribute is omitted, then a value of 0.05 inches is
+            // implied
+            return 3.6;
+        } else {
+            return inset;
         }
-        // If this attribute is omitted, then a value of 0.05 inches is implied
-        return 3.6;
     }
 
     /**
-     *  Returns the distance (in points) between the right edge of the
-     *  text frame and the right edge of the inscribed rectangle of the shape
-     *  that contains the text.
+     * Returns the distance (in points) between the right edge of the text frame
+     * and the right edge of the inscribed rectangle of the shape that contains
+     * the text.
      *
      * @return the right inset in points
      */
-    public double getRightInset(){
-        CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
-        if (bodyPr != null) {
-        	if(bodyPr.isSetRIns()){
-        		return Units.toPoints(bodyPr.getRIns());
-        	}
+    public double getRightInset() {
+        Double inset = _textBody.getBodyProperties().getRightInset();
+        if (inset == null) {
+            // If this attribute is omitted, then a value of 0.05 inches is
+            // implied
+            return 3.6;
+        } else {
+            return inset;
         }
-        // If this attribute is omitted, then a value of 0.05 inches is implied
-        return 3.6;
     }
 
     /**
-     *  Returns the distance (in points) between the top of the text frame
-     *  and the top of the inscribed rectangle of the shape that contains the text.
+     * Returns the distance (in points) between the top of the text frame and
+     * the top of the inscribed rectangle of the shape that contains the text.
      *
      * @return the top inset in points
      */
-    public double getTopInset(){
-        CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
-        if (bodyPr != null) {
-        	if(bodyPr.isSetTIns()){
-        		return Units.toPoints(bodyPr.getTIns());
-        	}
+    public double getTopInset() {
+        Double inset = _textBody.getBodyProperties().getTopInset();
+        if (inset == null) {
+            // If this attribute is omitted, then a value of 0.05 inches is
+            // implied
+            return 3.6;
+        } else {
+            return inset;
         }
-        // If this attribute is omitted, then a value of 0.05 inches is implied
-        return 3.6;    	
     }
 
     /**
      * Sets the bottom inset.
+     *
      * @see #getBottomInset()
      *
-     * @param margin    the bottom margin
+     * @param margin
+     *            the bottom margin
      */
-    public void setBottomInset(double margin){
-        CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
-        if (bodyPr != null) {
-            if(margin == -1) {
-                if(bodyPr.isSetBIns()) bodyPr.unsetBIns();
-            } else bodyPr.setBIns(Units.toEMU(margin));
+    public void setBottomInset(double margin) {
+        if (margin == -1) {
+            _textBody.getBodyProperties().setBottomInset(null);
+        } else {
+            _textBody.getBodyProperties().setBottomInset(margin);
         }
     }
 
     /**
      * Sets the left inset.
+     *
      * @see #getLeftInset()
      *
-     * @param margin    the left margin
+     * @param margin
+     *            the left margin
      */
-    public void setLeftInset(double margin){
-        CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
-        if (bodyPr != null) {
-            if(margin == -1) {
-                if(bodyPr.isSetLIns()) bodyPr.unsetLIns();
-            } else bodyPr.setLIns(Units.toEMU(margin));
+    public void setLeftInset(double margin) {
+        if (margin == -1) {
+            _textBody.getBodyProperties().setLeftInset(null);
+        } else {
+            _textBody.getBodyProperties().setLeftInset(margin);
         }
     }
 
     /**
      * Sets the right inset.
+     *
      * @see #getRightInset()
      *
-     * @param margin    the right margin
+     * @param margin
+     *            the right margin
      */
-    public void setRightInset(double margin){
-        CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
-        if (bodyPr != null) {
-            if(margin == -1) {
-                if(bodyPr.isSetRIns()) bodyPr.unsetRIns();
-            } else bodyPr.setRIns(Units.toEMU(margin));
+    public void setRightInset(double margin) {
+        if (margin == -1) {
+            _textBody.getBodyProperties().setRightInset(null);
+        } else {
+            _textBody.getBodyProperties().setRightInset(margin);
         }
     }
 
     /**
      * Sets the top inset.
+     *
      * @see #getTopInset()
      *
-     * @param margin    the top margin
+     * @param margin
+     *            the top margin
      */
-    public void setTopInset(double margin){
-        CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
-        if (bodyPr != null) {
-            if(margin == -1) {
-                if(bodyPr.isSetTIns()) bodyPr.unsetTIns();
-            } else bodyPr.setTIns(Units.toEMU(margin));
+    public void setTopInset(double margin) {
+        if (margin == -1) {
+            _textBody.getBodyProperties().setTopInset(null);
+        } else {
+            _textBody.getBodyProperties().setTopInset(margin);
         }
     }
 
-
     /**
      * @return whether to wrap words within the bounding rectangle
      */
-    public boolean getWordWrap(){
-    	CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
+    public boolean getWordWrap() {
+        CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
         if (bodyPr != null) {
-        	if(bodyPr.isSetWrap()){
-        		return bodyPr.getWrap() == STTextWrappingType.SQUARE;
-        	}
+            if (bodyPr.isSetWrap()) {
+                return bodyPr.getWrap() == STTextWrappingType.SQUARE;
+            }
         }
         return true;
     }
 
     /**
      *
-     * @param wrap  whether to wrap words within the bounding rectangle
+     * @param wrap
+     *            whether to wrap words within the bounding rectangle
      */
-    public void setWordWrap(boolean wrap){
+    public void setWordWrap(boolean wrap) {
         CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
         if (bodyPr != null) {
             bodyPr.setWrap(wrap ? STTextWrappingType.SQUARE : STTextWrappingType.NONE);
@@ -761,22 +868,36 @@ public class XSSFSimpleShape extends XSS
 
     /**
      *
-     * Specifies that a shape should be auto-fit to fully contain the text described within it.
-     * Auto-fitting is when text within a shape is scaled in order to contain all the text inside
+     * Specifies that a shape should be auto-fit to fully contain the text
+     * described within it. Auto-fitting is when text within a shape is scaled
+     * in order to contain all the text inside
      *
-     * @param value type of autofit
+     * @param value
+     *            type of autofit
      */
-    public void setTextAutofit(TextAutofit value){
+    public void setTextAutofit(TextAutofit value) {
         CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
         if (bodyPr != null) {
-            if(bodyPr.isSetSpAutoFit()) bodyPr.unsetSpAutoFit();
-            if(bodyPr.isSetNoAutofit()) bodyPr.unsetNoAutofit();
-            if(bodyPr.isSetNormAutofit()) bodyPr.unsetNormAutofit();
+            if (bodyPr.isSetSpAutoFit()) {
+                bodyPr.unsetSpAutoFit();
+            }
+            if (bodyPr.isSetNoAutofit()) {
+                bodyPr.unsetNoAutofit();
+            }
+            if (bodyPr.isSetNormAutofit()) {
+                bodyPr.unsetNormAutofit();
+            }
 
-            switch(value){
-                case NONE: bodyPr.addNewNoAutofit(); break;
-                case NORMAL: bodyPr.addNewNormAutofit(); break;
-                case SHAPE: bodyPr.addNewSpAutoFit(); break;
+            switch (value) {
+            case NONE:
+                bodyPr.addNewNoAutofit();
+                break;
+            case NORMAL:
+                bodyPr.addNewNormAutofit();
+                break;
+            case SHAPE:
+                bodyPr.addNewSpAutoFit();
+                break;
             }
         }
     }
@@ -785,18 +906,23 @@ public class XSSFSimpleShape extends XSS
      *
      * @return type of autofit
      */
-    public TextAutofit getTextAutofit(){
+    public TextAutofit getTextAutofit() {
         CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr();
         if (bodyPr != null) {
-            if(bodyPr.isSetNoAutofit()) return TextAutofit.NONE;
-            else if (bodyPr.isSetNormAutofit()) return TextAutofit.NORMAL;
-            else if (bodyPr.isSetSpAutoFit()) return TextAutofit.SHAPE;
+            if (bodyPr.isSetNoAutofit()) {
+                return TextAutofit.NONE;
+            } else if (bodyPr.isSetNormAutofit()) {
+                return TextAutofit.NORMAL;
+            } else if (bodyPr.isSetSpAutoFit()) {
+                return TextAutofit.SHAPE;
+            }
         }
         return TextAutofit.NORMAL;
     }
-    
+
     /**
-     * Gets the shape type, one of the constants defined in {@link org.apache.poi.ss.usermodel.ShapeTypes}.
+     * Gets the shape type, one of the constants defined in
+     * {@link org.apache.poi.ss.usermodel.ShapeTypes}.
      *
      * @return the shape type
      * @see org.apache.poi.ss.usermodel.ShapeTypes
@@ -808,14 +934,17 @@ public class XSSFSimpleShape extends XSS
     /**
      * Sets the shape types.
      *
-     * @param type the shape type, one of the constants defined in {@link org.apache.poi.ss.usermodel.ShapeTypes}.
+     * @param type
+     *            the shape type, one of the constants defined in
+     *            {@link org.apache.poi.ss.usermodel.ShapeTypes}.
      * @see org.apache.poi.ss.usermodel.ShapeTypes
      */
     public void setShapeType(int type) {
         ctShape.getSpPr().getPrstGeom().setPrst(STShapeType.Enum.forInt(type));
     }
 
-    protected CTShapeProperties getShapeProperties(){
+    @Override
+    protected CTShapeProperties getShapeProperties() {
         return ctShape.getSpPr();
     }
 
@@ -823,35 +952,42 @@ public class XSSFSimpleShape extends XSS
      * org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRPrElt to
      * org.openxmlformats.schemas.drawingml.x2006.main.CTFont adapter
      */
-    private static void applyAttributes(CTRPrElt pr, CTTextCharacterProperties rPr){
+    private static void applyAttributes(CTRPrElt pr, CTTextCharacterProperties rPr) {
 
-        if(pr.sizeOfBArray() > 0) rPr.setB(pr.getBArray(0).getVal());
-        if(pr.sizeOfUArray() > 0) {
+        if (pr.sizeOfBArray() > 0) {
+            rPr.setB(pr.getBArray(0).getVal());
+        }
+        if (pr.sizeOfUArray() > 0) {
             STUnderlineValues.Enum u1 = pr.getUArray(0).getVal();
-            if(u1 == STUnderlineValues.SINGLE) rPr.setU(STTextUnderlineType.SNG);
-            else if(u1 == STUnderlineValues.DOUBLE) rPr.setU(STTextUnderlineType.DBL);
-            else if(u1 == STUnderlineValues.NONE) rPr.setU(STTextUnderlineType.NONE);
+            if (u1 == STUnderlineValues.SINGLE) {
+                rPr.setU(STTextUnderlineType.SNG);
+            } else if (u1 == STUnderlineValues.DOUBLE) {
+                rPr.setU(STTextUnderlineType.DBL);
+            } else if (u1 == STUnderlineValues.NONE) {
+                rPr.setU(STTextUnderlineType.NONE);
+            }
+        }
+        if (pr.sizeOfIArray() > 0) {
+            rPr.setI(pr.getIArray(0).getVal());
         }
-        if(pr.sizeOfIArray() > 0) rPr.setI(pr.getIArray(0).getVal());
 
-        if(pr.sizeOfRFontArray() > 0) {
+        if (pr.sizeOfRFontArray() > 0) {
             CTTextFont rFont = rPr.isSetLatin() ? rPr.getLatin() : rPr.addNewLatin();
             rFont.setTypeface(pr.getRFontArray(0).getVal());
         }
 
-        if(pr.sizeOfSzArray() > 0) {
-            int sz = (int)(pr.getSzArray(0).getVal()*100);
+        if (pr.sizeOfSzArray() > 0) {
+            int sz = (int) (pr.getSzArray(0).getVal() * 100);
             rPr.setSz(sz);
         }
-        
-        if(pr.sizeOfColorArray() > 0) {
+
+        if (pr.sizeOfColorArray() > 0) {
             CTSolidColorFillProperties fill = rPr.isSetSolidFill() ? rPr.getSolidFill() : rPr.addNewSolidFill();
             org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor xlsColor = pr.getColorArray(0);
-            if(xlsColor.isSetRgb()) {
+            if (xlsColor.isSetRgb()) {
                 CTSRgbColor clr = fill.isSetSrgbClr() ? fill.getSrgbClr() : fill.addNewSrgbClr();
                 clr.setVal(xlsColor.getRgb());
-            }
-            else if(xlsColor.isSetIndexed()) {
+            } else if (xlsColor.isSetIndexed()) {
                 HSSFColor indexed = HSSFColor.getIndexHash().get((int) xlsColor.getIndexed());
                 if (indexed != null) {
                     byte[] rgb = new byte[3];
@@ -872,6 +1008,20 @@ public class XSSFSimpleShape extends XSS
 
     @Override
     public int getShapeId() {
-        return (int)ctShape.getNvSpPr().getCNvPr().getId();
+        return (int) ctShape.getNvSpPr().getCNvPr().getId();
+    }
+
+    @Override
+    public <R> Optional<R> findDefinedParagraphProperty(Function<CTTextParagraphProperties, Boolean> isSet,
+        Function<CTTextParagraphProperties, R> getter) {
+        // TODO Auto-generated method stub
+        return Optional.empty();
+    }
+
+    @Override
+    public <R> Optional<R> findDefinedRunProperty(Function<CTTextCharacterProperties, Boolean> isSet,
+        Function<CTTextCharacterProperties, R> getter) {
+        // TODO Auto-generated method stub
+        return Optional.empty();
     }
 }

Added: poi/trunk/src/ooxml/testcases/org/apache/poi/xddf/usermodel/text/TestXDDFTextBodyProperties.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/testcases/org/apache/poi/xddf/usermodel/text/TestXDDFTextBodyProperties.java?rev=1839259&view=auto
==============================================================================
--- poi/trunk/src/ooxml/testcases/org/apache/poi/xddf/usermodel/text/TestXDDFTextBodyProperties.java (added)
+++ poi/trunk/src/ooxml/testcases/org/apache/poi/xddf/usermodel/text/TestXDDFTextBodyProperties.java Sun Aug 26 21:33:16 2018
@@ -0,0 +1,81 @@
+/* ====================================================================
+   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.xddf.usermodel.text;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.apache.poi.util.Units;
+import org.junit.Test;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties;
+
+public class TestXDDFTextBodyProperties {
+
+    @Test
+    public void testProperties() throws IOException {
+        XDDFBodyProperties body = new XDDFTextBody(null).getBodyProperties();
+        CTTextBodyProperties props = body.getXmlObject();
+
+        body.setBottomInset(null);
+        assertFalse(props.isSetBIns());
+        body.setBottomInset(3.6);
+        assertTrue(props.isSetBIns());
+        assertEquals(Units.toEMU(3.6), props.getBIns());
+
+        body.setLeftInset(null);
+        assertFalse(props.isSetLIns());
+        body.setLeftInset(3.6);
+        assertTrue(props.isSetLIns());
+        assertEquals(Units.toEMU(3.6), props.getLIns());
+
+        body.setRightInset(null);
+        assertFalse(props.isSetRIns());
+        body.setRightInset(3.6);
+        assertTrue(props.isSetRIns());
+        assertEquals(Units.toEMU(3.6), props.getRIns());
+
+        body.setTopInset(null);
+        assertFalse(props.isSetTIns());
+        body.setTopInset(3.6);
+        assertTrue(props.isSetTIns());
+        assertEquals(Units.toEMU(3.6), props.getTIns());
+
+        body.setAutoFit(null);
+        assertFalse(props.isSetNoAutofit());
+        assertFalse(props.isSetNormAutofit());
+        assertFalse(props.isSetSpAutoFit());
+
+        body.setAutoFit(new XDDFNoAutoFit());
+        assertTrue(props.isSetNoAutofit());
+        assertFalse(props.isSetNormAutofit());
+        assertFalse(props.isSetSpAutoFit());
+
+        body.setAutoFit(new XDDFNormalAutoFit());
+        assertFalse(props.isSetNoAutofit());
+        assertTrue(props.isSetNormAutofit());
+        assertFalse(props.isSetSpAutoFit());
+
+        body.setAutoFit(new XDDFShapeAutoFit());
+        assertFalse(props.isSetNoAutofit());
+        assertFalse(props.isSetNormAutofit());
+        assertTrue(props.isSetSpAutoFit());
+
+    }
+}

Added: poi/trunk/src/ooxml/testcases/org/apache/poi/xddf/usermodel/text/TestXDDFTextRun.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/testcases/org/apache/poi/xddf/usermodel/text/TestXDDFTextRun.java?rev=1839259&view=auto
==============================================================================
--- poi/trunk/src/ooxml/testcases/org/apache/poi/xddf/usermodel/text/TestXDDFTextRun.java (added)
+++ poi/trunk/src/ooxml/testcases/org/apache/poi/xddf/usermodel/text/TestXDDFTextRun.java Sun Aug 26 21:33:16 2018
@@ -0,0 +1,135 @@
+/* ====================================================================
+   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.xddf.usermodel.text;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.poi.util.LocaleUtil;
+import org.apache.poi.xslf.usermodel.XMLSlideShow;
+import org.apache.poi.xslf.usermodel.XSLFSlide;
+import org.apache.poi.xslf.usermodel.XSLFTextShape;
+import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
+import org.apache.poi.xssf.usermodel.XSSFDrawing;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFTextBox;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.junit.Test;
+
+public class TestXDDFTextRun {
+
+    @Test
+    public void testTextRunPropertiesInSlide() throws IOException {
+        try (XMLSlideShow ppt = new XMLSlideShow()) {
+            XSLFSlide slide = ppt.createSlide();
+            XSLFTextShape sh = slide.createAutoShape();
+            sh.addNewTextParagraph();
+
+            XDDFTextBody body = sh.getTextBody();
+            XDDFTextParagraph para = body.getParagraph(0);
+            XDDFTextRun r = para.appendRegularRun("text");
+            assertEquals(LocaleUtil.getUserLocale().toLanguageTag(), r.getLanguage().toLanguageTag());
+
+            assertNull(r.getCharacterSpacing());
+            r.setCharacterSpacing(3.0);
+            assertEquals(3., r.getCharacterSpacing(), 0);
+            r.setCharacterSpacing(-3.0);
+            assertEquals(-3., r.getCharacterSpacing(), 0);
+            r.setCharacterSpacing(0.0);
+            assertEquals(0., r.getCharacterSpacing(), 0);
+
+            assertEquals(11.0, r.getFontSize(), 0);
+            r.setFontSize(13.0);
+            assertEquals(13.0, r.getFontSize(), 0);
+
+            assertFalse(r.isSuperscript());
+            r.setSuperscript(0.8);
+            assertTrue(r.isSuperscript());
+            r.setSuperscript(null);
+            assertFalse(r.isSuperscript());
+
+            assertFalse(r.isSubscript());
+            r.setSubscript(0.7);
+            assertTrue(r.isSubscript());
+            r.setSubscript(null);
+            assertFalse(r.isSubscript());
+
+            r.setBaseline(0.9);
+            assertTrue(r.isSuperscript());
+            r.setBaseline(-0.6);
+            assertTrue(r.isSubscript());
+        }
+    }
+
+    @Test
+    public void testTextRunPropertiesInSheet() throws IOException {
+        try (XSSFWorkbook wb = new XSSFWorkbook()) {
+            XSSFSheet sheet = wb.createSheet();
+            XSSFDrawing drawing = sheet.createDrawingPatriarch();
+
+            XSSFTextBox shape = drawing.createTextbox(new XSSFClientAnchor(0, 0, 0, 0, 2, 2, 3, 4));
+
+            shape.addNewTextParagraph().addNewTextRun().setText("Line 1");
+
+            XDDFTextBody body = shape.getTextBody();
+            XDDFTextParagraph para = body.getParagraph(1);
+            List<XDDFTextRun> runs = para.getTextRuns();
+            assertEquals(1, runs.size());
+
+            XDDFTextRun run = runs.get(0);
+            assertEquals("Line 1", run.getText());
+
+            assertFalse(run.isStrikeThrough());
+            run.setStrikeThrough(StrikeType.SINGLE_STRIKE);
+            assertTrue(run.isStrikeThrough());
+            run.setStrikeThrough(StrikeType.NO_STRIKE);
+            assertFalse(run.isStrikeThrough());
+
+            assertFalse(run.isCapitals());
+            run.setCapitals(CapsType.SMALL);
+            assertTrue(run.isCapitals());
+            run.setCapitals(CapsType.NONE);
+            assertFalse(run.isCapitals());
+
+            assertFalse(run.isBold());
+            run.setBold(true);
+            assertTrue(run.isBold());
+            run.setBold(false);
+            assertFalse(run.isBold());
+
+            assertFalse(run.isItalic());
+            run.setItalic(true);
+            assertTrue(run.isItalic());
+            run.setItalic(false);
+            assertFalse(run.isItalic());
+
+            assertFalse(run.isUnderline());
+            run.setUnderline(UnderlineType.WAVY_DOUBLE);
+            assertTrue(run.isUnderline());
+            run.setUnderline(UnderlineType.NONE);
+            assertFalse(run.isUnderline());
+
+            assertNotNull(run.getText());
+        }
+    }
+}

Modified: poi/trunk/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java?rev=1839259&r1=1839258&r2=1839259&view=diff
==============================================================================
--- poi/trunk/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java (original)
+++ poi/trunk/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java Sun Aug 26 21:33:16 2018
@@ -30,6 +30,7 @@ import java.awt.Color;
 import java.io.File;
 import java.io.IOException;
 import java.util.List;
+import java.util.stream.Collectors;
 
 import org.apache.poi.POIDataSamples;
 import org.apache.poi.hslf.usermodel.HSLFTextShape;
@@ -38,6 +39,8 @@ import org.apache.poi.sl.usermodel.Slide
 import org.apache.poi.sl.usermodel.SlideShowFactory;
 import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;
 import org.apache.poi.sl.usermodel.VerticalAlignment;
+import org.apache.poi.xddf.usermodel.text.XDDFBodyProperties;
+import org.apache.poi.xddf.usermodel.text.XDDFTextBody;
 import org.apache.poi.xslf.XSLFTestDataSamples;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -83,6 +86,8 @@ public class TestXSLFTextShape {
         assertEquals("Title Slide",layout.getName());
 
         XSLFTextShape shape1 = (XSLFTextShape)shapes.get(0);
+        XDDFTextBody tb1 = shape1.getTextBody();
+        XDDFBodyProperties tbp1 = tb1.getBodyProperties();
         CTPlaceholder ph1 = shape1.getPlaceholderDetails().getCTPlaceholder(false);
         assertEquals(STPlaceholderType.CTR_TITLE, ph1.getType());
         // anchor is not defined in the shape
@@ -104,15 +109,24 @@ public class TestXSLFTextShape {
         assertEquals(3.6, shape1.getTopInset(), 0);  // 0.05"
         assertEquals(3.6, shape1.getBottomInset(), 0); // 0.05"
         assertEquals(VerticalAlignment.MIDDLE, shape1.getVerticalAlignment());
+        assertNull(tbp1.getLeftInset());
+        assertNull(tbp1.getRightInset());
+        assertNull(tbp1.getBottomInset());
+        assertNull(tbp1.getTopInset());
+        assertNull(tbp1.getAnchoring());
 
         // now check text properties
         assertEquals("Centered Title", shape1.getText());
+        assertEquals("Centered Title",
+            tb1.getParagraphs().stream().map(p -> p.getText()).collect(Collectors.joining("\n")));
         XSLFTextRun r1 = shape1.getTextParagraphs().get(0).getTextRuns().get(0);
         assertEquals("Calibri", r1.getFontFamily());
         assertEquals(44.0, r1.getFontSize(), 0);
         assertTrue(sameColor(Color.black, r1.getFontColor()));
 
         XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1);
+        XDDFTextBody tb2 = shape2.getTextBody();
+        XDDFBodyProperties tbp2 = tb2.getBodyProperties();
         CTPlaceholder ph2 = shape2.getPlaceholderDetails().getCTPlaceholder(false);
         assertEquals(STPlaceholderType.SUB_TITLE, ph2.getType());
         // anchor is not defined in the shape
@@ -134,8 +148,14 @@ public class TestXSLFTextShape {
         assertEquals(3.6, shape2.getTopInset(), 0);  // 0.05"
         assertEquals(3.6, shape2.getBottomInset(), 0); // 0.05"
         assertEquals(VerticalAlignment.TOP, shape2.getVerticalAlignment());
+        assertNull(tbp2.getLeftInset());
+        assertNull(tbp2.getRightInset());
+        assertNull(tbp2.getBottomInset());
+        assertNull(tbp2.getTopInset());
+        assertNull(tbp2.getAnchoring());
 
         assertEquals("subtitle", shape2.getText());
+        assertEquals("subtitle", tb2.getParagraphs().stream().map(p -> p.getText()).collect(Collectors.joining("\n")));
         XSLFTextRun r2 = shape2.getTextParagraphs().get(0).getTextRuns().get(0);
         assertEquals("Calibri", r2.getFontFamily());
         assertEquals(32.0, r2.getFontSize(), 0);

Modified: poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSimpleShape.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSimpleShape.java?rev=1839259&r1=1839258&r2=1839259&view=diff
==============================================================================
--- poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSimpleShape.java (original)
+++ poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSimpleShape.java Sun Aug 26 21:33:16 2018
@@ -16,12 +16,23 @@
 ==================================================================== */
 package org.apache.poi.xssf.usermodel;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 
 import java.awt.Color;
 import java.io.IOException;
+import java.util.List;
 
 import org.apache.poi.ss.usermodel.VerticalAlignment;
+import org.apache.poi.xddf.usermodel.text.XDDFBodyProperties;
+import org.apache.poi.xddf.usermodel.text.XDDFNoAutoFit;
+import org.apache.poi.xddf.usermodel.text.XDDFNormalAutoFit;
+import org.apache.poi.xddf.usermodel.text.XDDFShapeAutoFit;
+import org.apache.poi.xddf.usermodel.text.XDDFTextBody;
+import org.apache.poi.xddf.usermodel.text.XDDFTextParagraph;
 import org.junit.Test;
 
 public class TestXSSFSimpleShape {
@@ -31,43 +42,53 @@ public class TestXSSFSimpleShape {
         try {
             XSSFSheet sheet = wb.createSheet();
             XSSFDrawing drawing = sheet.createDrawingPatriarch();
-    
+
             XSSFTextBox shape = drawing.createTextbox(new XSSFClientAnchor(0, 0, 0, 0, 2, 2, 3, 4));
-            
+
             XSSFRichTextString rt = new XSSFRichTextString("Test String");
-            
+
             XSSFFont font = wb.createFont();
             Color color = new Color(0, 255, 255);
             font.setColor(new XSSFColor(color, wb.getStylesSource().getIndexedColors()));
             font.setFontName("Arial");
             rt.applyFont(font);
-    
+
             shape.setText(rt);
 
             assertNotNull(shape.getCTShape());
             assertNotNull(shape.iterator());
             assertNotNull(XSSFSimpleShape.prototype());
-            
-            for(ListAutoNumber nr : ListAutoNumber.values()) {
+
+            for (ListAutoNumber nr : ListAutoNumber.values()) {
                 shape.getTextParagraphs().get(0).setBullet(nr);
                 assertNotNull(shape.getText());
             }
-            
+
             shape.getTextParagraphs().get(0).setBullet(false);
             assertNotNull(shape.getText());
 
             shape.setText("testtext");
             assertEquals("testtext", shape.getText());
-            
+
             shape.setText(new XSSFRichTextString());
             assertEquals("null", shape.getText());
-            
+
             shape.addNewTextParagraph();
             shape.addNewTextParagraph("test-other-text");
             shape.addNewTextParagraph(new XSSFRichTextString("rtstring"));
             shape.addNewTextParagraph(new XSSFRichTextString());
             assertEquals("null\n\ntest-other-text\nrtstring\nnull", shape.getText());
-            
+
+            XDDFTextBody body = shape.getTextBody();
+            assertNotNull(body);
+            List<XDDFTextParagraph> paragraphs = body.getParagraphs();
+            assertEquals(5, paragraphs.size());
+            assertEquals("null", body.getParagraph(0).getText());
+            assertEquals("", body.getParagraph(1).getText());
+            assertEquals("test-other-text", body.getParagraph(2).getText());
+            assertEquals("rtstring", body.getParagraph(3).getText());
+            assertEquals("null", body.getParagraph(4).getText());
+
             assertEquals(TextHorizontalOverflow.OVERFLOW, shape.getTextHorizontalOverflow());
             shape.setTextHorizontalOverflow(TextHorizontalOverflow.CLIP);
             assertEquals(TextHorizontalOverflow.CLIP, shape.getTextHorizontalOverflow());
@@ -77,7 +98,7 @@ public class TestXSSFSimpleShape {
             assertEquals(TextHorizontalOverflow.OVERFLOW, shape.getTextHorizontalOverflow());
             shape.setTextHorizontalOverflow(null);
             assertEquals(TextHorizontalOverflow.OVERFLOW, shape.getTextHorizontalOverflow());
-            
+
             assertEquals(TextVerticalOverflow.OVERFLOW, shape.getTextVerticalOverflow());
             shape.setTextVerticalOverflow(TextVerticalOverflow.CLIP);
             assertEquals(TextVerticalOverflow.CLIP, shape.getTextVerticalOverflow());
@@ -108,38 +129,57 @@ public class TestXSSFSimpleShape {
             shape.setTextDirection(null);
             assertEquals(TextDirection.HORIZONTAL, shape.getTextDirection());
 
+            XDDFBodyProperties props = body.getBodyProperties();
+            assertNotNull(props);
+
             assertEquals(3.6, shape.getBottomInset(), 0.01);
+            assertNull(props.getBottomInset());
             shape.setBottomInset(12.32);
             assertEquals(12.32, shape.getBottomInset(), 0.01);
+            assertEquals(12.32, props.getBottomInset(), 0.01);
             shape.setBottomInset(-1);
             assertEquals(3.6, shape.getBottomInset(), 0.01);
+            assertNull(props.getBottomInset());
             shape.setBottomInset(-1);
             assertEquals(3.6, shape.getBottomInset(), 0.01);
-            
+            assertNull(props.getBottomInset());
+
             assertEquals(3.6, shape.getLeftInset(), 0.01);
+            assertNull(props.getLeftInset());
             shape.setLeftInset(12.31);
             assertEquals(12.31, shape.getLeftInset(), 0.01);
+            assertEquals(12.31, props.getLeftInset(), 0.01);
             shape.setLeftInset(-1);
             assertEquals(3.6, shape.getLeftInset(), 0.01);
+            assertNull(props.getLeftInset());
             shape.setLeftInset(-1);
             assertEquals(3.6, shape.getLeftInset(), 0.01);
+            assertNull(props.getLeftInset());
 
             assertEquals(3.6, shape.getRightInset(), 0.01);
+            assertNull(props.getRightInset());
             shape.setRightInset(13.31);
             assertEquals(13.31, shape.getRightInset(), 0.01);
+            assertEquals(13.31, props.getRightInset(), 0.01);
             shape.setRightInset(-1);
             assertEquals(3.6, shape.getRightInset(), 0.01);
+            assertNull(props.getRightInset());
             shape.setRightInset(-1);
             assertEquals(3.6, shape.getRightInset(), 0.01);
+            assertNull(props.getRightInset());
 
             assertEquals(3.6, shape.getTopInset(), 0.01);
+            assertNull(props.getTopInset());
             shape.setTopInset(23.31);
             assertEquals(23.31, shape.getTopInset(), 0.01);
+            assertEquals(23.31, props.getTopInset(), 0.01);
             shape.setTopInset(-1);
             assertEquals(3.6, shape.getTopInset(), 0.01);
+            assertNull(props.getTopInset());
             shape.setTopInset(-1);
             assertEquals(3.6, shape.getTopInset(), 0.01);
-            
+            assertNull(props.getTopInset());
+
             assertTrue(shape.getWordWrap());
             shape.setWordWrap(false);
             assertFalse(shape.getWordWrap());
@@ -147,23 +187,27 @@ public class TestXSSFSimpleShape {
             assertTrue(shape.getWordWrap());
 
             assertEquals(TextAutofit.NORMAL, shape.getTextAutofit());
+            assertTrue(props.getAutoFit() instanceof XDDFNormalAutoFit);
             shape.setTextAutofit(TextAutofit.NORMAL);
             assertEquals(TextAutofit.NORMAL, shape.getTextAutofit());
+            assertTrue(props.getAutoFit() instanceof XDDFNormalAutoFit);
             shape.setTextAutofit(TextAutofit.SHAPE);
             assertEquals(TextAutofit.SHAPE, shape.getTextAutofit());
+            assertTrue(props.getAutoFit() instanceof XDDFShapeAutoFit);
             shape.setTextAutofit(TextAutofit.NONE);
             assertEquals(TextAutofit.NONE, shape.getTextAutofit());
-            
+            assertTrue(props.getAutoFit() instanceof XDDFNoAutoFit);
+
             assertEquals(5, shape.getShapeType());
             shape.setShapeType(23);
             assertEquals(23, shape.getShapeType());
 
             // TODO: should this be supported?
-//            shape.setShapeType(-1);
-//            assertEquals(-1, shape.getShapeType());
-//            shape.setShapeType(-1);
-//            assertEquals(-1, shape.getShapeType());
-            
+            // shape.setShapeType(-1);
+            // assertEquals(-1, shape.getShapeType());
+            // shape.setShapeType(-1);
+            // assertEquals(-1, shape.getShapeType());
+
             assertNotNull(shape.getShapeProperties());
         } finally {
             wb.close();



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org