]> source.dussan.org Git - poi.git/commitdiff
#56570 - RecordType has repeat by code type 3009
authorAndreas Beeker <kiwiwings@apache.org>
Thu, 31 Dec 2015 22:10:17 +0000 (22:10 +0000)
committerAndreas Beeker <kiwiwings@apache.org>
Thu, 31 Dec 2015 22:10:17 +0000 (22:10 +0000)
#58159 - getHeaderText() and getFooterText() duplicate text in sheet.getTextRuns()

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1722476 13f79535-47bb-0310-9956-ffa450edef68

53 files changed:
src/examples/src/org/apache/poi/hslf/examples/SoundFinder.java
src/examples/src/org/apache/poi/xslf/usermodel/Tutorial3.java
src/java/org/apache/poi/ddf/EscherClientDataRecord.java
src/java/org/apache/poi/sl/draw/DrawMasterSheet.java
src/java/org/apache/poi/sl/usermodel/Placeholder.java [new file with mode: 0644]
src/java/org/apache/poi/sl/usermodel/SimpleShape.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFBackground.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFConnectorShape.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideLayout.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideMaster.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFNotes.java
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSimpleShape.java
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextBox.java
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java
src/scratchpad/src/org/apache/poi/hslf/dev/PPTXMLDump.java
src/scratchpad/src/org/apache/poi/hslf/dev/SLWTListing.java
src/scratchpad/src/org/apache/poi/hslf/dev/SlideShowDumper.java
src/scratchpad/src/org/apache/poi/hslf/model/ActiveXShape.java
src/scratchpad/src/org/apache/poi/hslf/model/MovieShape.java
src/scratchpad/src/org/apache/poi/hslf/model/OLEShape.java
src/scratchpad/src/org/apache/poi/hslf/record/ExObjRefAtom.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hslf/record/HSLFEscherClientDataRecord.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hslf/record/HSLFEscherRecordFactory.java
src/scratchpad/src/org/apache/poi/hslf/record/OEPlaceholderAtom.java
src/scratchpad/src/org/apache/poi/hslf/record/OEShapeAtom.java [deleted file]
src/scratchpad/src/org/apache/poi/hslf/record/PPDrawing.java
src/scratchpad/src/org/apache/poi/hslf/record/Record.java
src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java
src/scratchpad/src/org/apache/poi/hslf/record/RoundTripHFPlaceholder12.java
src/scratchpad/src/org/apache/poi/hslf/record/TxMasterStyleAtom.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFHyperlink.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPlaceholder.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShape.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShapeFactory.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSheet.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSimpleShape.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlide.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTable.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextRun.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextShape.java
src/scratchpad/testcases/org/apache/poi/hslf/TestReWrite.java
src/scratchpad/testcases/org/apache/poi/hslf/record/TestRecordTypes.java
src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java
src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestNumberedList.java

index 75180c2d1925d6e9e218209955f4fa902d35babe..ec0cec8dc1e99ada7e5801887152a0d5524b001a 100644 (file)
 ==================================================================== */
 package org.apache.poi.hslf.examples;
 import java.io.FileInputStream;
+import java.io.IOException;
 
-import org.apache.poi.ddf.EscherClientDataRecord;
-import org.apache.poi.ddf.EscherContainerRecord;
-import org.apache.poi.ddf.EscherRecord;
-import org.apache.poi.hslf.record.InteractiveInfo;
 import org.apache.poi.hslf.record.InteractiveInfoAtom;
-import org.apache.poi.hslf.record.Record;
+import org.apache.poi.hslf.record.RecordTypes;
 import org.apache.poi.hslf.usermodel.HSLFShape;
 import org.apache.poi.hslf.usermodel.HSLFSlide;
 import org.apache.poi.hslf.usermodel.HSLFSlideShow;
@@ -30,12 +27,11 @@ import org.apache.poi.hslf.usermodel.HSLFSoundData;
 
 /**
  * For each slide iterate over shapes and found associated sound data.
- *
- * @author Yegor Kozlov
  */
 public class SoundFinder {
-    public static void main(String[] args) throws Exception {
-        HSLFSlideShow ppt = new HSLFSlideShow(new FileInputStream(args[0]));
+    public static void main(String[] args) throws IOException {
+        FileInputStream fis = new FileInputStream(args[0]);
+        HSLFSlideShow ppt = new HSLFSlideShow(fis);
         HSLFSoundData[] sounds = ppt.getSoundData();
 
         for (HSLFSlide slide : ppt.getSlides()) {
@@ -49,6 +45,8 @@ public class SoundFinder {
                 System.out.println("  " + sounds[soundRef].getSoundType());
             }
         }
+        ppt.close();
+        fis.close();
     }
 
     /**
@@ -59,19 +57,9 @@ public class SoundFinder {
     protected static int getSoundReference(HSLFShape shape){
         int soundRef = -1;
         //dive into the shape container and search for InteractiveInfoAtom
-        EscherContainerRecord spContainer = shape.getSpContainer();
-        for (EscherRecord obj : spContainer.getChildRecords()) {
-            if (obj.getRecordId() == EscherClientDataRecord.RECORD_ID) {
-                byte[] data = obj.serialize();
-                for (Record record : Record.findChildRecords(data, 8, data.length - 8)) {
-                    if (record instanceof InteractiveInfo) {
-                        InteractiveInfoAtom info = ((InteractiveInfo)record).getInteractiveInfoAtom();
-                        if (info.getAction() == InteractiveInfoAtom.ACTION_MEDIA) {
-                            soundRef = info.getSoundRef();
-                        }
-                    }
-                }
-            }
+        InteractiveInfoAtom info = shape.getClientDataRecord(RecordTypes.InteractiveInfo.typeID);
+        if (info != null && info.getAction() == InteractiveInfoAtom.ACTION_MEDIA) {
+            soundRef = info.getSoundRef();
         }
         return soundRef;
     }
index 28c1fa3f1202331787cfa15ac0cc6d7a9912fb2f..4433605f34c3332cd785a75f46ada4b128dfd896 100644 (file)
@@ -23,7 +23,7 @@ import java.awt.Rectangle;
 import java.io.FileOutputStream;\r
 import java.io.IOException;\r
 \r
-import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;\r
+import org.apache.poi.sl.usermodel.Placeholder;\r
 \r
 /**\r
  * How to set slide title\r
index bea83a83cf96a684efbd2f90392da244f4d32391..0b307ad5328d0561594c74332456507b0d0ecbc6 100644 (file)
@@ -76,7 +76,7 @@ public class EscherClientDataRecord
     public String toString()
     {
         String nl = System.getProperty("line.separator");
-        String extraData = HexDump.dump(this.remainingData, 0, 0);
+        String extraData = HexDump.dump(getRemainingData(), 0, 0);
         return getClass().getName() + ":" + nl +
                 "  RecordId: 0x" + HexDump.toHex(RECORD_ID) + nl +
                 "  Version: 0x" + HexDump.toHex(getVersion()) + nl +
@@ -88,7 +88,7 @@ public class EscherClientDataRecord
 
     @Override
     public String toXml(String tab) {
-        String extraData = HexDump.dump(this.remainingData, 0, 0).trim();
+        String extraData = HexDump.dump(getRemainingData(), 0, 0).trim();
         StringBuilder builder = new StringBuilder();
         builder.append(tab).append(formatXmlRecordHeader(getClass().getSimpleName(), HexDump.toHex(getRecordId()),
                 HexDump.toHex(getVersion()), HexDump.toHex(getInstance())))
index 76ae92de709351142bc9307a0cc8e9fc35e532bc..3bcedbe850c979ee12010d63fac4b14ac850b4b1 100644 (file)
@@ -33,7 +33,12 @@ public class DrawMasterSheet extends DrawSheet {
      * for instance, slide masters and layouts don't display placeholders\r
      */\r
     @Override\r
-    protected boolean canDraw(Shape<?,?> shape){\r
-        return !(shape instanceof SimpleShape) || !((SimpleShape<?,?>)shape).isPlaceholder();\r
+    protected boolean canDraw(Shape<?,?> shape) {\r
+        if (shape instanceof SimpleShape) {\r
+            Placeholder ph = ((SimpleShape<?,?>)shape).getPlaceholder();\r
+            return ph == null;\r
+        } else {\r
+            return true;\r
+        }\r
     }\r
 }\r
diff --git a/src/java/org/apache/poi/sl/usermodel/Placeholder.java b/src/java/org/apache/poi/sl/usermodel/Placeholder.java
new file mode 100644 (file)
index 0000000..a3bc9c7
--- /dev/null
@@ -0,0 +1,138 @@
+/* ====================================================================\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to You under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+       http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+==================================================================== */\r
+\r
+package org.apache.poi.sl.usermodel;\r
+\r
+public enum Placeholder {\r
+    /**\r
+     * No placeholder shape.\r
+     */\r
+    NONE(0,0,0,0,0),\r
+    /**\r
+     * Title text placeholder shape.\r
+     */\r
+    TITLE(13,1,1,1,1),\r
+    /**\r
+     * Body text placeholder shape.\r
+     */\r
+    BODY(14,2,12,6,2),\r
+    /**\r
+     * Center title text placeholder shape.\r
+     */\r
+    CENTERED_TITLE(15,3,3,3,3),\r
+    /**\r
+     * Sub-title text placeholder shape.\r
+     */\r
+    SUBTITLE(16,4,4,4,4),\r
+    /**\r
+     * Date placeholder shape.\r
+     */\r
+    DATETIME(7,7,7,7,5),\r
+    /**\r
+     * Slide number placeholder shape.\r
+     */\r
+    SLIDE_NUMBER(8,8,8,8,6),\r
+    /**\r
+     * Footer placeholder shape.\r
+     */\r
+    FOOTER(9,9,9,9,7),\r
+    /**\r
+     *  Header placeholder shape.\r
+     */\r
+    HEADER(10,10,10,10,8),\r
+    /**\r
+     * Object placeholder shape.\r
+     */\r
+    CONTENT(19,19,19,19,9),\r
+    /**\r
+     * Graph object placeholder shape.\r
+     */\r
+    CHART(20,20,20,20,10),\r
+    /**\r
+     * Table object placeholder shape.\r
+     */\r
+    TABLE(21,21,21,21,11),\r
+    /**\r
+     * Clipart object placeholder shape.\r
+     */\r
+    CLIP_ART(22,22,22,22,12),\r
+    /**\r
+     * Organization chart object placeholder shape.\r
+     */\r
+    DGM(23,23,23,23,13),\r
+    /**\r
+     * Media object placeholder shape.\r
+     */\r
+    MEDIA(24,24,24,24,14),\r
+    /**\r
+     * Slide image placeholder shape.\r
+     */\r
+    SLIDE_IMAGE(11,11,11,5,15),\r
+    /**\r
+     * Picture object placeholder shape.\r
+     */\r
+    PICTURE(26,26,26,26,16),\r
+    /**\r
+     * Vertical object placeholder shape.\r
+     */\r
+    VERTICAL_OBJECT(25,25,25,25,-2),\r
+    /**\r
+     * Vertical title text placeholder shape.\r
+     */\r
+    VERTICAL_TEXT_TITLE(17,17,17,17,-2),\r
+    /**\r
+     * Vertical body text placeholder shape.\r
+     */\r
+    VERTICAL_TEXT_BODY(18,18,18,18,-2)\r
+    ;\r
+    \r
+    public final int nativeSlideId;\r
+    public final int nativeSlideMasterId;\r
+    public final int nativeNotesId;\r
+    public final int nativeNotesMasterId;\r
+    public final int ooxmlId;\r
+    \r
+    Placeholder(int nativeSlideId, int nativeSlideMasterId, int nativeNotesId, int nativeNotesMasterId, int ooxmlId) {\r
+        this.nativeSlideId = nativeSlideId;\r
+        this.nativeSlideMasterId = nativeSlideMasterId;\r
+        this.nativeNotesId = nativeNotesId;\r
+        this.nativeNotesMasterId = nativeNotesMasterId;\r
+        this.ooxmlId = ooxmlId;\r
+    }\r
+    \r
+    public static Placeholder lookupNative(int nativeId) {\r
+        for (Placeholder ph : values()) {\r
+            if (ph.nativeSlideId == nativeId ||\r
+                ph.nativeSlideMasterId == nativeId || \r
+                ph.nativeNotesId == nativeId ||\r
+                ph.nativeNotesMasterId == nativeId\r
+            ) {\r
+                return ph;\r
+            }\r
+        }\r
+        return null;\r
+    }\r
+    \r
+    public static Placeholder lookupOoxml(int ooxmlId) {\r
+        for (Placeholder ph : values()) {\r
+            if (ph.ooxmlId == ooxmlId) {\r
+                return ph;\r
+            }\r
+        }\r
+        return null;\r
+    }\r
+}
\ No newline at end of file
index 8ed151b496ee5dc703dd012855a64312e81589c6..53ee6de5294c3327bc0af3f960dcc8f52b54b612 100644 (file)
@@ -28,25 +28,6 @@ public interface SimpleShape<
     P extends TextParagraph<S,P,?>
 > extends Shape<S,P>, IAdjustableShape, PlaceableShape<S,P> {
 
-    enum Placeholder {
-        TITLE,
-        BODY,
-        CENTERED_TITLE,
-        SUBTITLE,
-        DATETIME,
-        SLIDE_NUMBER,
-        FOOTER,
-        HEADER,
-        CONTENT,
-        CHART,
-        TABLE,
-        CLIP_ART,
-        DGM,
-        MEDIA,
-        SLIDE_IMAGE,
-        PICTURE
-    }
-    
     FillStyle getFillStyle();
     
     LineDecoration getLineDecoration();
@@ -69,7 +50,20 @@ public interface SimpleShape<
     ShapeType getShapeType();
     void setShapeType(ShapeType type);
 
-    boolean isPlaceholder();
+    /**
+     * @return the placeholder or null if none is assigned
+     * @see #setPlaceholder(Placeholder)
+     */
+    Placeholder getPlaceholder();
+    
+    /**
+     * Specifies that the corresponding shape should be represented by the generating application
+     * as a placeholder. When a shape is considered a placeholder by the generating application
+     * it can have special properties to alert the user that they may enter content into the shape.
+     * 
+     * @param placeholder the placeholder or null to remove the reference to the placeholder
+     */
+    void setPlaceholder(Placeholder placeholder);
 
        Shadow<S,P> getShadow();
 
index 6dbdf2d4f123fbc8085c2ba7806eecd722c16a30..290b5f49450cd99106fb91f27cae75cd9509b86d 100644 (file)
@@ -21,11 +21,13 @@ import java.awt.Color;
 import java.awt.Dimension;\r
 import java.awt.geom.Rectangle2D;\r
 \r
+import org.apache.poi.POIXMLException;\r
 import org.apache.poi.sl.draw.DrawPaint;\r
 import org.apache.poi.sl.usermodel.Background;\r
 import org.apache.poi.sl.usermodel.ColorStyle;\r
 import org.apache.poi.sl.usermodel.FillStyle;\r
 import org.apache.poi.sl.usermodel.PaintStyle;\r
+import org.apache.poi.sl.usermodel.Placeholder;\r
 import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;\r
 import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;\r
 import org.openxmlformats.schemas.presentationml.x2006.main.CTBackground;\r
@@ -70,4 +72,10 @@ public class XSLFBackground extends XSLFSimpleShape
     protected CTTransform2D getXfrm() {\r
         return CTTransform2D.Factory.newInstance();\r
     }\r
+    \r
+    @Override\r
+    public void setPlaceholder(Placeholder placeholder) {\r
+        // extending XSLFSimpleShape is a bit unlucky ...\r
+        throw new POIXMLException("Can't set a placeholder for a background");\r
+    }\r
 }\r
index ef8a2adf0f6a0c6c7514eef4a319ae18b281aacd..0ca895efa891476bcd3c3b8abba2e111df324b90 100644 (file)
@@ -19,7 +19,9 @@
 \r
 package org.apache.poi.xslf.usermodel;\r
 \r
+import org.apache.poi.POIXMLException;\r
 import org.apache.poi.sl.usermodel.ConnectorShape;\r
+import org.apache.poi.sl.usermodel.Placeholder;\r
 import org.apache.poi.util.Beta;\r
 import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;\r
 import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D;\r
@@ -69,4 +71,8 @@ public class XSLFConnectorShape extends XSLFSimpleShape
         return null;\r
     }\r
 \r
+    @Override\r
+    public void setPlaceholder(Placeholder placeholder) {\r
+        throw new POIXMLException("A connector shape can't be a placeholder.");\r
+    }\r
 }
\ No newline at end of file
index 48c8babddf99ccf35ac6f3ec0a2e760095d8a579..b9d7e37f6b6c6cc69b2412361118a8afc2aef61e 100644 (file)
@@ -28,6 +28,7 @@ import org.apache.poi.POIXMLException;
 import org.apache.poi.openxml4j.opc.PackagePart;\r
 import org.apache.poi.openxml4j.opc.PackageRelationship;\r
 import org.apache.poi.sl.usermodel.PictureShape;\r
+import org.apache.poi.sl.usermodel.Placeholder;\r
 import org.apache.poi.util.Beta;\r
 import org.apache.xmlbeans.XmlCursor;\r
 import org.apache.xmlbeans.XmlObject;\r
@@ -118,6 +119,12 @@ public class XSLFPictureShape extends XSLFSimpleShape
         }\r
         return _data;\r
     }\r
+\r
+    @Override\r
+    public void setPlaceholder(Placeholder placeholder) {\r
+        super.setPlaceholder(placeholder);\r
+    }\r
+    \r
     \r
     /**\r
      * For an external linked picture, return the last-seen\r
@@ -168,7 +175,6 @@ public class XSLFPictureShape extends XSLFSimpleShape
         return (r == null) ? null : new Insets(r.getT(), r.getL(), r.getB(), r.getR());\r
     }\r
 \r
-    @SuppressWarnings("deprecation")\r
     @Override\r
     void copy(XSLFShape sh){\r
         super.copy(sh);\r
index dc1ef5af2c23b9bd8920c838944a30118b93258e..f25c9278edc6bea52d2bbd847afa0423ec47a01e 100644 (file)
@@ -33,7 +33,7 @@ import org.apache.poi.sl.usermodel.PaintStyle;
 import org.apache.poi.sl.usermodel.PaintStyle.GradientPaint;\r
 import org.apache.poi.sl.usermodel.PaintStyle.TexturePaint;\r
 import org.apache.poi.sl.usermodel.PlaceableShape;\r
-import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;\r
+import org.apache.poi.sl.usermodel.Placeholder;\r
 import org.apache.poi.sl.usermodel.Shape;\r
 import org.apache.poi.util.Beta;\r
 import org.apache.poi.util.Internal;\r
@@ -255,6 +255,14 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
         return _ph;\r
     }\r
 \r
+    public Placeholder getPlaceholder() {\r
+        CTPlaceholder ph = getCTPlaceholder();\r
+        if (ph == null || !ph.isSetType()) {\r
+            return null;\r
+        }\r
+        return Placeholder.lookupOoxml(ph.getType().intValue());\r
+    }\r
+    \r
     /**\r
      * Specifies that the corresponding shape should be represented by the generating application\r
      * as a placeholder. When a shape is considered a placeholder by the generating application\r
@@ -272,7 +280,7 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
             if (nv.isSetPh()) nv.unsetPh();\r
             _ph = null;\r
         } else {\r
-            nv.addNewPh().setType(STPlaceholderType.Enum.forInt(placeholder.ordinal() + 1));\r
+            nv.addNewPh().setType(STPlaceholderType.Enum.forInt(placeholder.ooxmlId));\r
         }\r
     }\r
     \r
@@ -442,7 +450,6 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
     \r
     protected PaintStyle selectPaint(final CTGradientFillProperties gradFill, CTSchemeColor phClr) {\r
 \r
-        @SuppressWarnings("deprecation")\r
         final CTGradientStop[] gs = gradFill.getGsLst().getGsArray();\r
 \r
         Arrays.sort(gs, new Comparator<CTGradientStop>() {\r
index 5dac2181e97af784bbabffb6cd1e205fb533f497..e8fa1da034c80e19248b5fd20c1f3034509d62c5 100644 (file)
@@ -42,8 +42,8 @@ import org.apache.poi.sl.draw.DrawFactory;
 import org.apache.poi.sl.draw.DrawPictureShape;
 import org.apache.poi.sl.draw.Drawable;
 import org.apache.poi.sl.usermodel.PictureData;
+import org.apache.poi.sl.usermodel.Placeholder;
 import org.apache.poi.sl.usermodel.Sheet;
-import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
 import org.apache.poi.util.Beta;
 import org.apache.poi.util.IOUtils;
 import org.apache.poi.util.Internal;
index c6bbb1ff04652c346ab4c786d2b6d7b161c2c43f..8b92ec231600b4f7affbd2b4d28aa984e961cb85 100644 (file)
@@ -34,6 +34,7 @@ import org.apache.poi.sl.usermodel.LineDecoration;
 import org.apache.poi.sl.usermodel.LineDecoration.DecorationShape;\r
 import org.apache.poi.sl.usermodel.LineDecoration.DecorationSize;\r
 import org.apache.poi.sl.usermodel.PaintStyle;\r
+import org.apache.poi.sl.usermodel.Placeholder;\r
 import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;\r
 import org.apache.poi.sl.usermodel.ShapeType;\r
 import org.apache.poi.sl.usermodel.SimpleShape;\r
@@ -815,7 +816,6 @@ public abstract class XSLFSimpleShape extends XSLFShape
         return ph != null;\r
     }\r
 \r
-    @SuppressWarnings("deprecation")\r
     public Guide getAdjustValue(String name) {\r
         CTPresetGeometry2D prst = getSpPr().getPrstGeom();\r
         if (prst.isSetAvLst()) {\r
@@ -918,4 +918,9 @@ public abstract class XSLFSimpleShape extends XSLFShape
             }\r
         }\r
     }\r
+    \r
+    @Override\r
+    public void setPlaceholder(Placeholder placeholder) {\r
+        super.setPlaceholder(placeholder);\r
+    }\r
 }\r
index 4be19ea435a1504967711632d21dba5ab4565e4f..491062163c7c0baed3c0cfd252832db71d997718 100644 (file)
@@ -27,7 +27,7 @@ import org.apache.poi.openxml4j.opc.PackageRelationship;
 import org.apache.poi.sl.draw.DrawFactory;
 import org.apache.poi.sl.draw.Drawable;
 import org.apache.poi.sl.usermodel.Notes;
-import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
+import org.apache.poi.sl.usermodel.Placeholder;
 import org.apache.poi.sl.usermodel.Slide;
 import org.apache.poi.util.Beta;
 import org.apache.xmlbeans.XmlException;
index 95835e49528da24a9781aab25032eaaf1478afa5..1d49b068e89b3755e3e93c424afff516503bd158 100644 (file)
@@ -24,7 +24,7 @@ import org.apache.poi.POIXMLDocumentPart;
 import org.apache.poi.openxml4j.opc.PackagePart;
 import org.apache.poi.openxml4j.opc.PackageRelationship;
 import org.apache.poi.sl.usermodel.MasterSheet;
-import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
+import org.apache.poi.sl.usermodel.Placeholder;
 import org.apache.poi.util.Beta;
 import org.apache.poi.util.Internal;
 import org.apache.xmlbeans.XmlException;
index cf45bf74468d97878589725244b1d7543011e9e5..34d282cd07f742da1bfe1f233cf0a2a2299f4bcf 100644 (file)
@@ -27,7 +27,7 @@ import org.apache.poi.POIXMLDocumentPart;
 import org.apache.poi.openxml4j.opc.PackagePart;
 import org.apache.poi.openxml4j.opc.PackageRelationship;
 import org.apache.poi.sl.usermodel.MasterSheet;
-import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
+import org.apache.poi.sl.usermodel.Placeholder;
 import org.apache.poi.util.Beta;
 import org.apache.xmlbeans.XmlException;
 import org.openxmlformats.schemas.drawingml.x2006.main.CTColorMapping;
index 4a1856d7fdadf2f32439ffa5727ed20317fee743..d78749c750bce4abf16036c44d3f3d8961480096 100644 (file)
@@ -28,6 +28,7 @@ import org.apache.poi.POIXMLException;
 import org.apache.poi.sl.draw.DrawFactory;
 import org.apache.poi.sl.draw.DrawTextShape;
 import org.apache.poi.sl.usermodel.Insets2D;
+import org.apache.poi.sl.usermodel.Placeholder;
 import org.apache.poi.sl.usermodel.TextShape;
 import org.apache.poi.sl.usermodel.VerticalAlignment;
 import org.apache.poi.util.Beta;
@@ -54,7 +55,6 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
     implements TextShape<XSLFShape,XSLFTextParagraph> {
     private final List<XSLFTextParagraph> _paragraphs;
 
-    @SuppressWarnings("deprecation")
     /*package*/ XSLFTextShape(XmlObject shape, XSLFSheet sheet) {
         super(shape, sheet);
 
@@ -497,13 +497,13 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
     public void setPlaceholder(Placeholder placeholder) {
         super.setPlaceholder(placeholder);
     }
-
+    
     public Placeholder getTextType(){
         CTPlaceholder ph = getCTPlaceholder();
         if (ph == null) return null;
 
         int val = ph.getType().intValue();
-        return Placeholder.values()[val - 1];
+        return Placeholder.lookupOoxml(val);
     }
 
     @Override
index 02fac93bc864b44a3d4b3801f9ddf017f1681316..ae18fc70c219944d85b5b71a719ab7d806202b92 100644 (file)
@@ -22,7 +22,7 @@ import static org.junit.Assert.assertNull;
 \r
 import java.io.IOException;\r
 \r
-import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;\r
+import org.apache.poi.sl.usermodel.Placeholder;\r
 import org.apache.poi.xslf.XSLFTestDataSamples;\r
 import org.junit.Test;\r
 \r
index 452f22ebcb6f6a38262e8fbbd3e401c3b8eec651..9b6f448954f538b0e2e37b3ceca5cdbff4f47e4e 100644 (file)
@@ -28,7 +28,7 @@ import java.io.IOException;
 import java.util.List;\r
 \r
 import org.apache.poi.sl.draw.geom.TestPresetGeometries;\r
-import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;\r
+import org.apache.poi.sl.usermodel.Placeholder;\r
 import org.apache.poi.sl.usermodel.StrokeStyle.LineCap;\r
 import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;\r
 import org.apache.poi.util.Units;\r
index cee11e541ad6f168d24fa883f58a998d64c509b3..15352b448bf0e4e1ec0f958562855e20c6c2ac69 100644 (file)
@@ -21,7 +21,7 @@ import static org.junit.Assert.assertNull;
 \r
 import java.io.IOException;\r
 \r
-import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;\r
+import org.apache.poi.sl.usermodel.Placeholder;\r
 import org.junit.Test;\r
 import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;\r
 \r
index c8a1aeebd5c914051d40dba3a6a31d683f3a8f18..a87a9cb555fde1df681f6208b7f18f4834c5f24a 100644 (file)
@@ -31,7 +31,7 @@ import java.util.List;
 \r
 import org.apache.poi.POIDataSamples;\r
 import org.apache.poi.hslf.usermodel.HSLFTextShape;\r
-import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;\r
+import org.apache.poi.sl.usermodel.Placeholder;\r
 import org.apache.poi.sl.usermodel.SlideShow;\r
 import org.apache.poi.sl.usermodel.SlideShowFactory;\r
 import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;\r
index 5a5f82d165bb2077360f06c0735427fa074127b5..cf6f6bc41211cf7c83e401853337b9606055d1b9 100644 (file)
@@ -122,7 +122,7 @@ public final class PPTXMLDump {
             pos += LittleEndian.INT_SIZE;
 
             //get name of the record by type
-            String recname = RecordTypes.recordName(type);
+            String recname = RecordTypes.forTypeID(type).name();
             write(out, "<"+recname + " info=\""+info+"\" type=\""+type+"\" size=\""+size+"\" offset=\""+(pos-8)+"\"", padding);
             if (hexHeader){
                 out.write(" header=\"");
index 91d6086b1beb3accde01d9f258271ff0ce101586..90f404b1eb7a71838b2cbf005baee4eb0693abfc 100644 (file)
@@ -79,7 +79,7 @@ public final class SLWTListing {
                                        for(int k=0; k<upTo; k++) {
                                                Record r = children[k];
                                                int typeID = (int)r.getRecordType();
-                                               String typeName = RecordTypes.recordName(typeID);
+                                               String typeName = RecordTypes.forTypeID(typeID).name();
                                                System.out.println("   - " + typeID + " (" + typeName + ")");
                                        }
                                }
index 62b757f453d575e0c83a7f5d631978b2098cfd04..df2d38bdc45b19f072899bf8c26b105757cbf643 100644 (file)
@@ -167,7 +167,7 @@ public void walkTree(int depth, int startPos, int maxLen) throws IOException {
                out.println(String.format(Locale.ROOT, fmt, "", pos, type, len));
 
                // See if we know about the type of it
-               String recordName = RecordTypes.recordName((int)type);
+               String recordName = RecordTypes.forTypeID((short)type).name();
 
                // Jump over header, and think about going on more
                pos += 8;
@@ -293,7 +293,7 @@ public void walkTree(int depth, int startPos, int maxLen) throws IOException {
        String fmt = ind+"At position %2$d ($2$04x): type is %3$d (%3$04x), len is %4$d (%4$04x)";
        out.println(String.format(Locale.ROOT, fmt, "", pos, type, atomlen));
 
-       String typeName = RecordTypes.recordName((int)type);
+       String typeName = RecordTypes.forTypeID((short)type).name();
        out.println(String.format(Locale.ROOT, ind+"%2$s", "That's an Escher Record: ", typeName));
 
        // Record specific dumps
index 5bcf98ab850d8a80ac5b4231ea9fe99f7748dbfd..3ba8f6f2d6029637701030a7491bda6de1b1d19a 100644 (file)
 
 package org.apache.poi.hslf.model;
 
-import java.io.ByteArrayOutputStream;
-import java.util.Iterator;
-
 import org.apache.poi.ddf.AbstractEscherOptRecord;
-import org.apache.poi.ddf.EscherClientDataRecord;
 import org.apache.poi.ddf.EscherComplexProperty;
 import org.apache.poi.ddf.EscherContainerRecord;
 import org.apache.poi.ddf.EscherProperties;
-import org.apache.poi.ddf.EscherRecord;
 import org.apache.poi.ddf.EscherSpRecord;
 import org.apache.poi.hslf.exceptions.HSLFException;
 import org.apache.poi.hslf.record.Document;
 import org.apache.poi.hslf.record.ExControl;
 import org.apache.poi.hslf.record.ExObjList;
-import org.apache.poi.hslf.record.OEShapeAtom;
+import org.apache.poi.hslf.record.ExObjRefAtom;
+import org.apache.poi.hslf.record.HSLFEscherClientDataRecord;
 import org.apache.poi.hslf.record.Record;
 import org.apache.poi.hslf.record.RecordTypes;
 import org.apache.poi.hslf.usermodel.HSLFPictureData;
@@ -41,7 +37,6 @@ import org.apache.poi.hslf.usermodel.HSLFSheet;
 import org.apache.poi.hslf.usermodel.HSLFTextParagraph;
 import org.apache.poi.sl.usermodel.ShapeContainer;
 import org.apache.poi.sl.usermodel.ShapeType;
-import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.StringUtil;
 
 /**
@@ -92,20 +87,8 @@ public final class ActiveXShape extends HSLFPictureShape {
         setEscherProperty(EscherProperties.SHADOWSTYLE__COLOR, 0x8000002);
         setEscherProperty(EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, -1);
 
-        EscherClientDataRecord cldata = new EscherClientDataRecord();
-        cldata.setOptions((short)0xF);
-        _escherContainer.addChildRecord(cldata); // TODO unit test to prove getChildRecords().add is wrong
-
-        OEShapeAtom oe = new OEShapeAtom();
-
-        //convert hslf into ddf
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        try {
-            oe.writeOut(out);
-        } catch(Exception e){
-            throw new HSLFException(e);
-        }
-        cldata.setRemainingData(out.toByteArray());
+        HSLFEscherClientDataRecord cldata = getClientData(true);
+        cldata.addChild(new ExObjRefAtom());
 
         return _escherContainer;
     }
@@ -116,22 +99,18 @@ public final class ActiveXShape extends HSLFPictureShape {
      * @see org.apache.poi.hslf.usermodel.HSLFSlideShow#addMovie(String, int)
      * @param idx  the index of the movie
      */
-    public void setActiveXIndex(int idx){
-        EscherContainerRecord spContainer = getSpContainer();
-        for (Iterator<EscherRecord> it = spContainer.getChildIterator(); it.hasNext();) {
-            EscherRecord obj = it.next();
-            if (obj.getRecordId() == EscherClientDataRecord.RECORD_ID) {
-                EscherClientDataRecord clientRecord = (EscherClientDataRecord)obj;
-                byte[] recdata = clientRecord.getRemainingData();
-                LittleEndian.putInt(recdata, 8, idx);
-            }
+    public void setActiveXIndex(int idx) {
+        ExObjRefAtom oe = getClientDataRecord(RecordTypes.ExObjRefAtom.typeID);
+        if (oe == null) {
+            throw new HSLFException("OEShapeAtom for ActiveX doesn't exist");
         }
+        oe.setExObjIdRef(idx);
     }
 
     public int getControlIndex(){
         int idx = -1;
-        OEShapeAtom oe = getClientDataRecord(RecordTypes.OEShapeAtom.typeID);
-        if(oe != null) idx = oe.getOptions();
+        ExObjRefAtom oe = getClientDataRecord(RecordTypes.ExObjRefAtom.typeID);
+        if(oe != null) idx = oe.getExObjIdRef();
         return idx;
     }
 
index d4da2a3101ef57e4343e18eb6fd6f9ad4672239b..5650b2b2d83bf060f84c3277a52e0a3412d62250 100644 (file)
 
 package org.apache.poi.hslf.model;
 
-import java.io.ByteArrayOutputStream;
-
-import org.apache.poi.ddf.EscherClientDataRecord;
 import org.apache.poi.ddf.EscherContainerRecord;
 import org.apache.poi.ddf.EscherProperties;
-import org.apache.poi.hslf.exceptions.HSLFException;
-import org.apache.poi.hslf.record.*;
-import org.apache.poi.hslf.usermodel.*;
+import org.apache.poi.hslf.record.AnimationInfo;
+import org.apache.poi.hslf.record.AnimationInfoAtom;
+import org.apache.poi.hslf.record.ExMCIMovie;
+import org.apache.poi.hslf.record.ExObjList;
+import org.apache.poi.hslf.record.ExObjRefAtom;
+import org.apache.poi.hslf.record.ExVideoContainer;
+import org.apache.poi.hslf.record.HSLFEscherClientDataRecord;
+import org.apache.poi.hslf.record.InteractiveInfo;
+import org.apache.poi.hslf.record.InteractiveInfoAtom;
+import org.apache.poi.hslf.record.Record;
+import org.apache.poi.hslf.record.RecordTypes;
+import org.apache.poi.hslf.usermodel.HSLFPictureData;
+import org.apache.poi.hslf.usermodel.HSLFPictureShape;
+import org.apache.poi.hslf.usermodel.HSLFShape;
+import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.apache.poi.hslf.usermodel.HSLFTextParagraph;
 import org.apache.poi.sl.usermodel.ShapeContainer;
 
 /**
@@ -82,11 +92,7 @@ public final class MovieShape extends HSLFPictureShape {
         setEscherProperty(EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x1000100);
         setEscherProperty(EscherProperties.FILL__NOFILLHITTEST, 0x10001);
 
-        EscherClientDataRecord cldata = new EscherClientDataRecord();
-        cldata.setOptions((short)0xF);
-        _escherContainer.addChildRecord(cldata);
-
-        OEShapeAtom oe = new OEShapeAtom();
+        ExObjRefAtom oe = new ExObjRefAtom();
         InteractiveInfo info = new InteractiveInfo();
         InteractiveInfoAtom infoAtom = info.getInteractiveInfoAtom();
         infoAtom.setAction(InteractiveInfoAtom.ACTION_MEDIA);
@@ -96,16 +102,10 @@ public final class MovieShape extends HSLFPictureShape {
         AnimationInfoAtom anAtom = an.getAnimationInfoAtom();
         anAtom.setFlag(AnimationInfoAtom.Automatic, true);
 
-        //convert hslf into ddf
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        try {
-            oe.writeOut(out);
-            an.writeOut(out);
-            info.writeOut(out);
-        } catch(Exception e){
-            throw new HSLFException(e);
-        }
-        cldata.setRemainingData(out.toByteArray());
+        HSLFEscherClientDataRecord cldata = getClientData(true);
+        cldata.addChild(oe);
+        cldata.addChild(an);
+        cldata.addChild(info);
 
         return _escherContainer;
     }
@@ -117,8 +117,8 @@ public final class MovieShape extends HSLFPictureShape {
      * @param idx  the index of the movie
      */
     public void setMovieIndex(int idx){
-        OEShapeAtom oe = getClientDataRecord(RecordTypes.OEShapeAtom.typeID);
-        oe.setOptions(idx);
+        ExObjRefAtom oe = getClientDataRecord(RecordTypes.ExObjRefAtom.typeID);
+        oe.setExObjIdRef(idx);
 
         AnimationInfo an = getClientDataRecord(RecordTypes.AnimationInfo.typeID);
         if(an != null) {
@@ -135,7 +135,6 @@ public final class MovieShape extends HSLFPictureShape {
         AnimationInfo an = getClientDataRecord(RecordTypes.AnimationInfo.typeID);
         if(an != null){
             an.getAnimationInfoAtom().setFlag(AnimationInfoAtom.Automatic, flag);
-            updateClientData();
         }
     }
 
@@ -150,13 +149,16 @@ public final class MovieShape extends HSLFPictureShape {
     /**
      * @return UNC or local path to a video file
      */
+    @SuppressWarnings("resource")
     public String getPath(){
-        OEShapeAtom oe = getClientDataRecord(RecordTypes.OEShapeAtom.typeID);
-        int idx = oe.getOptions();
+        ExObjRefAtom oe = getClientDataRecord(RecordTypes.ExObjRefAtom.typeID);
+        int idx = oe.getExObjIdRef();
 
         HSLFSlideShow ppt = getSheet().getSlideShow();
         ExObjList lst = (ExObjList)ppt.getDocumentRecord().findFirstOfType(RecordTypes.ExObjList.typeID);
-        if(lst == null) return null;
+        if(lst == null) {
+            return null;
+        }
 
         Record[]  r = lst.getChildRecords();
         for (int i = 0; i < r.length; i++) {
index c61c5ce5ac4e7ab8f104cd290f2d9a8799457cd3..c0e5948d773d8a79b6b6d3b4705b6b502bad15c8 100644 (file)
 
 package org.apache.poi.hslf.model;
 
-import org.apache.poi.ddf.*;
-import org.apache.poi.hslf.usermodel.*;
+import org.apache.poi.ddf.EscherContainerRecord;
+import org.apache.poi.ddf.EscherProperties;
+import org.apache.poi.ddf.EscherSpRecord;
+import org.apache.poi.hslf.record.ExEmbed;
 import org.apache.poi.hslf.record.ExObjList;
+import org.apache.poi.hslf.record.ExObjRefAtom;
+import org.apache.poi.hslf.record.HSLFEscherClientDataRecord;
 import org.apache.poi.hslf.record.Record;
-import org.apache.poi.hslf.record.ExEmbed;
 import org.apache.poi.hslf.record.RecordTypes;
+import org.apache.poi.hslf.usermodel.HSLFObjectData;
+import org.apache.poi.hslf.usermodel.HSLFPictureData;
+import org.apache.poi.hslf.usermodel.HSLFPictureShape;
+import org.apache.poi.hslf.usermodel.HSLFShape;
+import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.apache.poi.hslf.usermodel.HSLFTextParagraph;
 import org.apache.poi.sl.usermodel.ShapeContainer;
-import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.POILogger;
 
 
@@ -88,26 +96,19 @@ public final class OLEShape extends HSLFPictureShape {
        EscherSpRecord spRecord = ecr.getChildById(EscherSpRecord.RECORD_ID);
         spRecord.setFlags(spRecord.getFlags()|EscherSpRecord.FLAG_OLESHAPE);
 
-        EscherContainerRecord uerCont = ecr.getChildById((short)RecordTypes.EscherClientData);
-        if (uerCont == null) {
-               uerCont = new EscherContainerRecord();
-               ecr.addChildRecord(uerCont);
+        HSLFEscherClientDataRecord cldata = getClientData(true);
+        ExObjRefAtom uer = null;
+        for (Record r : cldata.getHSLFChildRecords()) {
+            if (r.getRecordType() == RecordTypes.ExObjRefAtom.typeID) {
+                uer = (ExObjRefAtom)r;
+                break;
+            }
         }
-        uerCont.setRecordId((short)RecordTypes.EscherClientData);
-        uerCont.setVersion((short)0x000F); // yes, we are still a container ...
-
-        UnknownEscherRecord uer = uerCont.getChildById((short)RecordTypes.ExObjRefAtom.typeID);
         if (uer == null) {
-               uer = new UnknownEscherRecord();
-               uerCont.addChildRecord(uer);
+               uer = new ExObjRefAtom();
+               cldata.addChild(uer);
         }
-        
-        byte uerData[] = new byte[12];
-        LittleEndian.putShort( uerData, 0, (short)0 ); // options = 0
-        LittleEndian.putShort( uerData, 2, (short)RecordTypes.ExObjRefAtom.typeID); // recordId
-        LittleEndian.putInt( uerData, 4, 4 ); // remaining bytes
-        LittleEndian.putInt( uerData, 8, objectId ); // the data
-        uer.fillFields(uerData, 0, null);        
+        uer.setExObjIdRef(objectId);
     }
     
     
@@ -116,6 +117,7 @@ public final class OLEShape extends HSLFPictureShape {
      *
      * @return the unique identifier for the OLE object
      */
+    @SuppressWarnings("resource")
     public HSLFObjectData getObjectData(){
         HSLFSlideShow ppt = getSheet().getSlideShow();
         HSLFObjectData[] ole = ppt.getEmbeddedObjects();
@@ -153,6 +155,7 @@ public final class OLEShape extends HSLFPictureShape {
      * 6. MetaFile( 4033), optional
      * </p>
      */
+    @SuppressWarnings("resource")
     public ExEmbed getExEmbed(){
         if(_exEmbed == null){
             HSLFSlideShow ppt = getSheet().getSlideShow();
diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/ExObjRefAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/ExObjRefAtom.java
new file mode 100644 (file)
index 0000000..fa362c8
--- /dev/null
@@ -0,0 +1,94 @@
+/* ====================================================================\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to You under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+       http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+==================================================================== */\r
+\r
+package org.apache.poi.hslf.record;\r
+\r
+import org.apache.poi.util.LittleEndian;\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+\r
+/**\r
+ * ExObjRefAtom (3009).\r
+ * <p>\r
+ *  An atom record that specifies a reference to an external object.\r
+ * </p>\r
+ */\r
+\r
+public final class ExObjRefAtom extends RecordAtom {\r
+       private byte[] _header;\r
+\r
+       /**\r
+        * A 4-byte unsigned integer that specifies a reference to an external object.\r
+        * It MUST be equal to the value of the exObjId field of an ExMediaAtom record\r
+        * or the value of the exObjId field of an ExOleObjAtom record.\r
+        */\r
+       private int exObjIdRef;\r
+\r
+    /**\r
+     * Create a new instance of <code>ExObjRefAtom</code>\r
+     */\r
+    public ExObjRefAtom() {\r
+        _header = new byte[8];\r
+        LittleEndian.putUShort(_header, 0, 0);\r
+        LittleEndian.putUShort(_header, 2, (int)getRecordType());\r
+        LittleEndian.putInt(_header, 4, 4);\r
+        exObjIdRef = 0;\r
+    }\r
+\r
+    /**\r
+     * Build an instance of <code>ExObjRefAtom</code> from on-disk data\r
+     * \r
+     * @param source the source data as a byte array.\r
+     * @param start the start offset into the byte array.\r
+     * @param len the length of the slice in the byte array.\r
+     */\r
+       protected ExObjRefAtom(byte[] source, int start, int len) {\r
+               _header = new byte[8];\r
+        int offset = start;\r
+        System.arraycopy(source,start,_header,0,8);\r
+        offset += _header.length;\r
+        exObjIdRef = (int)LittleEndian.getUInt(source, offset);\r
+       }\r
+\r
+    /**\r
+     * @return type of this record {@link RecordTypes#ExObjRefAtom}.\r
+     */\r
+       public long getRecordType() {\r
+           return RecordTypes.ExObjRefAtom.typeID;\r
+    }\r
+\r
+    public int getExObjIdRef(){\r
+        return exObjIdRef;\r
+    }\r
+\r
+   public void setExObjIdRef(int id){\r
+       exObjIdRef = id;\r
+    }\r
+\r
+   /**\r
+        * Write the contents of the record back, so it can be written\r
+        *  to disk\r
+        */\r
+       public void writeOut(OutputStream out) throws IOException {\r
+               out.write(_header);\r
+\r
+        byte[] recdata = new byte[4];\r
+        LittleEndian.putUInt(recdata, 0, exObjIdRef);\r
+\r
+        out.write(recdata);\r
+       }\r
+}\r
diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/HSLFEscherClientDataRecord.java b/src/scratchpad/src/org/apache/poi/hslf/record/HSLFEscherClientDataRecord.java
new file mode 100644 (file)
index 0000000..e6a2cdc
--- /dev/null
@@ -0,0 +1,120 @@
+/* ====================================================================\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to You under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+       http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+==================================================================== */\r
+\r
+package org.apache.poi.hslf.record;\r
+\r
+import java.io.ByteArrayOutputStream;\r
+import java.io.IOException;\r
+import java.util.ArrayList;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+\r
+import org.apache.poi.ddf.EscherClientDataRecord;\r
+import org.apache.poi.ddf.EscherRecordFactory;\r
+import org.apache.poi.ddf.EscherSerializationListener;\r
+import org.apache.poi.hslf.exceptions.HSLFException;\r
+import org.apache.poi.util.LittleEndian;\r
+\r
+/**\r
+ * An atom record that specifies whether a shape is a placeholder shape.\r
+ * The number, position, and type of placeholder shapes are determined by\r
+ * the slide layout as specified in the SlideAtom record.\r
+ * \r
+ * @since POI 3.14-Beta2\r
+ */\r
+public class HSLFEscherClientDataRecord extends EscherClientDataRecord {\r
+\r
+    private final List<Record> _childRecords = new ArrayList<Record>();\r
+    \r
+    public List<? extends Record> getHSLFChildRecords() { \r
+        return _childRecords;\r
+    }\r
+    \r
+    public void removeChild(Class<? extends Record> childClass) {\r
+        Iterator<Record> iter = _childRecords.iterator();\r
+        while (iter.hasNext()) {\r
+            if (childClass.isInstance(iter.next())) {\r
+                iter.remove();\r
+            }\r
+        }\r
+    }\r
+    \r
+    public void addChild(Record childRecord) {\r
+        _childRecords.add(childRecord);\r
+    }\r
+    \r
+    @Override\r
+    public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) {\r
+        int bytesRemaining = readHeader( data, offset );\r
+        byte remainingData[] = new byte[bytesRemaining];\r
+        System.arraycopy(data, offset+8, remainingData, 0, bytesRemaining);\r
+        setRemainingData(remainingData);\r
+        return bytesRemaining + 8;\r
+    }\r
+\r
+    @Override\r
+    public int serialize(int offset, byte[] data, EscherSerializationListener listener) {\r
+        listener.beforeRecordSerialize( offset, getRecordId(), this );\r
+        \r
+        LittleEndian.putShort(data, offset, getOptions());\r
+        LittleEndian.putShort(data, offset+2, getRecordId());\r
+        \r
+        byte childBytes[] = getRemainingData();\r
+        \r
+        LittleEndian.putInt(data, offset+4, childBytes.length);\r
+        System.arraycopy(childBytes, 0, data, offset+8, childBytes.length);\r
+        int recordSize = 8+childBytes.length;\r
+        listener.afterRecordSerialize( offset+recordSize, getRecordId(), recordSize, this );\r
+        return recordSize;\r
+    }\r
+\r
+    @Override\r
+    public int getRecordSize() {\r
+        return 8 + getRemainingData().length;\r
+    }\r
+    \r
+    @Override\r
+    public byte[] getRemainingData() {\r
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();\r
+        try {\r
+            for (Record r : _childRecords) {\r
+                r.writeOut(bos);\r
+            }\r
+        } catch (IOException e) {\r
+            throw new HSLFException(e);\r
+        }\r
+        return bos.toByteArray();\r
+    }\r
+\r
+    @Override\r
+    public void setRemainingData( byte[] remainingData ) {\r
+        _childRecords.clear();\r
+        int offset = 0;\r
+        while (offset < remainingData.length) {\r
+            Record r = Record.buildRecordAtOffset(remainingData, offset);\r
+            _childRecords.add(r);\r
+            long rlen = LittleEndian.getUInt(remainingData,offset+4);\r
+            offset += 8 + rlen;\r
+        }\r
+    }\r
+    \r
+    public String getRecordName() {\r
+        return "HSLFClientData";\r
+    }\r
+\r
+    \r
+}\r
index c985864f00443aa0d1d7362614c208af3fc6ca89..a37ea943c7db18cecb908161ec2c68a0022880d5 100644 (file)
@@ -29,7 +29,7 @@ import org.apache.poi.util.LittleEndian;
  * @see EscherRecordFactory\r
  */\r
 public class HSLFEscherRecordFactory extends DefaultEscherRecordFactory {\r
-    private static Class<?>[] escherRecordClasses = { EscherPlaceholder.class };\r
+    private static Class<?>[] escherRecordClasses = { EscherPlaceholder.class, HSLFEscherClientDataRecord.class };\r
     private static Map<Short, Constructor<? extends EscherRecord>> recordsMap = recordsToMap( escherRecordClasses );\r
 \r
     \r
@@ -65,6 +65,10 @@ public class HSLFEscherRecordFactory extends DefaultEscherRecordFactory {
         }\r
         escherRecord.setRecordId(recordId);\r
         escherRecord.setOptions(options);\r
+        if (escherRecord instanceof EscherContainerRecord) {\r
+            ((EscherContainerRecord)escherRecord).fillFields(data, offset, this);\r
+        }\r
+        \r
         return escherRecord;\r
     }\r
 }\r
index 1d8d7df62f4fe6cac7e2c34a05567e0c9e1438bf..54d5d8622118213e73868363fcc489e0f9a8d3a0 100644 (file)
@@ -201,6 +201,7 @@ public final class OEPlaceholderAtom extends RecordAtom{
     private int placementId;
     private int placeholderId;
     private int placeholderSize;
+    private short unusedShort = 0;
 
 
     /**
@@ -227,8 +228,9 @@ public final class OEPlaceholderAtom extends RecordAtom{
         offset += _header.length;
 
         placementId = LittleEndian.getInt(source, offset); offset += 4;
-        placeholderId = LittleEndian.getUnsignedByte(source, offset); offset++;
-        placeholderSize = LittleEndian.getUnsignedByte(source, offset); offset++;
+        placeholderId = LittleEndian.getUByte(source, offset); offset++;
+        placeholderSize = LittleEndian.getUByte(source, offset); offset++;
+        unusedShort = LittleEndian.getShort(source, offset);
        }
 
     /**
@@ -322,6 +324,7 @@ public final class OEPlaceholderAtom extends RecordAtom{
         LittleEndian.putInt(recdata, 0, placementId);
         recdata[4] = (byte)placeholderId;
         recdata[5] = (byte)placeholderSize;
+        LittleEndian.putShort(recdata, 6, unusedShort);
 
         out.write(recdata);
        }
diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/OEShapeAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/OEShapeAtom.java
deleted file mode 100644 (file)
index 00b873f..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/* ====================================================================
-   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.hslf.record;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-import org.apache.poi.util.LittleEndian;
-
-/**
- * Atom that contains information that describes shape client data.
- *
- * @author Yegor Kozlov
- */
-public final class OEShapeAtom extends RecordAtom
-{
-
-    /**
-     * Record header.
-     */
-    private byte[] _header;
-
-    /**
-     * record data
-     */
-    private byte[] _recdata;
-
-    /**
-     * Constructs a brand new link related atom record.
-     */
-    public OEShapeAtom() {
-        _recdata = new byte[4];
-
-        _header = new byte[8];
-        LittleEndian.putShort(_header, 2, (short)getRecordType());
-        LittleEndian.putInt(_header, 4, _recdata.length);
-    }
-
-    /**
-     * Constructs the link related atom record from its
-     *  source data.
-     *
-     * @param source the source data as a byte array.
-     * @param start the start offset into the byte array.
-     * @param len the length of the slice in the byte array.
-     */
-    protected OEShapeAtom(byte[] source, int start, int len) {
-        // Get the header
-        _header = new byte[8];
-        System.arraycopy(source,start,_header,0,8);
-
-        // Grab the record data
-        _recdata = new byte[len-8];
-        System.arraycopy(source,start+8,_recdata,0,len-8);
-    }
-
-    /**
-     * Gets the record type.
-     * @return the record type.
-     */
-    public long getRecordType() { return RecordTypes.OEShapeAtom.typeID; }
-
-    /**
-     * Write the contents of the record back, so it can be written
-     * to disk
-     *
-     * @param out the output stream to write to.
-     * @throws java.io.IOException if an error occurs.
-     */
-    public void writeOut(OutputStream out) throws IOException {
-        out.write(_header);
-        out.write(_recdata);
-    }
-
-    /**
-     * shape flags.
-     *
-     * @return  shape flags.
-     */
-    public int getOptions(){
-        return LittleEndian.getInt(_recdata, 0);
-    }
-
-    /**
-     * shape flags.
-     *
-     * @param id  shape flags.
-     */
-    public void setOptions(int id){
-         LittleEndian.putInt(_recdata, 0, id);
-    }
-}
index 637f9a8ab8b59cebecc4b74df17a10ef5a4ba72d..90b24ed9f2142feabfaa8e7d94211c734dfbfed5 100644 (file)
@@ -20,7 +20,6 @@ package org.apache.poi.hslf.record;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -36,7 +35,6 @@ import org.apache.poi.ddf.EscherSimpleProperty;
 import org.apache.poi.ddf.EscherSpRecord;
 import org.apache.poi.ddf.EscherSpgrRecord;
 import org.apache.poi.ddf.EscherTextboxRecord;
-import org.apache.poi.ddf.UnknownEscherRecord;
 import org.apache.poi.sl.usermodel.ShapeType;
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.POILogger;
@@ -57,7 +55,7 @@ public final class PPDrawing extends RecordAtom {
        private byte[] _header;
        private long _type;
 
-       private EscherRecord[] childRecords;
+       private final List<EscherRecord> childRecords = new ArrayList<EscherRecord>();
        private EscherTextboxWrapper[] textboxWrappers;
 
        //cached EscherDgRecord
@@ -66,7 +64,7 @@ public final class PPDrawing extends RecordAtom {
        /**
         * Get access to the underlying Escher Records
         */
-       public EscherRecord[] getEscherRecords() { return childRecords; }
+       public List<EscherRecord> getEscherRecords() { return childRecords; }
 
        /**
         * Get access to the atoms inside Textboxes
@@ -76,6 +74,20 @@ public final class PPDrawing extends RecordAtom {
 
        /* ******************** record stuff follows ********************** */
 
+    /**
+     * Creates a new, empty, PPDrawing (typically for use with a new Slide
+     *  or Notes)
+     */
+    public PPDrawing() {
+        _header = new byte[8];
+        LittleEndian.putUShort(_header, 0, 15);
+        LittleEndian.putUShort(_header, 2, RecordTypes.PPDrawing.typeID);
+        LittleEndian.putInt(_header, 4, 0);
+
+        textboxWrappers = new EscherTextboxWrapper[]{};
+        create();
+    }
+
        /**
         * Sets everything up, groks the escher etc
         */
@@ -93,12 +105,11 @@ public final class PPDrawing extends RecordAtom {
 
                // Build up a tree of Escher records contained within
                final DefaultEscherRecordFactory erf = new HSLFEscherRecordFactory();
-               final List<EscherRecord> escherChildren = new ArrayList<EscherRecord>();
-               findEscherChildren(erf, contents, 8, len-8, escherChildren);
-               this.childRecords = escherChildren.toArray(new EscherRecord[escherChildren.size()]);
+               findEscherChildren(erf, contents, 8, len-8, childRecords);
+               EscherContainerRecord dgContainer = getDgContainer();
 
-               if (1 == this.childRecords.length && (short)RecordTypes.EscherDgContainer == this.childRecords[0].getRecordId() && this.childRecords[0] instanceof EscherContainerRecord) {
-                       this.textboxWrappers = findInDgContainer((EscherContainerRecord) this.childRecords[0]);
+               if (dgContainer != null) {
+                       textboxWrappers = findInDgContainer(dgContainer);
                } else {
                        // Find and EscherTextboxRecord's, and wrap them up
                        final List<EscherTextboxWrapper> textboxes = new ArrayList<EscherTextboxWrapper>();
@@ -108,15 +119,15 @@ public final class PPDrawing extends RecordAtom {
        }
        private EscherTextboxWrapper[] findInDgContainer(final EscherContainerRecord dgContainer) {
                final List<EscherTextboxWrapper> found = new LinkedList<EscherTextboxWrapper>();
-               final EscherContainerRecord spgrContainer = findFirstEscherContainerRecordOfType((short)RecordTypes.EscherSpgrContainer, dgContainer);
-               final EscherContainerRecord[] spContainers = findAllEscherContainerRecordOfType((short)RecordTypes.EscherSpContainer, spgrContainer);
+               final EscherContainerRecord spgrContainer = findFirstEscherContainerRecordOfType(RecordTypes.EscherSpgrContainer, dgContainer);
+               final EscherContainerRecord[] spContainers = findAllEscherContainerRecordOfType(RecordTypes.EscherSpContainer, spgrContainer);
                for (EscherContainerRecord spContainer : spContainers) {
-                       StyleTextProp9Atom nineAtom = findInSpContainer(spContainer);
-                       EscherSpRecord sp = (EscherSpRecord)findFirstEscherRecordOfType((short)RecordTypes.EscherSp, spContainer);
-                       EscherTextboxRecord clientTextbox = (EscherTextboxRecord)findFirstEscherRecordOfType((short)RecordTypes.EscherClientTextbox, spContainer);
+                       EscherSpRecord sp = (EscherSpRecord)findFirstEscherRecordOfType(RecordTypes.EscherSp, spContainer);
+                       EscherTextboxRecord clientTextbox = (EscherTextboxRecord)findFirstEscherRecordOfType(RecordTypes.EscherClientTextbox, spContainer);
                        if (null == clientTextbox) { continue; }
 
                        EscherTextboxWrapper w = new EscherTextboxWrapper(clientTextbox);
+            StyleTextProp9Atom nineAtom = findInSpContainer(spContainer);
                        w.setStyleTextProp9Atom(nineAtom);
                        if (null != sp) {
                            w.setShapeId(sp.getShapeId());
@@ -127,16 +138,26 @@ public final class PPDrawing extends RecordAtom {
        }
        
        private StyleTextProp9Atom findInSpContainer(final EscherContainerRecord spContainer) {
-               EscherContainerRecord clientData = findFirstEscherContainerRecordOfType((short)RecordTypes.EscherClientData, spContainer);
-               if (null == clientData) { return null; }
-               final EscherContainerRecord progTagsContainer = findFirstEscherContainerRecordOfType((short)0x1388, clientData);
-               if (null == progTagsContainer) { return null; }
-               final EscherContainerRecord progBinaryTag = findFirstEscherContainerRecordOfType((short)0x138A, progTagsContainer);
-               if (null == progBinaryTag) { return null; }
-               int size = progBinaryTag.getChildRecords().size();
+        HSLFEscherClientDataRecord cldata = spContainer.getChildById(RecordTypes.EscherClientData.typeID);
+        if (cldata == null) {
+            return null;
+        }
+        DummyPositionSensitiveRecordWithChildren progTags =
+            getChildRecord(cldata.getHSLFChildRecords(), RecordTypes.ProgTags);
+        if (progTags == null) {
+            return null;
+        }
+        DummyPositionSensitiveRecordWithChildren progBinaryTag =
+            (DummyPositionSensitiveRecordWithChildren)progTags.findFirstOfType(RecordTypes.ProgBinaryTag.typeID);
+        if (progBinaryTag == null) {
+            return null;
+        }
+               int size = progBinaryTag.getChildRecords().length;
                if (2 != size) { return null; }
-               final Record r0 = buildFromUnknownEscherRecord((UnknownEscherRecord) progBinaryTag.getChild(0));
-               final Record r1 = buildFromUnknownEscherRecord((UnknownEscherRecord) progBinaryTag.getChild(1));
+
+               final Record r0 = progBinaryTag.getChildRecords()[0];
+               final Record r1 = progBinaryTag.getChildRecords()[1];
+               
                if (!(r0 instanceof CString)) { return null; }
                if (!("___PPT9".equals(((CString) r0).getText()))) { return null; };
                if (!(r1 instanceof BinaryTagDataBlob )) { return null; }
@@ -144,19 +165,6 @@ public final class PPDrawing extends RecordAtom {
                if (1 != blob.getChildRecords().length) { return null; }
                return (StyleTextProp9Atom) blob.findFirstOfType(RecordTypes.StyleTextProp9Atom.typeID);
        }
-       /**
-        * Creates a new, empty, PPDrawing (typically for use with a new Slide
-        *  or Notes)
-        */
-       public PPDrawing(){
-               _header = new byte[8];
-               LittleEndian.putUShort(_header, 0, 15);
-               LittleEndian.putUShort(_header, 2, RecordTypes.PPDrawing.typeID);
-               LittleEndian.putInt(_header, 4, 0);
-
-               textboxWrappers = new EscherTextboxWrapper[]{};
-               create();
-       }
 
        /**
         * Tree walking way of finding Escher Child Records
@@ -198,27 +206,22 @@ public final class PPDrawing extends RecordAtom {
        /**
         * Look for EscherTextboxRecords
         */
-       private void findEscherTextboxRecord(EscherRecord[] toSearch, List<EscherTextboxWrapper> found) {
-               for(int i=0; i<toSearch.length; i++) {
-                       if(toSearch[i] instanceof EscherTextboxRecord) {
-                               EscherTextboxRecord tbr = (EscherTextboxRecord)toSearch[i];
+       private void findEscherTextboxRecord(List<EscherRecord> toSearch, List<EscherTextboxWrapper> found) {
+           EscherSpRecord sp = null;
+           for (EscherRecord r : toSearch) {
+               if (r instanceof EscherSpRecord) {
+                   sp = (EscherSpRecord)r;
+               } else if (r instanceof EscherTextboxRecord) {
+                               EscherTextboxRecord tbr = (EscherTextboxRecord)r;
                                EscherTextboxWrapper w = new EscherTextboxWrapper(tbr);
-                               found.add(w);
-                               for (int j = i; j >= 0; j--) {
-                                       if(toSearch[j] instanceof EscherSpRecord){
-                                               EscherSpRecord sp = (EscherSpRecord)toSearch[j];
-                                               w.setShapeId(sp.getShapeId());
-                                               break;
-                                       }
+                               if (sp != null) {
+                                   w.setShapeId(sp.getShapeId());
                                }
-                       } else {
+                               found.add(w);
+                       } else if (r.isContainerRecord()) {
                                // If it has children, walk them
-                               if(toSearch[i].isContainerRecord()) {
-                                       List<EscherRecord> childrenL = toSearch[i].getChildRecords();
-                                       EscherRecord[] children = new EscherRecord[childrenL.size()];
-                                       childrenL.toArray(children);
-                                       findEscherTextboxRecord(children,found);
-                               }
+                               List<EscherRecord> children = r.getChildRecords();
+                               findEscherTextboxRecord(children,found);
                        }
                }
        }
@@ -259,9 +262,8 @@ public final class PPDrawing extends RecordAtom {
                // Now grab the children's data
                byte[] b = new byte[newSize];
                int done = 0;
-               for(int i=0; i<childRecords.length; i++) {
-                       int written = childRecords[i].serialize( done, b );
-                       done += written;
+               for(EscherRecord r : childRecords) {
+                   done += r.serialize( done, b );
                }
 
                // Finally, write out the children
@@ -276,7 +278,7 @@ public final class PPDrawing extends RecordAtom {
                dgContainer.setRecordId( EscherContainerRecord.DG_CONTAINER );
                dgContainer.setOptions((short)15);
 
-               EscherDgRecord dg = new EscherDgRecord();
+               dg = new EscherDgRecord();
                dg.setOptions((short)16);
                dg.setNumShapes(1);
                dgContainer.addChildRecord(dg);
@@ -321,10 +323,8 @@ public final class PPDrawing extends RecordAtom {
                spContainer.addChildRecord(opt);
 
                dgContainer.addChildRecord(spContainer);
-
-               childRecords = new EscherRecord[]{
-                       dgContainer
-               };
+               
+               childRecords.add(dgContainer);
        }
 
        /**
@@ -338,6 +338,22 @@ public final class PPDrawing extends RecordAtom {
                textboxWrappers = tw;
        }
 
+       /**
+        * @return the container record for drawings
+        * @since POI 3.14-Beta2
+        */
+       public EscherContainerRecord getDgContainer() {
+           if (childRecords.isEmpty()) {
+               return null;
+           }
+           EscherRecord r = childRecords.get(0);
+           if (r instanceof EscherContainerRecord && r.getRecordId() == RecordTypes.EscherDgContainer.typeID) {
+               return (EscherContainerRecord)r;
+           } else {
+               return null;
+           }
+       }
+       
        /**
         * Return EscherDgRecord which keeps track of the number of shapes and shapeId in this drawing group
         *
@@ -345,9 +361,7 @@ public final class PPDrawing extends RecordAtom {
         */
        public EscherDgRecord getEscherDgRecord(){
                if(dg == null){
-                       EscherContainerRecord dgContainer = (EscherContainerRecord)childRecords[0];
-                       for(Iterator<EscherRecord> it = dgContainer.getChildIterator(); it.hasNext();){
-                               EscherRecord r = it.next();
+                       for(EscherRecord r : getDgContainer().getChildRecords()){
                                if(r instanceof EscherDgRecord){
                                        dg = (EscherDgRecord)r;
                                        break;
@@ -357,59 +371,59 @@ public final class PPDrawing extends RecordAtom {
                return dg;
        }
 
-    protected EscherContainerRecord findFirstEscherContainerRecordOfType(short type, EscherContainerRecord parent) {
+    protected EscherContainerRecord findFirstEscherContainerRecordOfType(RecordTypes type, EscherContainerRecord parent) {
        if (null == parent) { return null; }
                final List<EscherContainerRecord> children = parent.getChildContainers();
                for (EscherContainerRecord child : children) {
-                       if (type == child.getRecordId()) {
+                       if (type.typeID == child.getRecordId()) {
                                return child;
                        }
                }
                return null;
     }
-    protected EscherRecord findFirstEscherRecordOfType(short type, EscherContainerRecord parent) {
+    protected EscherRecord findFirstEscherRecordOfType(RecordTypes type, EscherContainerRecord parent) {
        if (null == parent) { return null; }
                final List<EscherRecord> children = parent.getChildRecords();
                for (EscherRecord child : children) {
-                       if (type == child.getRecordId()) {
+                       if (type.typeID == child.getRecordId()) {
                                return child;
                        }
                }
                return null;
     }
-    protected EscherContainerRecord[] findAllEscherContainerRecordOfType(short type, EscherContainerRecord parent) {
+    protected EscherContainerRecord[] findAllEscherContainerRecordOfType(RecordTypes type, EscherContainerRecord parent) {
        if (null == parent) { return new EscherContainerRecord[0]; }
                final List<EscherContainerRecord> children = parent.getChildContainers();
                final List<EscherContainerRecord> result = new LinkedList<EscherContainerRecord>();
                for (EscherContainerRecord child : children) {
-                       if (type == child.getRecordId()) {
+                       if (type.typeID == child.getRecordId()) {
                                result.add(child);
                        }
                }
                return result.toArray(new EscherContainerRecord[result.size()]);
     }
-    protected Record buildFromUnknownEscherRecord(UnknownEscherRecord unknown) {
-               byte[] bingo = unknown.getData();
-               byte[] restoredRecord = new byte[8 + bingo.length];
-               System.arraycopy(bingo, 0, restoredRecord, 8, bingo.length);
-               short recordVersion = unknown.getVersion();
-               short recordId = unknown.getRecordId();
-               int recordLength = unknown.getRecordSize();
-               LittleEndian.putShort(restoredRecord, 0, recordVersion);
-               LittleEndian.putShort(restoredRecord, 2, recordId);
-               LittleEndian.putInt(restoredRecord, 4, recordLength);
-               return Record.createRecordForType(recordId, restoredRecord, 0, restoredRecord.length);
-    }
 
     public StyleTextProp9Atom[] getNumberedListInfo() {
        final List<StyleTextProp9Atom> result = new LinkedList<StyleTextProp9Atom>();
-       EscherContainerRecord dgContainer = (EscherContainerRecord)childRecords[0];
-               final EscherContainerRecord spgrContainer = findFirstEscherContainerRecordOfType((short)RecordTypes.EscherSpgrContainer, dgContainer);
-               final EscherContainerRecord[] spContainers = findAllEscherContainerRecordOfType((short)RecordTypes.EscherSpContainer, spgrContainer);
+       EscherContainerRecord dgContainer = getDgContainer();
+               final EscherContainerRecord spgrContainer = findFirstEscherContainerRecordOfType(RecordTypes.EscherSpgrContainer, dgContainer);
+               final EscherContainerRecord[] spContainers = findAllEscherContainerRecordOfType(RecordTypes.EscherSpContainer, spgrContainer);
                for (EscherContainerRecord spContainer : spContainers) {
                    StyleTextProp9Atom prop9 = findInSpContainer(spContainer);
-                   if (prop9 != null) result.add(prop9);
+                   if (prop9 != null) {
+                       result.add(prop9);
+                   }
                }
        return result.toArray(new StyleTextProp9Atom[result.size()]);
        }
+    
+    @SuppressWarnings("unchecked")
+    private static <T extends Record> T getChildRecord(List<? extends Record> children, RecordTypes type) {
+        for (Record r : children) {
+            if (r.getRecordType() == type.typeID) {
+                return (T)r;
+            }
+        }
+        return null;
+    }
 }
index 78db7ee273e9b64e38fc191200fbcf000ee27f1c..61034f1f949987739651c133d195d5bf1a6b66bf 100644 (file)
@@ -166,19 +166,19 @@ public abstract class Record
                // Any special record handling occurs once we have the class
                Class<? extends Record> c = null;
                try {
-                       c = RecordTypes.recordHandlingClass((int)type);
+                       c = RecordTypes.forTypeID((short)type).handlingClass;
                        if(c == null) {
                                // How odd. RecordTypes normally subsitutes in
                                //  a default handler class if it has heard of the record
                                //  type but there's no support for it. Explicitly request
                                //  that now
-                               c = RecordTypes.recordHandlingClass( RecordTypes.Unknown.typeID );
+                               c = RecordTypes.UnknownRecordPlaceholder.handlingClass;
                        }
 
                        // Grab the right constructor
                        java.lang.reflect.Constructor<? extends Record> con = c.getDeclaredConstructor(new Class[] { byte[].class, Integer.TYPE, Integer.TYPE });
                        // Instantiate
-                       toReturn = con.newInstance(new Object[] { b, Integer.valueOf(start), Integer.valueOf(len) });
+                       toReturn = con.newInstance(new Object[] { b, start, len });
                } catch(InstantiationException ie) {
                        throw new RuntimeException("Couldn't instantiate the class for type with id " + type + " on class " + c + " : " + ie, ie);
                } catch(java.lang.reflect.InvocationTargetException ite) {
index 73a95f6d9a354a7ff5681c6f4e7c7b2f75fd6ca0..c20ca12b2e11238255dd04fea2959e3056c0c12b 100644 (file)
@@ -17,8 +17,8 @@
 
 package org.apache.poi.hslf.record;
 
-import java.lang.reflect.Field;
 import java.util.HashMap;
+import java.util.Map;
 
 /**
  * List of all known record types in a PowerPoint document, and the
@@ -26,191 +26,209 @@ import java.util.HashMap;
  * There are two categories of records:
  * <li> PowerPoint records: 0 <= info <= 10002 (will carry class info)
  * <li> Escher records: info >= 0xF000 (handled by DDF, so no class info)
- *
- * @author Yegor Kozlov
- * @author Nick Burch
  */
-public final class RecordTypes {
-    public static final HashMap<Integer,String> typeToName;
-    public static final HashMap<Integer,Class<? extends Record>> typeToClass;
-
-    public static final Type Unknown = new Type(0,null);
-    public static final Type Document = new Type(1000,Document.class);
-    public static final Type DocumentAtom = new Type(1001,DocumentAtom.class);
-    public static final Type EndDocument = new Type(1002,null);
-    public static final Type Slide = new Type(1006,Slide.class);
-    public static final Type SlideAtom = new Type(1007,SlideAtom.class);
-    public static final Type Notes = new Type(1008,Notes.class);
-    public static final Type NotesAtom = new Type(1009,NotesAtom.class);
-    public static final Type Environment = new Type(1010,Environment.class);
-    public static final Type SlidePersistAtom = new Type(1011,SlidePersistAtom.class);
-    public static final Type SSlideLayoutAtom = new Type(1015,null);
-    public static final Type MainMaster = new Type(1016,MainMaster.class);
-    public static final Type SSSlideInfoAtom = new Type(1017,SSSlideInfoAtom.class);
-    public static final Type SlideViewInfo = new Type(1018,null);
-    public static final Type GuideAtom = new Type(1019,null);
-    public static final Type ViewInfo = new Type(1020,null);
-    public static final Type ViewInfoAtom = new Type(1021,null);
-    public static final Type SlideViewInfoAtom = new Type(1022,null);
-    public static final Type VBAInfo = new Type(1023,null);
-    public static final Type VBAInfoAtom = new Type(1024,null);
-    public static final Type SSDocInfoAtom = new Type(1025,null);
-    public static final Type Summary = new Type(1026,null);
-    public static final Type DocRoutingSlip = new Type(1030,null);
-    public static final Type OutlineViewInfo = new Type(1031,null);
-    public static final Type SorterViewInfo = new Type(1032,null);
-    public static final Type ExObjList = new Type(1033,ExObjList.class);
-    public static final Type ExObjListAtom = new Type(1034,ExObjListAtom.class);
-    public static final Type PPDrawingGroup = new Type(1035,PPDrawingGroup.class);
-    public static final Type PPDrawing = new Type(1036,PPDrawing.class);
-    public static final Type NamedShows = new Type(1040,null);
-    public static final Type NamedShow = new Type(1041,null);
-    public static final Type NamedShowSlides = new Type(1042,null);
-    public static final Type SheetProperties = new Type(1044,null);
-    public static final Type RoundTripCustomTableStyles12Atom = new Type(1064,null);
-    public static final Type List = new Type(2000,null);
-    public static final Type FontCollection = new Type(2005,FontCollection.class);
-    public static final Type BookmarkCollection = new Type(2019,null);
-    public static final Type SoundCollection = new Type(2020,SoundCollection.class);
-    public static final Type SoundCollAtom = new Type(2021,null);
-    public static final Type Sound = new Type(2022,Sound.class);
-    public static final Type SoundData = new Type(2023,SoundData.class);
-    public static final Type BookmarkSeedAtom = new Type(2025,null);
-    public static final Type ColorSchemeAtom = new Type(2032,ColorSchemeAtom.class);
-    public static final Type ExObjRefAtom = new Type(3009,null);
-    public static final Type OEShapeAtom = new Type(3009,OEShapeAtom.class);
-    public static final Type OEPlaceholderAtom = new Type(3011,OEPlaceholderAtom.class);
-    public static final Type GPopublicintAtom = new Type(3024,null);
-    public static final Type GRatioAtom = new Type(3031,null);
-    public static final Type OutlineTextRefAtom = new Type(3998,OutlineTextRefAtom.class);
-    public static final Type TextHeaderAtom = new Type(3999,TextHeaderAtom.class);
-    public static final Type TextCharsAtom = new Type(4000,TextCharsAtom.class);
-    public static final Type StyleTextPropAtom = new Type(4001, StyleTextPropAtom.class);//0x0fa1 RT_StyleTextPropAtom
-    public static final Type MasterTextPropAtom = new Type(4002, MasterTextPropAtom.class);
-    public static final Type TxMasterStyleAtom = new Type(4003,TxMasterStyleAtom.class);
-    public static final Type TxCFStyleAtom = new Type(4004,null);
-    public static final Type TxPFStyleAtom = new Type(4005,null);
-    public static final Type TextRulerAtom = new Type(4006,TextRulerAtom.class);
-    public static final Type TextBookmarkAtom = new Type(4007,null);
-    public static final Type TextBytesAtom = new Type(4008,TextBytesAtom.class);
-    public static final Type TxSIStyleAtom = new Type(4009,null);
-    public static final Type TextSpecInfoAtom = new Type(4010, TextSpecInfoAtom.class);
-    public static final Type DefaultRulerAtom = new Type(4011,null);
-    public static final Type StyleTextProp9Atom = new Type(4012, StyleTextProp9Atom.class); //0x0FAC RT_StyleTextProp9Atom
-    public static final Type FontEntityAtom = new Type(4023,FontEntityAtom.class);
-    public static final Type FontEmbeddedData = new Type(4024,null);
-    public static final Type CString = new Type(4026,CString.class);
-    public static final Type MetaFile = new Type(4033,null);
-    public static final Type ExOleObjAtom = new Type(4035,ExOleObjAtom.class);
-    public static final Type SrKinsoku = new Type(4040,null);
-    public static final Type HandOut = new Type(4041,DummyPositionSensitiveRecordWithChildren.class);
-    public static final Type ExEmbed = new Type(4044,ExEmbed.class);
-    public static final Type ExEmbedAtom = new Type(4045,ExEmbedAtom.class);
-    public static final Type ExLink = new Type(4046,null);
-    public static final Type BookmarkEntityAtom = new Type(4048,null);
-    public static final Type ExLinkAtom = new Type(4049,null);
-    public static final Type SrKinsokuAtom = new Type(4050,null);
-    public static final Type ExHyperlinkAtom = new Type(4051,ExHyperlinkAtom.class);
-    public static final Type ExHyperlink = new Type(4055,ExHyperlink.class);
-    public static final Type SlideNumberMCAtom = new Type(4056,null);
-    public static final Type HeadersFooters = new Type(4057,HeadersFootersContainer.class);
-    public static final Type HeadersFootersAtom = new Type(4058,HeadersFootersAtom.class);
-    public static final Type TxInteractiveInfoAtom = new Type(4063,TxInteractiveInfoAtom.class);
-    public static final Type CharFormatAtom = new Type(4066,null);
-    public static final Type ParaFormatAtom = new Type(4067,null);
-    public static final Type RecolorInfoAtom = new Type(4071,null);
-    public static final Type ExQuickTimeMovie = new Type(4074,null);
-    public static final Type ExQuickTimeMovieData = new Type(4075,null);
-    public static final Type ExControl = new Type(4078,ExControl.class);
-    public static final Type SlideListWithText = new Type(4080,SlideListWithText.class);
-    public static final Type InteractiveInfo = new Type(4082,InteractiveInfo.class);
-    public static final Type InteractiveInfoAtom = new Type(4083,InteractiveInfoAtom.class);
-    public static final Type UserEditAtom = new Type(4085,UserEditAtom.class);
-    public static final Type CurrentUserAtom = new Type(4086,null);
-    public static final Type DateTimeMCAtom = new Type(4087,null);
-    public static final Type GenericDateMCAtom = new Type(4088,null);
-    public static final Type FooterMCAtom = new Type(4090,null);
-    public static final Type ExControlAtom = new Type(4091,ExControlAtom.class);
-    public static final Type ExMediaAtom = new Type(4100,ExMediaAtom.class);
-    public static final Type ExVideoContainer = new Type(4101,ExVideoContainer.class);
-    public static final Type ExAviMovie = new Type(4102,ExAviMovie.class);
-    public static final Type ExMCIMovie = new Type(4103,ExMCIMovie.class);
-    public static final Type ExMIDIAudio = new Type(4109,null);
-    public static final Type ExCDAudio = new Type(4110,null);
-    public static final Type ExWAVAudioEmbedded = new Type(4111,null);
-    public static final Type ExWAVAudioLink = new Type(4112,null);
-    public static final Type ExOleObjStg = new Type(4113,ExOleObjStg.class);
-    public static final Type ExCDAudioAtom = new Type(4114,null);
-    public static final Type ExWAVAudioEmbeddedAtom = new Type(4115,null);
-    public static final Type AnimationInfo = new Type(4116,AnimationInfo.class);
-    public static final Type AnimationInfoAtom = new Type(4081,AnimationInfoAtom.class);
-    public static final Type RTFDateTimeMCAtom = new Type(4117,null);
-    public static final Type ProgTags = new Type(5000,DummyPositionSensitiveRecordWithChildren.class);
-    public static final Type ProgStringTag = new Type(5001,null);
-    public static final Type ProgBinaryTag = new Type(5002,DummyPositionSensitiveRecordWithChildren.class);
-    public static final Type BinaryTagData = new Type(5003, BinaryTagDataBlob.class);//0x138b RT_BinaryTagDataBlob
-    public static final Type PrpublicintOptions = new Type(6000,null);
-    public static final Type PersistPtrFullBlock = new Type(6001,PersistPtrHolder.class);
-    public static final Type PersistPtrIncrementalBlock = new Type(6002,PersistPtrHolder.class);
-    public static final Type GScalingAtom = new Type(10001,null);
-    public static final Type GRColorAtom = new Type(10002,null);
+public enum RecordTypes {
+    Unknown(0,null),
+    UnknownRecordPlaceholder(-1, UnknownRecordPlaceholder.class),
+    Document(1000,Document.class),
+    DocumentAtom(1001,DocumentAtom.class),
+    EndDocument(1002,null),
+    Slide(1006,Slide.class),
+    SlideAtom(1007,SlideAtom.class),
+    Notes(1008,Notes.class),
+    NotesAtom(1009,NotesAtom.class),
+    Environment(1010,Environment.class),
+    SlidePersistAtom(1011,SlidePersistAtom.class),
+    SSlideLayoutAtom(1015,null),
+    MainMaster(1016,MainMaster.class),
+    SSSlideInfoAtom(1017,SSSlideInfoAtom.class),
+    SlideViewInfo(1018,null),
+    GuideAtom(1019,null),
+    ViewInfo(1020,null),
+    ViewInfoAtom(1021,null),
+    SlideViewInfoAtom(1022,null),
+    VBAInfo(1023,null),
+    VBAInfoAtom(1024,null),
+    SSDocInfoAtom(1025,null),
+    Summary(1026,null),
+    DocRoutingSlip(1030,null),
+    OutlineViewInfo(1031,null),
+    SorterViewInfo(1032,null),
+    ExObjList(1033,ExObjList.class),
+    ExObjListAtom(1034,ExObjListAtom.class),
+    PPDrawingGroup(1035,PPDrawingGroup.class),
+    PPDrawing(1036,PPDrawing.class),
+    NamedShows(1040,null),
+    NamedShow(1041,null),
+    NamedShowSlides(1042,null),
+    SheetProperties(1044,null),
+    RoundTripCustomTableStyles12Atom(1064,null),
+    List(2000,null),
+    FontCollection(2005,FontCollection.class),
+    BookmarkCollection(2019,null),
+    SoundCollection(2020,SoundCollection.class),
+    SoundCollAtom(2021,null),
+    Sound(2022,Sound.class),
+    SoundData(2023,SoundData.class),
+    BookmarkSeedAtom(2025,null),
+    ColorSchemeAtom(2032,ColorSchemeAtom.class),
+    ExObjRefAtom(3009,ExObjRefAtom.class),
+    OEPlaceholderAtom(3011,OEPlaceholderAtom.class),
+    GPopublicintAtom(3024,null),
+    GRatioAtom(3031,null),
+    OutlineTextRefAtom(3998,OutlineTextRefAtom.class),
+    TextHeaderAtom(3999,TextHeaderAtom.class),
+    TextCharsAtom(4000,TextCharsAtom.class),
+    StyleTextPropAtom(4001, StyleTextPropAtom.class),//0x0fa1 RT_StyleTextPropAtom
+    MasterTextPropAtom(4002, MasterTextPropAtom.class),
+    TxMasterStyleAtom(4003,TxMasterStyleAtom.class),
+    TxCFStyleAtom(4004,null),
+    TxPFStyleAtom(4005,null),
+    TextRulerAtom(4006,TextRulerAtom.class),
+    TextBookmarkAtom(4007,null),
+    TextBytesAtom(4008,TextBytesAtom.class),
+    TxSIStyleAtom(4009,null),
+    TextSpecInfoAtom(4010, TextSpecInfoAtom.class),
+    DefaultRulerAtom(4011,null),
+    StyleTextProp9Atom(4012, StyleTextProp9Atom.class), //0x0FAC RT_StyleTextProp9Atom
+    FontEntityAtom(4023,FontEntityAtom.class),
+    FontEmbeddedData(4024,null),
+    CString(4026,CString.class),
+    MetaFile(4033,null),
+    ExOleObjAtom(4035,ExOleObjAtom.class),
+    SrKinsoku(4040,null),
+    HandOut(4041,DummyPositionSensitiveRecordWithChildren.class),
+    ExEmbed(4044,ExEmbed.class),
+    ExEmbedAtom(4045,ExEmbedAtom.class),
+    ExLink(4046,null),
+    BookmarkEntityAtom(4048,null),
+    ExLinkAtom(4049,null),
+    SrKinsokuAtom(4050,null),
+    ExHyperlinkAtom(4051,ExHyperlinkAtom.class),
+    ExHyperlink(4055,ExHyperlink.class),
+    SlideNumberMCAtom(4056,null),
+    HeadersFooters(4057,HeadersFootersContainer.class),
+    HeadersFootersAtom(4058,HeadersFootersAtom.class),
+    TxInteractiveInfoAtom(4063,TxInteractiveInfoAtom.class),
+    CharFormatAtom(4066,null),
+    ParaFormatAtom(4067,null),
+    RecolorInfoAtom(4071,null),
+    ExQuickTimeMovie(4074,null),
+    ExQuickTimeMovieData(4075,null),
+    ExControl(4078,ExControl.class),
+    SlideListWithText(4080,SlideListWithText.class),
+    InteractiveInfo(4082,InteractiveInfo.class),
+    InteractiveInfoAtom(4083,InteractiveInfoAtom.class),
+    UserEditAtom(4085,UserEditAtom.class),
+    CurrentUserAtom(4086,null),
+    DateTimeMCAtom(4087,null),
+    GenericDateMCAtom(4088,null),
+    FooterMCAtom(4090,null),
+    ExControlAtom(4091,ExControlAtom.class),
+    ExMediaAtom(4100,ExMediaAtom.class),
+    ExVideoContainer(4101,ExVideoContainer.class),
+    ExAviMovie(4102,ExAviMovie.class),
+    ExMCIMovie(4103,ExMCIMovie.class),
+    ExMIDIAudio(4109,null),
+    ExCDAudio(4110,null),
+    ExWAVAudioEmbedded(4111,null),
+    ExWAVAudioLink(4112,null),
+    ExOleObjStg(4113,ExOleObjStg.class),
+    ExCDAudioAtom(4114,null),
+    ExWAVAudioEmbeddedAtom(4115,null),
+    AnimationInfo(4116,AnimationInfo.class),
+    AnimationInfoAtom(4081,AnimationInfoAtom.class),
+    RTFDateTimeMCAtom(4117,null),
+    ProgTags(5000,DummyPositionSensitiveRecordWithChildren.class),
+    ProgStringTag(5001,null),
+    ProgBinaryTag(5002,DummyPositionSensitiveRecordWithChildren.class),
+    BinaryTagData(5003, BinaryTagDataBlob.class),//0x138b RT_BinaryTagDataBlob
+    PrpublicintOptions(6000,null),
+    PersistPtrFullBlock(6001,PersistPtrHolder.class),
+    PersistPtrIncrementalBlock(6002,PersistPtrHolder.class),
+    GScalingAtom(10001,null),
+    GRColorAtom(10002,null),
 
     // Records ~12000 seem to be related to the Comments used in PPT 2000/XP
     // (Comments in PPT97 are normal Escher text boxes)
-    public static final Type Comment2000 = new Type(12000,Comment2000.class);
-    public static final Type Comment2000Atom = new Type(12001,Comment2000Atom.class);
-    public static final Type Comment2000Summary = new Type(12004,null);
-    public static final Type Comment2000SummaryAtom = new Type(12005,null);
+    Comment2000(12000,Comment2000.class),
+    Comment2000Atom(12001,Comment2000Atom.class),
+    Comment2000Summary(12004,null),
+    Comment2000SummaryAtom(12005,null),
 
     // Records ~12050 seem to be related to Document Encryption
-    public static final Type DocumentEncryptionAtom = new Type(12052,DocumentEncryptionAtom.class);
+    DocumentEncryptionAtom(12052,DocumentEncryptionAtom.class),
+
+    OriginalMainMasterId(1052,null),
+    CompositeMasterId(1052,null),
+    RoundTripContentMasterInfo12(1054,null),
+    RoundTripShapeId12(1055,null),
+    RoundTripHFPlaceholder12(1056,RoundTripHFPlaceholder12.class),
+    RoundTripContentMasterId(1058,null),
+    RoundTripOArtTextStyles12(1059,null),
+    RoundTripShapeCheckSumForCustomLayouts12(1062,null),
+    RoundTripNotesMasterTextStyles12(1063,null),
+    RoundTripCustomTableStyles12(1064,null),
+
+    // records greater then 0xF000 belong to with Microsoft Office Drawing format also known as Escher
+    EscherDggContainer(0xF000,null),
+    EscherDgg(0xf006,null),
+    EscherCLSID(0xf016,null),
+    EscherOPT(0xf00b,null),
+    EscherBStoreContainer(0xf001,null),
+    EscherBSE(0xf007,null),
+    EscherBlip_START(0xf018,null),
+    EscherBlip_END(0xf117,null),
+    EscherDgContainer(0xf002,null),
+    EscherDg(0xf008,null),
+    EscherRegroupItems(0xf118,null),
+    EscherColorScheme(0xf120,null),
+    EscherSpgrContainer(0xf003,null),
+    EscherSpContainer(0xf004,null),
+    EscherSpgr(0xf009,null),
+    EscherSp(0xf00a,null),
+    EscherTextbox(0xf00c,null),
+    EscherClientTextbox(0xf00d,null),
+    EscherAnchor(0xf00e,null),
+    EscherChildAnchor(0xf00f,null),
+    EscherClientAnchor(0xf010,null),
+    EscherClientData(0xf011,null),
+    EscherSolverContainer(0xf005,null),
+    EscherConnectorRule(0xf012,null),
+    EscherAlignRule(0xf013,null),
+    EscherArcRule(0xf014,null),
+    EscherClientRule(0xf015,null),
+    EscherCalloutRule(0xf017,null),
+    EscherSelection(0xf119,null),
+    EscherColorMRU(0xf11a,null),
+    EscherDeletedPspl(0xf11d,null),
+    EscherSplitMenuColors(0xf11e,null),
+    EscherOleObject(0xf11f,null),
+    EscherUserDefined(0xf122,null);
+
+    private static final Map<Short,RecordTypes> LOOKUP;
+
+    static {
+        LOOKUP = new HashMap<Short,RecordTypes>();
+        for(RecordTypes s : values()) {
+            LOOKUP.put(s.typeID, s);
+        }
+    }    
+    
+    public final short typeID;
+    public final Class<? extends Record> handlingClass;
+
+    private RecordTypes(int typeID, Class<? extends Record> handlingClass) {
+        this.typeID = (short)typeID;
+        this.handlingClass = handlingClass;
+    }
+
+    public static RecordTypes forTypeID(int typeID) {
+        RecordTypes rt = LOOKUP.get((short)typeID);
+        return (rt != null) ? rt : UnknownRecordPlaceholder;
+    }
 
-    public static final Type OriginalMainMasterId = new Type(1052,null);
-    public static final Type CompositeMasterId = new Type(1052,null);
-    public static final Type RoundTripContentMasterInfo12 = new Type(1054,null);
-    public static final Type RoundTripShapeId12 = new Type(1055,null);
-    public static final Type RoundTripHFPlaceholder12 = new Type(1056,RoundTripHFPlaceholder12.class);
-    public static final Type RoundTripContentMasterId = new Type(1058,null);
-    public static final Type RoundTripOArtTextStyles12 = new Type(1059,null);
-    public static final Type RoundTripShapeCheckSumForCustomLayouts12 = new Type(1062,null);
-    public static final Type RoundTripNotesMasterTextStyles12 = new Type(1063,null);
-    public static final Type RoundTripCustomTableStyles12 = new Type(1064,null);
 
-    //records greater then 0xF000 belong to with Microsoft Office Drawing format also known as Escher
-    public static final int EscherDggContainer = 0xf000;
-    public static final int EscherDgg = 0xf006;
-    public static final int EscherCLSID = 0xf016;
-    public static final int EscherOPT = 0xf00b;
-    public static final int EscherBStoreContainer = 0xf001;
-    public static final int EscherBSE = 0xf007;
-    public static final int EscherBlip_START = 0xf018;
-    public static final int EscherBlip_END = 0xf117;
-    public static final int EscherDgContainer = 0xf002;
-    public static final int EscherDg = 0xf008;
-    public static final int EscherRegroupItems = 0xf118;
-    public static final int EscherColorScheme = 0xf120;
-    public static final int EscherSpgrContainer = 0xf003;
-    public static final int EscherSpContainer = 0xf004;
-    public static final int EscherSpgr = 0xf009;
-    public static final int EscherSp = 0xf00a;
-    public static final int EscherTextbox = 0xf00c;
-    public static final int EscherClientTextbox = 0xf00d;
-    public static final int EscherAnchor = 0xf00e;
-    public static final int EscherChildAnchor = 0xf00f;
-    public static final int EscherClientAnchor = 0xf010;
-    public static final int EscherClientData = 0xf011;
-    public static final int EscherSolverContainer = 0xf005;
-    public static final int EscherConnectorRule = 0xf012;
-    public static final int EscherAlignRule = 0xf013;
-    public static final int EscherArcRule = 0xf014;
-    public static final int EscherClientRule = 0xf015;
-    public static final int EscherCalloutRule = 0xf017;
-    public static final int EscherSelection = 0xf119;
-    public static final int EscherColorMRU = 0xf11a;
-    public static final int EscherDeletedPspl = 0xf11d;
-    public static final int EscherSplitMenuColors = 0xf11e;
-    public static final int EscherOleObject = 0xf11f;
-    public static final int EscherUserDefined = 0xf122;
 
     /**
      * Returns name of the record by its type
@@ -218,10 +236,10 @@ public final class RecordTypes {
      * @param type section of the record header
      * @return name of the record
      */
-    public static String recordName(int type) {
-        String name = typeToName.get(Integer.valueOf(type));
-        return (name == null) ? ("Unknown" + type) : name;
-    }
+//    public static String recordName(int type) {
+//        String name = typeToName.get(Integer.valueOf(type));
+//        return (name == null) ? ("Unknown" + type) : name;
+//    }
 
     /**
      * Returns the class handling a record by its type.
@@ -232,38 +250,38 @@ public final class RecordTypes {
      * @param type section of the record header
      * @return class to handle the record, or null if an unknown (eg Escher) record
      */
-       public static Class<? extends Record> recordHandlingClass(int type) {
-               Class<? extends Record> c = typeToClass.get(Integer.valueOf(type));
-               return c;
-       }
-
-    static {
-               typeToName = new HashMap<Integer,String>();
-               typeToClass = new HashMap<Integer,Class<? extends Record>>();
-        try {
-            Field[] f = RecordTypes.class.getFields();
-            for (int i = 0; i < f.length; i++){
-               Object val = f[i].get(null);
-
-               // Escher record, only store ID -> Name
-               if (val instanceof Integer) {
-                  typeToName.put((Integer)val, f[i].getName());
-               }
-               // PowerPoint record, store ID -> Name and ID -> Class
-               if (val instanceof Type) {
-                  Type t = (Type)val;
-                  Class<? extends Record> c = t.handlingClass;
-                  Integer id = Integer.valueOf(t.typeID);
-                  if(c == null) { c = UnknownRecordPlaceholder.class; }
-
-                  typeToName.put(id, f[i].getName());
-                  typeToClass.put(id, c);
-               }
-            }
-        } catch (IllegalAccessException e){
-            throw new RuntimeException("Failed to initialize records types");
-        }
-    }
+//     public static Class<? extends Record> recordHandlingClass(int type) {
+//             Class<? extends Record> c = typeToClass.get(Integer.valueOf(type));
+//             return c;
+//     }
+//
+//    static {
+//             typeToName = new HashMap<Integer,String>();
+//             typeToClass = new HashMap<Integer,Class<? extends Record>>();
+//        try {
+//            Field[] f = RecordTypes.class.getFields();
+//            for (int i = 0; i < f.length; i++){
+//               Object val = f[i].get(null);
+//
+//               // Escher record, only store ID -> Name
+//               if (val instanceof Integer) {
+//                  typeToName.put((Integer)val, f[i].getName());
+//               }
+//               // PowerPoint record, store ID -> Name and ID -> Class
+//               if (val instanceof Type) {
+//                  Type t = (Type)val;
+//                  Class<? extends Record> c = t.handlingClass;
+//                  Integer id = Integer.valueOf(t.typeID);
+//                  if(c == null) { c = UnknownRecordPlaceholder.class; }
+//
+//                  typeToName.put(id, f[i].getName());
+//                  typeToClass.put(id, c);
+//               }
+//            }
+//        } catch (IllegalAccessException e){
+//            throw new RuntimeException("Failed to initialize records types");
+//        }
+//    }
 
 
        /**
@@ -271,12 +289,12 @@ public final class RecordTypes {
         * Contains both the type, and the handling class (if any), and
         *  offers methods to get either back out.
         */
-       public static class Type {
-               public final int typeID;
-               public final Class<? extends Record> handlingClass;
-               public Type(int typeID, Class<? extends Record> handlingClass) {
-                       this.typeID = typeID;
-                       this.handlingClass = handlingClass;
-               }
-       }
+//     public static class Type {
+//             public final int typeID;
+//             public final Class<? extends Record> handlingClass;
+//             public Type(int typeID, Class<? extends Record> handlingClass) {
+//                     this.typeID = typeID;
+//                     this.handlingClass = handlingClass;
+//             }
+//     }
 }
index 412beb1fc2819c5a5b14844c70952ec22c77d3d4..e843f1dd739f6b726f2a9218db1998404e1649c0 100644 (file)
@@ -20,6 +20,8 @@ package org.apache.poi.hslf.record;
 import java.io.IOException;
 import java.io.OutputStream;
 
+import org.apache.poi.util.LittleEndian;
+
 /**
  * An atom record that specifies that a shape is a header or footer placeholder shape
  *
@@ -40,6 +42,17 @@ public final class RoundTripHFPlaceholder12 extends RecordAtom {
      */
     private byte _placeholderId;
 
+    /**
+     * Create a new instance of <code>RoundTripHFPlaceholder12</code>
+     */
+    public RoundTripHFPlaceholder12(){
+        _header = new byte[8];
+        LittleEndian.putUShort(_header, 0, 0);
+        LittleEndian.putUShort(_header, 2, (int)getRecordType());
+        LittleEndian.putInt(_header, 4, 8);
+        _placeholderId = 0;
+    }
+    
     /**
      * Constructs the comment atom record from its source data.
      *
index 6d1c4873d7e4e88ca473e69fa2e4400792186f28..9ee64d62814c7c6350e61696e6a918df8e868854 100644 (file)
@@ -171,7 +171,7 @@ public final class TxMasterStyleAtom extends RecordAtom {
     /**
      * Updates the rawdata from the modified paragraph/character styles
      * 
-     * @since 3.14-beta1
+     * @since POI 3.14-beta1
      */
     public void updateStyles() {
         int type = getTextType();
index 02608b74a3b0b25fa412ae7c919f564a31b7c733..d20f0efa9bcb12341bb53904e5d3c729b48c4c5e 100644 (file)
 
 package org.apache.poi.hslf.usermodel;
 
-import java.util.*;
-
-import org.apache.poi.ddf.*;
-import org.apache.poi.hslf.record.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.ListIterator;
+
+import org.apache.poi.hslf.record.ExHyperlink;
+import org.apache.poi.hslf.record.ExObjList;
+import org.apache.poi.hslf.record.HSLFEscherClientDataRecord;
+import org.apache.poi.hslf.record.InteractiveInfo;
+import org.apache.poi.hslf.record.InteractiveInfoAtom;
+import org.apache.poi.hslf.record.Record;
+import org.apache.poi.hslf.record.TxInteractiveInfoAtom;
 
 /**
  * Represents a hyperlink in a PowerPoint document
@@ -156,6 +164,7 @@ public final class HSLFHyperlink {
      * @param paragraphs  List of <code>TextParagraph</code> to lookup hyperlinks
      * @return found hyperlinks
      */
+    @SuppressWarnings("resource")
     public static List<HSLFHyperlink> find(List<HSLFTextParagraph> paragraphs){
         List<HSLFHyperlink> lst = new ArrayList<HSLFHyperlink>();
         if (paragraphs == null || paragraphs.isEmpty()) return lst;
@@ -165,10 +174,10 @@ public final class HSLFHyperlink {
         HSLFSlideShow ppt = firstPara.getSheet().getSlideShow();
         //document-level container which stores info about all links in a presentation
         ExObjList exobj = ppt.getDocumentRecord().getExObjList();
-        if (exobj == null) return lst;
-        
-        Record[] records = firstPara.getRecords();
-        find(records, exobj, lst);
+        if (exobj != null) {
+            Record[] records = firstPara.getRecords();
+            find(Arrays.asList(records), exobj, lst);
+        }
 
         return lst;
     }
@@ -179,39 +188,38 @@ public final class HSLFHyperlink {
      * @param shape  <code>Shape</code> to lookup hyperlink in
      * @return found hyperlink or <code>null</code>
      */
+    @SuppressWarnings("resource")
     public static HSLFHyperlink find(HSLFShape shape){
-        List<HSLFHyperlink> lst = new ArrayList<HSLFHyperlink>();
         HSLFSlideShow ppt = shape.getSheet().getSlideShow();
         //document-level container which stores info about all links in a presentation
         ExObjList exobj = ppt.getDocumentRecord().getExObjList();
-        if (exobj == null) {
-            return null;
-        }
+        HSLFEscherClientDataRecord cldata = shape.getClientData(false);
 
-        EscherContainerRecord spContainer = shape.getSpContainer();
-        for (Iterator<EscherRecord> it = spContainer.getChildIterator(); it.hasNext(); ) {
-            EscherRecord obj = it.next();
-            if (obj.getRecordId() ==  EscherClientDataRecord.RECORD_ID){
-                byte[] data = obj.serialize();
-                Record[] records = Record.findChildRecords(data, 8, data.length-8);
-                find(records, exobj, lst);
-            }
+        if (exobj != null && cldata != null) {
+            List<HSLFHyperlink> lst = new ArrayList<HSLFHyperlink>();
+            find(cldata.getHSLFChildRecords(), exobj, lst);
+            return lst.isEmpty() ? null : (HSLFHyperlink)lst.get(0);
         }
 
-        return lst.size() == 1 ? (HSLFHyperlink)lst.get(0) : null;
+        return null;
     }
 
-    private static void find(Record[] records, ExObjList exobj, List<HSLFHyperlink> out){
-        if (records == null) return;
-        for (int i = 0; i < records.length; i++) {
-            //see if we have InteractiveInfo in the textrun's records
-            if(!(records[i] instanceof InteractiveInfo)) continue;
-            
-            InteractiveInfo hldr = (InteractiveInfo)records[i];
+    private static void find(List<? extends Record> records, ExObjList exobj, List<HSLFHyperlink> out){
+        ListIterator<? extends Record> iter = records.listIterator();
+        while (iter.hasNext()) {
+            Record r = iter.next();
+            // see if we have InteractiveInfo in the textrun's records
+            if (!(r instanceof InteractiveInfo)) {
+                continue;
+            }
+
+            InteractiveInfo hldr = (InteractiveInfo)r;
             InteractiveInfoAtom info = hldr.getInteractiveInfoAtom();
             int id = info.getHyperlinkID();
             ExHyperlink linkRecord = exobj.get(id);
-            if (linkRecord == null) continue;
+            if (linkRecord == null) {
+                continue;
+            }
             
             HSLFHyperlink link = new HSLFHyperlink();
             link.title = linkRecord.getLinkTitle();
@@ -219,8 +227,13 @@ public final class HSLFHyperlink {
             link.type = info.getAction();
             out.add(link);
 
-            if (i+1 < records.length && records[i+1] instanceof TxInteractiveInfoAtom){
-                TxInteractiveInfoAtom txinfo = (TxInteractiveInfoAtom)records[++i];
+            if (iter.hasNext()) {
+                r = iter.next();
+                if (!(r instanceof TxInteractiveInfoAtom)) {
+                    iter.previous();
+                    continue;
+                }
+                TxInteractiveInfoAtom txinfo = (TxInteractiveInfoAtom)r;
                 link.startIndex = txinfo.getStartIndex();
                 link.endIndex = txinfo.getEndIndex();
             }
index c0a7aef69e49811ce4a703f10d2494acf32e32c7..22b1d90abb21e514b4ebfd05298b1e5de43bc1db 100644 (file)
@@ -18,7 +18,7 @@
 package org.apache.poi.hslf.usermodel;
 
 import org.apache.poi.ddf.EscherContainerRecord;
-import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
+import org.apache.poi.sl.usermodel.Placeholder;
 import org.apache.poi.sl.usermodel.ShapeContainer;
 
 /**
index 38483d03a45df07f8074b756bbb32b1a8212007c..e4ef3b1b779f4f0e0a50de338dbffb25ef8d05e7 100644 (file)
@@ -21,6 +21,7 @@ import java.awt.Color;
 import java.awt.Graphics2D;
 import java.awt.geom.Rectangle2D;
 import java.util.Iterator;
+import java.util.List;
 
 import org.apache.poi.ddf.AbstractEscherOptRecord;
 import org.apache.poi.ddf.EscherChildAnchorRecord;
@@ -33,7 +34,10 @@ import org.apache.poi.ddf.EscherProperty;
 import org.apache.poi.ddf.EscherRecord;
 import org.apache.poi.ddf.EscherSimpleProperty;
 import org.apache.poi.ddf.EscherSpRecord;
+import org.apache.poi.ddf.EscherTextboxRecord;
 import org.apache.poi.hslf.record.ColorSchemeAtom;
+import org.apache.poi.hslf.record.HSLFEscherClientDataRecord;
+import org.apache.poi.hslf.record.Record;
 import org.apache.poi.hslf.record.RecordTypes;
 import org.apache.poi.sl.usermodel.FillStyle;
 import org.apache.poi.sl.usermodel.Shape;
@@ -217,19 +221,32 @@ public abstract class HSLFShape implements Shape<HSLFShape,HSLFTextParagraph> {
     public static <T extends EscherRecord> T getEscherChild(EscherContainerRecord owner, int recordId){
         return owner.getChildById((short)recordId);
     }
+    
+    /**
+     * @since POI 3.14-Beta2
+     */
+    public static <T extends EscherRecord> T getEscherChild(EscherContainerRecord owner, RecordTypes recordId){
+        return getEscherChild(owner, recordId.typeID);
+    }
 
     public <T extends EscherRecord> T getEscherChild(int recordId){
         return _escherContainer.getChildById((short)recordId);
     }
     
+    /**
+     * @since POI 3.14-Beta2
+     */
+    public <T extends EscherRecord> T getEscherChild(RecordTypes recordId){
+        return getEscherChild(recordId.typeID);
+    }
+    
     /**
      * Returns  escher property by id.
      *
      * @return escher property or <code>null</code> if not found.
      */
      public static <T extends EscherProperty> T getEscherProperty(AbstractEscherOptRecord opt, int propId){
-         if (opt == null) return null;
-         return opt.lookup(propId);
+         return (opt == null) ? null : opt.<T>lookup(propId);
      }
 
     /**
@@ -443,7 +460,7 @@ public abstract class HSLFShape implements Shape<HSLFShape,HSLFTextParagraph> {
     }
 
     public AbstractEscherOptRecord getEscherOptRecord() {
-        AbstractEscherOptRecord opt = getEscherChild(EscherOptRecord.RECORD_ID);
+        AbstractEscherOptRecord opt = getEscherChild(RecordTypes.EscherOPT);
         if (opt == null) {
             opt = getEscherChild(RecordTypes.EscherUserDefined);
         }
@@ -485,4 +502,48 @@ public abstract class HSLFShape implements Shape<HSLFShape,HSLFTextParagraph> {
     public boolean isPlaceholder() {
         return false;
     }
+
+    /**
+     *  Find a record in the underlying EscherClientDataRecord
+     *
+     * @param recordType type of the record to search
+     */
+    @SuppressWarnings("unchecked")
+    public <T extends Record> T getClientDataRecord(int recordType) {
+
+        List<? extends Record> records = getClientRecords();
+        if (records != null) for (Record r : records) {
+            if (r.getRecordType() == recordType){
+                return (T)r;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Search for EscherClientDataRecord, if found, convert its contents into an array of HSLF records
+     *
+     * @return an array of HSLF records contained in the shape's EscherClientDataRecord or <code>null</code>
+     */
+    protected List<? extends Record> getClientRecords() {
+        HSLFEscherClientDataRecord clientData = getClientData(false);
+        return (clientData == null) ? null : clientData.getHSLFChildRecords();
+    }
+
+    /**
+     * Create a new HSLF-specific EscherClientDataRecord
+     *
+     * @param create if true, create the missing record 
+     * @return the client record or null if it was missing and create wasn't activated
+     */
+    protected HSLFEscherClientDataRecord getClientData(boolean create) {
+        HSLFEscherClientDataRecord clientData = getEscherChild(HSLFEscherClientDataRecord.RECORD_ID);
+        if (clientData == null && create) {
+            clientData = new HSLFEscherClientDataRecord();
+            clientData.setOptions((short)15);
+            clientData.setRecordId(HSLFEscherClientDataRecord.RECORD_ID);
+            getSpContainer().addChildBefore(clientData, EscherTextboxRecord.RECORD_ID);
+        }
+        return clientData;
+    }
 }
index 737d2927a2111178f7a2ef3e110f0144b0473153..19717135368b4b705de2c8775451ae9975967716 100644 (file)
 
 package org.apache.poi.hslf.usermodel;
 
-import java.util.Iterator;
 import java.util.List;
 
-import org.apache.poi.ddf.*;
-import org.apache.poi.hslf.model.*;
-import org.apache.poi.hslf.record.*;
+import org.apache.poi.ddf.AbstractEscherOptRecord;
+import org.apache.poi.ddf.EscherClientDataRecord;
+import org.apache.poi.ddf.EscherContainerRecord;
+import org.apache.poi.ddf.EscherOptRecord;
+import org.apache.poi.ddf.EscherProperties;
+import org.apache.poi.ddf.EscherProperty;
+import org.apache.poi.ddf.EscherPropertyFactory;
+import org.apache.poi.ddf.EscherRecord;
+import org.apache.poi.ddf.EscherSimpleProperty;
+import org.apache.poi.ddf.EscherSpRecord;
+import org.apache.poi.ddf.EscherTextboxRecord;
+import org.apache.poi.hslf.model.MovieShape;
+import org.apache.poi.hslf.model.OLEShape;
+import org.apache.poi.hslf.record.ExObjRefAtom;
+import org.apache.poi.hslf.record.HSLFEscherClientDataRecord;
+import org.apache.poi.hslf.record.InteractiveInfo;
+import org.apache.poi.hslf.record.InteractiveInfoAtom;
+import org.apache.poi.hslf.record.Record;
+import org.apache.poi.hslf.record.RecordTypes;
 import org.apache.poi.sl.usermodel.ShapeContainer;
 import org.apache.poi.sl.usermodel.ShapeType;
 import org.apache.poi.util.POILogFactory;
@@ -50,7 +65,7 @@ public final class HSLFShapeFactory {
     public static HSLFGroupShape createShapeGroup(EscherContainerRecord spContainer, ShapeContainer<HSLFShape,HSLFTextParagraph> parent){
         boolean isTable = false;
         EscherContainerRecord ecr = (EscherContainerRecord)spContainer.getChild(0);
-        EscherRecord opt = HSLFShape.getEscherChild(ecr, (short)RecordTypes.EscherUserDefined);
+        EscherRecord opt = HSLFShape.getEscherChild(ecr, RecordTypes.EscherUserDefined);
 
         if (opt != null) {
             EscherPropertyFactory f = new EscherPropertyFactory();
@@ -120,12 +135,10 @@ public final class HSLFShapeFactory {
             }
         }
         
-        OEShapeAtom oes = getClientDataRecord(spContainer, RecordTypes.OEShapeAtom.typeID);
-        if (oes != null){
-            return new OLEShape(spContainer, parent);
-        }
-
-        return new HSLFPictureShape(spContainer, parent);
+        ExObjRefAtom oes = getClientDataRecord(spContainer, RecordTypes.ExObjRefAtom.typeID);
+        return (oes != null)
+            ? new OLEShape(spContainer, parent)
+            : new HSLFPictureShape(spContainer, parent);
     }
     
     private static HSLFShape createNonPrimitive(EscherContainerRecord spContainer, ShapeContainer<HSLFShape,HSLFTextParagraph> parent) {
@@ -141,15 +154,10 @@ public final class HSLFShapeFactory {
     
     @SuppressWarnings("unchecked")
     protected static <T extends Record> T getClientDataRecord(EscherContainerRecord spContainer, int recordType) {
-        for (Iterator<EscherRecord> it = spContainer.getChildIterator(); it.hasNext();) {
-            EscherRecord obj = it.next();
-            if (obj.getRecordId() == EscherClientDataRecord.RECORD_ID) {
-                byte[] data = obj.serialize();
-                for (Record r : Record.findChildRecords(data, 8, data.length - 8)) {
-                    if (r.getRecordType() == recordType) {
-                        return (T)r;
-                    }
-                }
+        HSLFEscherClientDataRecord cldata = spContainer.getChildById(EscherClientDataRecord.RECORD_ID);
+        if (cldata != null) for (Record r : cldata.getHSLFChildRecords()) {
+            if (r.getRecordType() == recordType) {
+                return (T)r;
             }
         }
         return null;
index e80070e6c2967106e41074f4a15ae341573a896b..3fe79aeb16417a793f00ce211611a6dac5431996 100644 (file)
@@ -149,7 +149,7 @@ public abstract class HSLFSheet implements HSLFShapeContainer, Sheet<HSLFShape,H
     public List<HSLFShape> getShapes() {
         PPDrawing ppdrawing = getPPDrawing();
 
-        EscherContainerRecord dg = (EscherContainerRecord) ppdrawing.getEscherRecords()[0];
+        EscherContainerRecord dg = ppdrawing.getDgContainer();
         EscherContainerRecord spgr = null;
 
         for (Iterator<EscherRecord> it = dg.getChildIterator(); it.hasNext();) {
@@ -187,7 +187,7 @@ public abstract class HSLFSheet implements HSLFShapeContainer, Sheet<HSLFShape,H
     public void addShape(HSLFShape shape) {
         PPDrawing ppdrawing = getPPDrawing();
 
-        EscherContainerRecord dgContainer = (EscherContainerRecord) ppdrawing.getEscherRecords()[0];
+        EscherContainerRecord dgContainer = ppdrawing.getDgContainer();
         EscherContainerRecord spgr = (EscherContainerRecord) HSLFShape.getEscherChild(dgContainer, EscherContainerRecord.SPGR_CONTAINER);
         spgr.addChildRecord(shape.getSpContainer());
 
@@ -244,16 +244,8 @@ public abstract class HSLFSheet implements HSLFShapeContainer, Sheet<HSLFShape,H
     public boolean removeShape(HSLFShape shape) {
         PPDrawing ppdrawing = getPPDrawing();
 
-        EscherContainerRecord dg = (EscherContainerRecord) ppdrawing.getEscherRecords()[0];
-        EscherContainerRecord spgr = null;
-
-        for (Iterator<EscherRecord> it = dg.getChildIterator(); it.hasNext();) {
-            EscherRecord rec = it.next();
-            if (rec.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) {
-                spgr = (EscherContainerRecord) rec;
-                break;
-            }
-        }
+        EscherContainerRecord dg = ppdrawing.getDgContainer();
+        EscherContainerRecord spgr = dg.getChildById(EscherContainerRecord.SPGR_CONTAINER);
         if(spgr == null) {
             return false;
         }
@@ -292,7 +284,7 @@ public abstract class HSLFSheet implements HSLFShapeContainer, Sheet<HSLFShape,H
         if (_background == null) {
             PPDrawing ppdrawing = getPPDrawing();
 
-            EscherContainerRecord dg = (EscherContainerRecord) ppdrawing.getEscherRecords()[0];
+            EscherContainerRecord dg = ppdrawing.getDgContainer();
             EscherContainerRecord spContainer = dg.getChildById(EscherContainerRecord.SP_CONTAINER);
             _background = new HSLFBackground(spContainer, null);
             _background.setSheet(this);
index 47ab16b1679a31b79a24a3c0885321049429ce0f..4da85a946eec65673db47ed9c6e30e5f52ccb931 100644 (file)
 package org.apache.poi.hslf.usermodel;
 
 import java.awt.Color;
-import java.io.ByteArrayOutputStream;
-
-import org.apache.poi.ddf.*;
+import java.util.List;
+
+import org.apache.poi.ddf.AbstractEscherOptRecord;
+import org.apache.poi.ddf.EscherChildAnchorRecord;
+import org.apache.poi.ddf.EscherClientAnchorRecord;
+import org.apache.poi.ddf.EscherContainerRecord;
+import org.apache.poi.ddf.EscherOptRecord;
+import org.apache.poi.ddf.EscherProperties;
+import org.apache.poi.ddf.EscherProperty;
+import org.apache.poi.ddf.EscherRecord;
+import org.apache.poi.ddf.EscherSimpleProperty;
+import org.apache.poi.ddf.EscherSpRecord;
 import org.apache.poi.hslf.exceptions.HSLFException;
-import org.apache.poi.hslf.record.*;
+import org.apache.poi.hslf.record.HSLFEscherClientDataRecord;
+import org.apache.poi.hslf.record.InteractiveInfo;
+import org.apache.poi.hslf.record.InteractiveInfoAtom;
+import org.apache.poi.hslf.record.OEPlaceholderAtom;
+import org.apache.poi.hslf.record.Record;
+import org.apache.poi.hslf.record.RoundTripHFPlaceholder12;
 import org.apache.poi.sl.draw.DrawPaint;
-import org.apache.poi.sl.draw.geom.*;
-import org.apache.poi.sl.usermodel.*;
-import org.apache.poi.sl.usermodel.LineDecoration.*;
+import org.apache.poi.sl.draw.geom.CustomGeometry;
+import org.apache.poi.sl.draw.geom.Guide;
+import org.apache.poi.sl.draw.geom.PresetGeometries;
+import org.apache.poi.sl.usermodel.LineDecoration;
+import org.apache.poi.sl.usermodel.LineDecoration.DecorationShape;
+import org.apache.poi.sl.usermodel.LineDecoration.DecorationSize;
+import org.apache.poi.sl.usermodel.PaintStyle;
 import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
+import org.apache.poi.sl.usermodel.Placeholder;
+import org.apache.poi.sl.usermodel.Shadow;
+import org.apache.poi.sl.usermodel.ShapeContainer;
+import org.apache.poi.sl.usermodel.ShapeType;
+import org.apache.poi.sl.usermodel.SimpleShape;
+import org.apache.poi.sl.usermodel.StrokeStyle;
 import org.apache.poi.sl.usermodel.StrokeStyle.LineCap;
 import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound;
 import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
@@ -45,12 +69,6 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H
 
     public final static double DEFAULT_LINE_WIDTH = 0.75;
 
-    /**
-     * Records stored in EscherClientDataRecord
-     */
-    protected Record[] _clientRecords;
-    protected EscherClientDataRecord _clientData;
-
     /**
      * Create a SimpleShape object and initialize it from the supplied Record container.
      *
@@ -82,9 +100,10 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H
         opt.setRecordId(EscherOptRecord.RECORD_ID);
         _escherContainer.addChildRecord(opt);
 
-        EscherRecord anchor;
-        if(isChild) anchor = new EscherChildAnchorRecord();
-        else {
+        EscherRecord anchor; 
+        if(isChild) {
+            anchor = new EscherChildAnchorRecord();
+        } else {
             anchor = new EscherClientAnchorRecord();
 
             //hack. internal variable EscherClientAnchorRecord.shortRecord can be
@@ -251,70 +270,11 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H
         getFill().setForegroundColor(color);
     }
 
-    /**
-     *  Find a record in the underlying EscherClientDataRecord
-     *
-     * @param recordType type of the record to search
-     */
-    @SuppressWarnings("unchecked")
-    protected <T extends Record> T getClientDataRecord(int recordType) {
-
-        Record[] records = getClientRecords();
-        if(records != null) for (int i = 0; i < records.length; i++) {
-            if(records[i].getRecordType() == recordType){
-                return (T)records[i];
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Search for EscherClientDataRecord, if found, convert its contents into an array of HSLF records
-     *
-     * @return an array of HSLF records contained in the shape's EscherClientDataRecord or <code>null</code>
-     */
-    protected Record[] getClientRecords() {
-        if(_clientData == null){
-            EscherRecord r = getEscherChild(EscherClientDataRecord.RECORD_ID);
-            //ddf can return EscherContainerRecord with recordId=EscherClientDataRecord.RECORD_ID
-            //convert in to EscherClientDataRecord on the fly
-            if(r != null && !(r instanceof EscherClientDataRecord)){
-                byte[] data = r.serialize();
-                r = new EscherClientDataRecord();
-                r.fillFields(data, 0, new HSLFEscherRecordFactory());
-            }
-            _clientData = (EscherClientDataRecord)r;
-        }
-        if(_clientData != null && _clientRecords == null){
-            byte[] data = _clientData.getRemainingData();
-            _clientRecords = Record.findChildRecords(data, 0, data.length);
-        }
-        return _clientRecords;
-    }
-
-    protected void updateClientData() {
-        if(_clientData != null && _clientRecords != null){
-            ByteArrayOutputStream out = new ByteArrayOutputStream();
-            try {
-                for (int i = 0; i < _clientRecords.length; i++) {
-                    _clientRecords[i].writeOut(out);
-                }
-            } catch(Exception e){
-                throw new HSLFException(e);
-            }
-            _clientData.setRemainingData(out.toByteArray());
-        }
-    }
-
     public void setHyperlink(HSLFHyperlink link){
         if(link.getId() == -1){
             throw new HSLFException("You must call SlideShow.addHyperlink(Hyperlink link) first");
         }
 
-        EscherClientDataRecord cldata = new EscherClientDataRecord();
-        cldata.setOptions((short)0xF);
-        getSpContainer().addChildRecord(cldata); // TODO - junit to prove getChildRecords().add is wrong
-
         InteractiveInfo info = new InteractiveInfo();
         InteractiveInfoAtom infoAtom = info.getInteractiveInfoAtom();
 
@@ -356,14 +316,8 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H
 
         infoAtom.setHyperlinkID(link.getId());
 
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        try {
-            info.writeOut(out);
-        } catch(Exception e){
-            throw new HSLFException(e);
-        }
-        cldata.setRemainingData(out.toByteArray());
-
+        HSLFEscherClientDataRecord cldata = getClientData(true);
+        cldata.addChild(infoAtom);
     }
 
     public Guide getAdjustValue(String name) {
@@ -560,99 +514,119 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H
             }
         };
     }
-
-    protected void setPlaceholder(Placeholder placeholder) {
-        EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID);
+    
+    @Override
+    public Placeholder getPlaceholder() {
+        List<? extends Record> clRecords = getClientRecords();
+        if (clRecords == null) {
+            return null;
+        }
+        for (Record r : clRecords) {
+            if (r instanceof OEPlaceholderAtom) {
+                OEPlaceholderAtom oep = (OEPlaceholderAtom)r;
+                return Placeholder.lookupNative(oep.getPlaceholderId());
+            } else if (r instanceof RoundTripHFPlaceholder12) {
+                RoundTripHFPlaceholder12 rtp = (RoundTripHFPlaceholder12)r;
+                return Placeholder.lookupNative(rtp.getPlaceholderId());
+            }
+        }
+        
+        return null;
+    }
+    
+    @Override
+    public void setPlaceholder(Placeholder placeholder) {
+        EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
         int flags = spRecord.getFlags();
-        flags |= EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HAVEMASTER;
-        spRecord.setFlags(flags);
-
-        EscherClientDataRecord cldata = _escherContainer.getChildById(EscherClientDataRecord.RECORD_ID);
-        if (cldata == null) {
-            cldata = new EscherClientDataRecord();
-            // append placeholder container before EscherTextboxRecord
-            _escherContainer.addChildBefore(cldata, EscherTextboxRecord.RECORD_ID);
+        if (placeholder == null) {
+            flags ^= EscherSpRecord.FLAG_HAVEMASTER;
+        } else {
+            flags |= EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HAVEMASTER;
         }
-        cldata.setOptions((short)15);
-
-        AbstractEscherOptRecord opt = getEscherOptRecord();
+        spRecord.setFlags(flags);
 
         // Placeholders can't be grouped
-        setEscherProperty(opt, EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 262144);
+        setEscherProperty(EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, (placeholder == null ? -1 : 262144));
+        
+        HSLFEscherClientDataRecord clientData = getClientData(false);
+        if (placeholder == null) {
+            if (clientData != null) {
+                clientData.removeChild(OEPlaceholderAtom.class);
+                clientData.removeChild(RoundTripHFPlaceholder12.class);
+                // remove client data if the placeholder was the only child to be carried
+                if (clientData.getChildRecords().isEmpty()) {
+                    getSpContainer().removeChildRecord(clientData);
+                }
+            }
+            return;
+        }
+        
+        if (clientData == null) {
+            clientData = getClientData(true);
+        }
 
         // OEPlaceholderAtom tells powerpoint that this shape is a placeholder
-        OEPlaceholderAtom oep = new OEPlaceholderAtom();
+        OEPlaceholderAtom oep = null;
+        RoundTripHFPlaceholder12 rtp = null;
+        for (Record r : clientData.getHSLFChildRecords()) {
+            if (r instanceof OEPlaceholderAtom) {
+                oep = (OEPlaceholderAtom)r;
+                break;
+            }
+            if (r instanceof RoundTripHFPlaceholder12) {
+                rtp = (RoundTripHFPlaceholder12)r;
+                break;
+            }
+        }
 
         /**
-         * Extarct from MSDN:
+         * Extract from MSDN:
          *
          * There is a special case when the placeholder does not have a position in the layout.
          * This occurs when the user has moved the placeholder from its original position.
          * In this case the placeholder ID is -1.
          */
-        oep.setPlacementId(-1);
-
-        boolean isMaster = (getSheet() instanceof HSLFSlideMaster);
-        boolean isNotes = (getSheet() instanceof HSLFNotes);
         byte phId;
+        HSLFSheet sheet = getSheet();
+        // TODO: implement/switch NotesMaster
+        if (sheet instanceof HSLFSlideMaster) {
+            phId = (byte)placeholder.nativeSlideMasterId;
+        } else if (sheet instanceof HSLFNotes) {
+            phId = (byte)placeholder.nativeNotesId;
+        } else {
+            phId = (byte)placeholder.nativeSlideId;
+        }
+        
+        if (phId == -2) {
+            throw new HSLFException("Placeholder "+placeholder.name()+" not supported for this sheet type ("+sheet.getClass()+")");
+        }
+        
         switch (placeholder) {
-            case TITLE:
-                phId = (isMaster) ? OEPlaceholderAtom.MasterTitle : OEPlaceholderAtom.Title;
-                break;
-            case BODY:
-                phId = (isMaster) ? OEPlaceholderAtom.MasterBody :
-                    ((isNotes) ? OEPlaceholderAtom.NotesBody : OEPlaceholderAtom.Body);
-                break;
-            case CENTERED_TITLE:
-                phId = (isMaster) ? OEPlaceholderAtom.MasterCenteredTitle : OEPlaceholderAtom.CenteredTitle;
-                break;
-            case SUBTITLE:
-                phId = (isMaster) ? OEPlaceholderAtom.MasterSubTitle : OEPlaceholderAtom.Subtitle;
-                break;
-            case DATETIME:
-                phId = OEPlaceholderAtom.MasterDate;
-                break;
-            case SLIDE_NUMBER:
-                phId = OEPlaceholderAtom.MasterSlideNumber;
-                break;
-            case FOOTER:
-                phId = OEPlaceholderAtom.MasterFooter;
-                break;
             case HEADER:
-                phId = OEPlaceholderAtom.MasterHeader;
-                break;
-            case DGM:
-            case CHART:
-                phId = OEPlaceholderAtom.Graph;
-                break;
-            case TABLE:
-                phId = OEPlaceholderAtom.Table;
-                break;
-            case PICTURE:
-            case CLIP_ART:
-                phId = OEPlaceholderAtom.ClipArt;
-                break;
-            case MEDIA:
-                phId = OEPlaceholderAtom.MediaClip;
-                break;
-            case SLIDE_IMAGE:
-                phId = (isMaster) ? OEPlaceholderAtom.MasterNotesSlideImage : OEPlaceholderAtom.NotesSlideImage;
+            case FOOTER:
+                if (rtp == null) {
+                    rtp = new RoundTripHFPlaceholder12();
+                    rtp.setPlaceholderId(phId);
+                    clientData.addChild(rtp);
+                }
+                if (oep != null) {
+                    clientData.removeChild(OEPlaceholderAtom.class);
+                }
                 break;
             default:
-            case CONTENT:
-                phId = OEPlaceholderAtom.Object;
+                if (rtp != null) {
+                    clientData.removeChild(RoundTripHFPlaceholder12.class);
+                }
+                if (oep == null) {
+                    oep = new OEPlaceholderAtom();
+                    oep.setPlaceholderSize((byte)OEPlaceholderAtom.PLACEHOLDER_FULLSIZE);
+                    // TODO: placement id only "SHOULD" be unique ... check other placeholders on sheet for unique id
+                    oep.setPlacementId(-1);
+                    oep.setPlaceholderId(phId);
+                    clientData.addChild(oep);
+                }
                 break;
         }
-        oep.setPlaceholderId(phId);
-
-        //convert hslf into ddf record
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        try {
-            oep.writeOut(out);
-        } catch(Exception e){
-            throw new HSLFException(e);
-        }
-        cldata.setRemainingData(out.toByteArray());
     }
 
 
index 1ebd32368e9d05ae5cb4125629ea079241f5b024..73223646c794dfec91c51e72174bc74f02533e1c 100644 (file)
@@ -42,8 +42,8 @@ import org.apache.poi.hslf.record.TextHeaderAtom;
 import org.apache.poi.sl.draw.DrawFactory;
 import org.apache.poi.sl.draw.Drawable;
 import org.apache.poi.sl.usermodel.Notes;
+import org.apache.poi.sl.usermodel.Placeholder;
 import org.apache.poi.sl.usermodel.ShapeType;
-import org.apache.poi.sl.usermodel.SimpleShape.Placeholder;
 import org.apache.poi.sl.usermodel.Slide;
 
 /**
@@ -163,7 +163,7 @@ public final class HSLFSlide extends HSLFSheet implements Slide<HSLFShape,HSLFTe
     public void onCreate(){
         //initialize drawing group id
         EscherDggRecord dgg = getSlideShow().getDocumentRecord().getPPDrawingGroup().getEscherDggRecord();
-        EscherContainerRecord dgContainer = (EscherContainerRecord)getSheetContainer().getPPDrawing().getEscherRecords()[0];
+        EscherContainerRecord dgContainer = getSheetContainer().getPPDrawing().getDgContainer();
         EscherDgRecord dg = (EscherDgRecord) HSLFShape.getEscherChild(dgContainer, EscherDgRecord.RECORD_ID);
         int dgId = dgg.getMaxDrawingGroupId() + 1;
         dg.setOptions((short)(dgId << 4));
index 33cdbf966ba882aa91d88cb76155d7d2fbea9228..f08c398074d160bf9ca77d7d1273417800d39f90 100644 (file)
@@ -1162,8 +1162,8 @@ public final class HSLFSlideShow implements SlideShow<HSLFShape,HSLFTextParagrap
         // For position dependent records, hold where they were and now are
         // As we go along, update, and hand over, to any Position Dependent
         // records we happen across
-               Map<RecordTypes.Type,PositionDependentRecord> interestingRecords =
-                new HashMap<RecordTypes.Type,PositionDependentRecord>();
+               Map<RecordTypes,PositionDependentRecord> interestingRecords =
+                new HashMap<RecordTypes,PositionDependentRecord>();
 
                try {
             _hslfSlideShow.updateAndWriteDependantRecords(null,interestingRecords);
index d27b6f050b9daea41425aea1003a4932f2e8934b..750c74ebf38a93ce163e4a06259090fd03b4141f 100644 (file)
@@ -474,7 +474,7 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
         *        May be null, if not needed. 
         * @throws IOException
         */
-       public void updateAndWriteDependantRecords(OutputStream os, Map<RecordTypes.Type,PositionDependentRecord> interestingRecords)
+       public void updateAndWriteDependantRecords(OutputStream os, Map<RecordTypes,PositionDependentRecord> interestingRecords)
        throws IOException {
         // For position dependent records, hold where they were and now are
         // As we go along, update, and hand over, to any Position Dependent
@@ -502,7 +502,7 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
 
             // Grab interesting records as they come past
             // this will only save the very last record of each type
-            RecordTypes.Type saveme = null;
+            RecordTypes saveme = null;
             int recordType = (int)record.getRecordType();
             if (recordType == RecordTypes.PersistPtrIncrementalBlock.typeID) {
                 saveme = RecordTypes.PersistPtrIncrementalBlock;
index b82bed34a686b05a0e5f34a8657ffd1650f8d011..664e935d4adf5d1ad41dc32fb5f27e13bc38df81 100644 (file)
@@ -95,14 +95,14 @@ implements HSLFShapeContainer, TableShape<HSLFShape,HSLFTextParagraph> {
 
         EscherContainerRecord spCont = (EscherContainerRecord) getSpContainer().getChild(0);
         AbstractEscherOptRecord opt = new EscherOptRecord();
-        opt.setRecordId((short)RecordTypes.EscherUserDefined);
+        opt.setRecordId(RecordTypes.EscherUserDefined.typeID);
         opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GROUPSHAPE__TABLEPROPERTIES, 1));
         EscherArrayProperty p = new EscherArrayProperty((short)(0x4000 | EscherProperties.GROUPSHAPE__TABLEROWPROPERTIES), false, null);
         p.setSizeOfElements(0x0004);
         p.setNumberOfElementsInArray(numRows);
         p.setNumberOfElementsInMemory(numRows);
         opt.addEscherProperty(p);
-        spCont.addChildBefore(opt, RecordTypes.EscherClientAnchor);
+        spCont.addChildBefore(opt, RecordTypes.EscherClientAnchor.typeID);
     }
 
     /**
index da6e16454963f8669892e7e2b9d31309d5296a1d..8460a5b9795ca4890f378700e3fd5c683b97aaba 100644 (file)
@@ -157,7 +157,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
      *\r
      * @param paragraphStyle the master style reference\r
      * \r
-     * @since 3.14-Beta1\r
+     * @since POI 3.14-Beta1\r
      */\r
     @Internal\r
     /* package */ void setMasterStyleReference(TextPropCollection paragraphStyle) {\r
index 42350c581a12219f461c52dd3d99aca704abd26a..5e6a705def1c160e5791ba3ace21c65365ab498d 100644 (file)
@@ -76,7 +76,7 @@ public final class HSLFTextRun implements TextRun {
      *
      * @param characterStyle the master style reference
      * 
-     * @since 3.14-Beta1
+     * @since POI 3.14-Beta1
      */
        @Internal
     /* package */ void setMasterStyleReference(TextPropCollection characterStyle) {
index 236ab234b18375e02829d4d48d4f91f99be9c779..88e5d80016946442cd8eaecc4e2a18d1eae23a9e 100644 (file)
@@ -45,6 +45,7 @@ import org.apache.poi.hslf.record.TxInteractiveInfoAtom;
 import org.apache.poi.sl.draw.DrawFactory;
 import org.apache.poi.sl.draw.DrawTextShape;
 import org.apache.poi.sl.usermodel.Insets2D;
+import org.apache.poi.sl.usermodel.Placeholder;
 import org.apache.poi.sl.usermodel.ShapeContainer;
 import org.apache.poi.sl.usermodel.TextShape;
 import org.apache.poi.sl.usermodel.VerticalAlignment;
@@ -603,14 +604,29 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
     }
 
     /**
-     * Return <code>OEPlaceholderAtom</code>, the atom that describes a placeholder.
+     * Return {@link OEPlaceholderAtom}, the atom that describes a placeholder.
      *
-     * @return <code>OEPlaceholderAtom</code> or <code>null</code> if not found
+     * @return {@link OEPlaceholderAtom} or {@code null} if not found
      */
     public OEPlaceholderAtom getPlaceholderAtom(){
         return getClientDataRecord(OEPlaceholderAtom.typeID);
     }
 
+    /**
+     * Return {@link RoundTripHFPlaceholder12}, the atom that describes a header/footer placeholder.
+     * Compare the {@link RoundTripHFPlaceholder12#getPlaceholderId()} with
+     * {@link OEPlaceholderAtom#MasterHeader} or {@link OEPlaceholderAtom#MasterFooter}, to find out
+     * what kind of placeholder this is.
+     *
+     * @return {@link RoundTripHFPlaceholder12} or {@code null} if not found
+     * 
+     * @since POI 3.14-Beta2
+     */
+    public RoundTripHFPlaceholder12 getHFPlaceholderAtom() {
+        // special case for files saved in Office 2007
+        return getClientDataRecord(RoundTripHFPlaceholder12.typeID);
+    }
+    
     /**
      *
      * Assigns a hyperlink to this text shape
@@ -644,7 +660,7 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
         if (oep != null) return true;
 
         //special case for files saved in Office 2007
-        RoundTripHFPlaceholder12 hldr = getClientDataRecord(RoundTripHFPlaceholder12.typeID);
+        RoundTripHFPlaceholder12 hldr = getHFPlaceholderAtom();
         if (hldr != null) return true;
 
         return false;
index a742528e2129b204e000608c7a6a2b628a2e4e00..d5a2b60a091e1dd3123d5de8be1734beea8c7d7d 100644 (file)
 
 package org.apache.poi.hslf;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
-import java.io.FileNotFoundException;
-
-import junit.framework.TestCase;
+import java.io.IOException;
 
 import org.apache.poi.POIDataSamples;
 import org.apache.poi.hslf.usermodel.HSLFSlideShow;
 import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;
 import org.apache.poi.poifs.filesystem.DocumentEntry;
 import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+import org.junit.Before;
+import org.junit.Test;
 
 /**
  * Tests that HSLFSlideShow writes the powerpoint bit of data back out
@@ -36,7 +40,7 @@ import org.apache.poi.poifs.filesystem.POIFSFileSystem;
  *
  * @author Nick Burch (nick at torchbox dot com)
  */
-public final class TestReWrite extends TestCase {
+public final class TestReWrite {
        // HSLFSlideShow primed on the test data
        private HSLFSlideShowImpl hssA;
        private HSLFSlideShowImpl hssB;
@@ -46,7 +50,8 @@ public final class TestReWrite extends TestCase {
        private POIFSFileSystem pfsB;
        private POIFSFileSystem pfsC;
 
-    public void setUp() throws Exception {
+       @Before
+       public void setUp() throws Exception {
 
         POIDataSamples slTests = POIDataSamples.getSlideShowInstance();
         
@@ -60,10 +65,12 @@ public final class TestReWrite extends TestCase {
                hssC = new HSLFSlideShowImpl(pfsC);
     }
 
+       @Test
     public void testWritesOutTheSame() throws Exception {
        assertWritesOutTheSame(hssA, pfsA);
        assertWritesOutTheSame(hssB, pfsB);
     }
+       
     public void assertWritesOutTheSame(HSLFSlideShowImpl hss, POIFSFileSystem pfs) throws Exception {
                // Write out to a byte array
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -85,13 +92,15 @@ public final class TestReWrite extends TestCase {
                byte[] _nData = new byte[nProps.getSize()];
                pfs.createDocumentInputStream("PowerPoint Document").read(_oData);
                npfs.createDocumentInputStream("PowerPoint Document").read(_nData);
-               for(int i=0; i<_oData.length; i++) {
+        for(int i=0; i<_oData.length; i++) {
                        //System.out.println(i + "\t" + Integer.toHexString(i));
                        assertEquals(_oData[i], _nData[i]);
                }
+               npfs.close();
        }
 
-    public void testWithMacroStreams() throws Exception {
+    @Test
+    public void testWithMacroStreams() throws IOException {
        // Check that they're apparently the same
        assertSlideShowWritesOutTheSame(hssC, pfsC);
 
@@ -101,28 +110,25 @@ public final class TestReWrite extends TestCase {
        // Write out normally, will loose the macro stream
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        hssC.write(baos);
-       POIFSFileSystem pfsNew = new POIFSFileSystem(
-                       new ByteArrayInputStream(baos.toByteArray()) );
-
-       try {
-               pfsNew.getRoot().getEntry("Macros");
-               fail();
-       } catch(FileNotFoundException e) {
-               // Good, as expected
-       }
+       ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+       POIFSFileSystem pfsNew = new POIFSFileSystem(bais);
+       assertFalse(pfsNew.getRoot().hasEntry("Macros"));
+       pfsNew.close();
 
        // But if we write out with nodes preserved, will be there
-       baos = new ByteArrayOutputStream();
+       baos.reset();
        hssC.write(baos, true);
-       pfsNew = new POIFSFileSystem(
-                       new ByteArrayInputStream(baos.toByteArray()) );
-       assertNotNull( pfsNew.getRoot().getEntry("Macros") );
+       bais = new ByteArrayInputStream(baos.toByteArray());
+       pfsNew = new POIFSFileSystem(bais);
+       assertTrue( pfsNew.getRoot().hasEntry("Macros") );
+       pfsNew.close();
     }
 
     /**
      * Ensure that simply opening a slideshow (usermodel) view of it
      *  doesn't change things
      */
+    @Test
     public void testSlideShowWritesOutTheSame() throws Exception {
        assertSlideShowWritesOutTheSame(hssA, pfsA);
 
@@ -130,9 +136,11 @@ public final class TestReWrite extends TestCase {
        // We need to identify and fix that first
        //assertSlideShowWritesOutTheSame(hssB, pfsB);
     }
-    public void assertSlideShowWritesOutTheSame(HSLFSlideShowImpl hss, POIFSFileSystem pfs) throws Exception {
+    
+    public void assertSlideShowWritesOutTheSame(HSLFSlideShowImpl hss, POIFSFileSystem pfs) throws IOException {
        // Create a slideshow covering it
-       HSLFSlideShow ss = new HSLFSlideShow(hss);
+       @SuppressWarnings("resource")
+        HSLFSlideShow ss = new HSLFSlideShow(hss);
        ss.getSlides();
        ss.getNotes();
 
@@ -161,17 +169,23 @@ public final class TestReWrite extends TestCase {
                                System.out.println(i + "\t" + Integer.toHexString(i));
                        assertEquals(_oData[i], _nData[i]);
                }
+               npfs.close();
        }
     
-    public void test48593() throws Exception {
-               HSLFSlideShow slideShow = new HSLFSlideShow();
-               slideShow.createSlide();
-               slideShow = HSLFTestDataSamples.writeOutAndReadBack(slideShow);
-               slideShow.createSlide();
-               slideShow = HSLFTestDataSamples.writeOutAndReadBack(slideShow);
-               slideShow.createSlide();
-               slideShow = HSLFTestDataSamples.writeOutAndReadBack(slideShow);
-               slideShow.createSlide();
-               slideShow = HSLFTestDataSamples.writeOutAndReadBack(slideShow);
+    @Test
+    public void test48593() throws IOException {
+               HSLFSlideShow ppt1 = new HSLFSlideShow();
+               ppt1.createSlide();
+               HSLFSlideShow ppt2 = HSLFTestDataSamples.writeOutAndReadBack(ppt1);
+               ppt2.createSlide();
+               HSLFSlideShow ppt3 = HSLFTestDataSamples.writeOutAndReadBack(ppt2);
+               ppt3.createSlide();
+               HSLFSlideShow ppt4 = HSLFTestDataSamples.writeOutAndReadBack(ppt3);
+               ppt4.createSlide();
+               HSLFTestDataSamples.writeOutAndReadBack(ppt4).close();
+               ppt4.close();
+               ppt3.close();
+               ppt2.close();
+               ppt1.close();
     }
 }
index 45522dfd81aa4375d3a256b1ecea5615c5057697..814259ca1570ea286fe36bc1cdef35693e3efcb1 100644 (file)
 package org.apache.poi.hslf.record;
 
 
-import junit.framework.TestCase;
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
 
 /**
  * Tests that RecordTypes returns the right records and classes when asked
- *
- * @author Nick Burch (nick at torchbox dot com)
  */
-public final class TestRecordTypes extends TestCase {
+public final class TestRecordTypes {
+    @Test
        public void testPPTNameLookups() {
-               assertEquals("MainMaster", RecordTypes.recordName(1016));
-               assertEquals("TextBytesAtom", RecordTypes.recordName(4008));
-               assertEquals("VBAInfo", RecordTypes.recordName(1023));
+               assertEquals("MainMaster", RecordTypes.MainMaster.name());
+               assertEquals("TextBytesAtom", RecordTypes.TextBytesAtom.name());
+               assertEquals("VBAInfo", RecordTypes.VBAInfo.name());
        }
 
+    @Test
        public void testEscherNameLookups() {
-               assertEquals("EscherDggContainer", RecordTypes.recordName(0xf000));
-               assertEquals("EscherClientTextbox", RecordTypes.recordName(0xf00d));
-               assertEquals("EscherSelection", RecordTypes.recordName(0xf119));
+               assertEquals("EscherDggContainer", RecordTypes.EscherDggContainer.name());
+               assertEquals("EscherClientTextbox", RecordTypes.EscherClientTextbox.name());
+               assertEquals("EscherSelection", RecordTypes.EscherSelection.name());
        }
 
+    @Test
        public void testPPTClassLookups() {
-               assertEquals(Slide.class, RecordTypes.recordHandlingClass(1006));
-               assertEquals(TextCharsAtom.class, RecordTypes.recordHandlingClass(4000));
-               assertEquals(TextBytesAtom.class, RecordTypes.recordHandlingClass(4008));
-               assertEquals(SlideListWithText.class, RecordTypes.recordHandlingClass(4080));
+               assertEquals(Slide.class, RecordTypes.Slide.handlingClass);
+               assertEquals(TextCharsAtom.class, RecordTypes.TextCharsAtom.handlingClass);
+               assertEquals(TextBytesAtom.class, RecordTypes.TextBytesAtom.handlingClass);
+               assertEquals(SlideListWithText.class, RecordTypes.SlideListWithText.handlingClass);
 
                // If this record is ever implemented, change to one that isn't!
                // This is checking the "unhandled default" stuff works
-               assertEquals(UnknownRecordPlaceholder.class, RecordTypes.recordHandlingClass(2019));
+               assertEquals(UnknownRecordPlaceholder.class, RecordTypes.forTypeID(-10).handlingClass);
        }
 
-       public void testEscherClassLookups() {
+    @Test
+    public void testEscherClassLookups() {
                // Should all come back with null, as DDF handles them
-               assertEquals(null, RecordTypes.recordHandlingClass(0xf000));
-               assertEquals(null, RecordTypes.recordHandlingClass(0xf001));
+               assertEquals(null, RecordTypes.EscherDggContainer.handlingClass);
+               assertEquals(null, RecordTypes.EscherBStoreContainer.handlingClass);
        }
 }
index 68684bf8d62c0d07c1920c1fe3af17f9fc2eefeb..b57d9e4f2f795fcb2fd1013e1027c53e9a208462 100644 (file)
@@ -20,6 +20,7 @@ package org.apache.poi.hslf.usermodel;
 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;
@@ -42,7 +43,9 @@ import org.apache.poi.hslf.exceptions.OldPowerPointFormatException;
 import org.apache.poi.hslf.extractor.PowerPointExtractor;
 import org.apache.poi.hslf.model.HeadersFooters;
 import org.apache.poi.hslf.record.Document;
+import org.apache.poi.hslf.record.OEPlaceholderAtom;
 import org.apache.poi.hslf.record.Record;
+import org.apache.poi.hslf.record.RoundTripHFPlaceholder12;
 import org.apache.poi.hslf.record.SlideListWithText;
 import org.apache.poi.hslf.record.SlideListWithText.SlideAtomsSet;
 import org.apache.poi.hslf.record.TextHeaderAtom;
@@ -50,6 +53,7 @@ import org.apache.poi.sl.draw.DrawPaint;
 import org.apache.poi.sl.usermodel.PaintStyle;
 import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
 import org.apache.poi.sl.usermodel.PictureData.PictureType;
+import org.apache.poi.sl.usermodel.Placeholder;
 import org.apache.poi.sl.usermodel.Slide;
 import org.apache.poi.sl.usermodel.SlideShow;
 import org.apache.poi.sl.usermodel.SlideShowFactory;
@@ -777,6 +781,31 @@ public final class TestBugs {
         ex.close();
     }
 
+    @Test
+    public void bug58159() throws IOException {
+        File sample = HSLFTestDataSamples.getSampleFile("bug58159_headers-and-footers.ppt");
+        HSLFSlideShow ppt = (HSLFSlideShow)SlideShowFactory.create(sample);
+        HeadersFooters hf = ppt.getSlideHeadersFooters();
+        assertNull(hf.getHeaderText());
+        assertEquals("Slide footer", hf.getFooterText());
+        hf = ppt.getNotesHeadersFooters();
+        assertEquals("Notes header", hf.getHeaderText());
+        assertEquals("Notes footer", hf.getFooterText());
+        HSLFSlide sl = ppt.getSlides().get(0);
+        hf = sl.getHeadersFooters();
+        assertNull(hf.getHeaderText());
+        assertEquals("Slide footer", hf.getFooterText());
+        for (HSLFShape shape : sl.getShapes()) {
+            if (shape instanceof HSLFTextShape) {
+                HSLFTextShape ts = (HSLFTextShape)shape;
+                Placeholder ph = ts.getPlaceholder();
+                if (Placeholder.FOOTER == ph) {
+                    assertEquals("Slide footer", ts.getText());
+                }
+            }
+        }
+        ppt.close();
+    }
     
     private static HSLFSlideShow open(String fileName) throws IOException {
         File sample = HSLFTestDataSamples.getSampleFile(fileName);
index e54da298ffc3fa9545b87d87e0c662d42651bffa..b21f216577ae69119d178471b42dc06ea513649e 100644 (file)
@@ -42,12 +42,11 @@ public final class TestNumberedList {
     @Test
     public void testNumberedList() throws Exception {
                HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("numbers.ppt"));
-               assertTrue("No Exceptions while reading file", true);
-
                final List<HSLFSlide> slides = ppt.getSlides();
                assertEquals(2, slides.size());
                checkSlide0(slides.get(0));
                checkSlide1(slides.get(1));
+               ppt.close();
        }
 
     private void checkSlide0(final HSLFSlide s) {