You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ki...@apache.org on 2019/12/14 23:44:26 UTC

svn commit: r1871563 - in /poi/trunk/src: java/org/apache/poi/ddf/ scratchpad/src/org/apache/poi/hslf/record/ testcases/org/apache/poi/ddf/

Author: kiwiwings
Date: Sat Dec 14 23:44:26 2019
New Revision: 1871563

URL: http://svn.apache.org/viewvc?rev=1871563&view=rev
Log:
#64004 - Replace clone() with copy constructor

Modified:
    poi/trunk/src/java/org/apache/poi/ddf/AbstractEscherOptRecord.java
    poi/trunk/src/java/org/apache/poi/ddf/EscherBSERecord.java
    poi/trunk/src/java/org/apache/poi/ddf/EscherBitmapBlip.java
    poi/trunk/src/java/org/apache/poi/ddf/EscherBlipRecord.java
    poi/trunk/src/java/org/apache/poi/ddf/EscherChildAnchorRecord.java
    poi/trunk/src/java/org/apache/poi/ddf/EscherClientAnchorRecord.java
    poi/trunk/src/java/org/apache/poi/ddf/EscherClientDataRecord.java
    poi/trunk/src/java/org/apache/poi/ddf/EscherContainerRecord.java
    poi/trunk/src/java/org/apache/poi/ddf/EscherDgRecord.java
    poi/trunk/src/java/org/apache/poi/ddf/EscherDggRecord.java
    poi/trunk/src/java/org/apache/poi/ddf/EscherMetafileBlip.java
    poi/trunk/src/java/org/apache/poi/ddf/EscherOptRecord.java
    poi/trunk/src/java/org/apache/poi/ddf/EscherPictBlip.java
    poi/trunk/src/java/org/apache/poi/ddf/EscherRecord.java
    poi/trunk/src/java/org/apache/poi/ddf/EscherSpRecord.java
    poi/trunk/src/java/org/apache/poi/ddf/EscherSpgrRecord.java
    poi/trunk/src/java/org/apache/poi/ddf/EscherSplitMenuColorsRecord.java
    poi/trunk/src/java/org/apache/poi/ddf/EscherTertiaryOptRecord.java
    poi/trunk/src/java/org/apache/poi/ddf/EscherTextboxRecord.java
    poi/trunk/src/java/org/apache/poi/ddf/UnknownEscherRecord.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/EscherPlaceholder.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/HSLFEscherClientDataRecord.java
    poi/trunk/src/testcases/org/apache/poi/ddf/TestEscherContainerRecord.java
    poi/trunk/src/testcases/org/apache/poi/ddf/TestEscherDump.java

Modified: poi/trunk/src/java/org/apache/poi/ddf/AbstractEscherOptRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ddf/AbstractEscherOptRecord.java?rev=1871563&r1=1871562&r2=1871563&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ddf/AbstractEscherOptRecord.java (original)
+++ poi/trunk/src/java/org/apache/poi/ddf/AbstractEscherOptRecord.java Sat Dec 14 23:44:26 2019
@@ -30,13 +30,20 @@ import org.apache.poi.util.Removal;
  * Common abstract class for {@link EscherOptRecord} and
  * {@link EscherTertiaryOptRecord}
  */
-public abstract class AbstractEscherOptRecord extends EscherRecord
-{
+public abstract class AbstractEscherOptRecord extends EscherRecord {
     private final List<EscherProperty> properties = new ArrayList<>();
 
+    protected AbstractEscherOptRecord() {}
+
+    protected AbstractEscherOptRecord(AbstractEscherOptRecord other) {
+        super(other);
+        properties.addAll(other.properties);
+    }
+
+
     /**
      * Add a property to this record.
-     * 
+     *
      * @param prop the escher property to add
      */
     public void addEscherProperty( EscherProperty prop )
@@ -60,7 +67,7 @@ public abstract class AbstractEscherOptR
 
     /**
      * The list of properties stored by this record.
-     * 
+     *
      * @return the list of properties
      */
     public List<EscherProperty> getEscherProperties()
@@ -70,7 +77,7 @@ public abstract class AbstractEscherOptR
 
     /**
      * The list of properties stored by this record.
-     * 
+     *
      * @param index the ordinal index of the property
      * @return the escher property
      */
@@ -79,7 +86,7 @@ public abstract class AbstractEscherOptR
         return properties.get( index );
     }
 
-    
+
     private int getPropertiesSize()
     {
         int totalSize = 0;
@@ -164,4 +171,7 @@ public abstract class AbstractEscherOptR
             "properties", this::getEscherProperties
         );
     }
+
+    @Override
+    public abstract AbstractEscherOptRecord copy();
 }

Modified: poi/trunk/src/java/org/apache/poi/ddf/EscherBSERecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ddf/EscherBSERecord.java?rev=1871563&r1=1871562&r2=1871563&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ddf/EscherBSERecord.java (original)
+++ poi/trunk/src/java/org/apache/poi/ddf/EscherBSERecord.java Sat Dec 14 23:44:26 2019
@@ -58,7 +58,25 @@ public final class EscherBSERecord exten
     public EscherBSERecord() {
         setRecordId(RECORD_ID);
     }
-    
+
+    public EscherBSERecord(EscherBSERecord other) {
+        super(other);
+
+        field_1_blipTypeWin32 = other.field_1_blipTypeWin32;
+        field_2_blipTypeMacOS = other.field_2_blipTypeMacOS;
+        System.arraycopy(other.field_3_uid, 0, field_3_uid, 0, field_3_uid.length);
+        field_4_tag = other.field_4_tag;
+        field_5_size = other.field_5_size;
+        field_6_ref = other.field_6_ref;
+        field_7_offset = other.field_7_offset;
+        field_8_usage = other.field_8_usage;
+        field_9_name = other.field_9_name;
+        field_10_unused2 = other.field_10_unused2;
+        field_11_unused3 = other.field_11_unused3;
+        field_12_blipRecord = other.field_12_blipRecord.copy();
+        _remainingData = other._remainingData.clone();
+    }
+
     @Override
     public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) {
         int bytesRemaining = readHeader( data, offset );
@@ -149,7 +167,7 @@ public final class EscherBSERecord exten
     /**
      * The expected blip type under windows (failure to match this blip type will result in
      * Excel converting to this format).
-     * 
+     *
      * @return win32 blip type
      */
     public byte getBlipTypeWin32() {
@@ -162,7 +180,7 @@ public final class EscherBSERecord exten
 
     /**
      * Set the expected win32 blip type
-     * 
+     *
      * @param blipTypeWin32 win32 blip type
      */
     public void setBlipTypeWin32(byte blipTypeWin32) {
@@ -172,7 +190,7 @@ public final class EscherBSERecord exten
     /**
      * The expected blip type under MacOS (failure to match this blip type will result in
      * Excel converting to this format).
-     * 
+     *
      * @return MacOS blip type
      */
     public byte getBlipTypeMacOS() {
@@ -185,7 +203,7 @@ public final class EscherBSERecord exten
 
     /**
      * Set the expected MacOS blip type
-     * 
+     *
      * @param blipTypeMacOS MacOS blip type
      */
     public void setBlipTypeMacOS(byte blipTypeMacOS) {
@@ -194,7 +212,7 @@ public final class EscherBSERecord exten
 
     /**
      * 16 byte MD4 checksum.
-     * 
+     *
      * @return 16 byte MD4 checksum
      */
     public byte[] getUid() {
@@ -203,7 +221,7 @@ public final class EscherBSERecord exten
 
     /**
      * 16 byte MD4 checksum.
-     * 
+     *
      * @param uid 16 byte MD4 checksum
      */
     public void setUid(byte[] uid) {
@@ -215,7 +233,7 @@ public final class EscherBSERecord exten
 
     /**
      * unused
-     * 
+     *
      * @return an unknown tag
      */
     public short getTag() {
@@ -224,7 +242,7 @@ public final class EscherBSERecord exten
 
     /**
      * unused
-     * 
+     *
      * @param tag unknown tag
      */
     public void setTag(short tag) {
@@ -233,7 +251,7 @@ public final class EscherBSERecord exten
 
     /**
      * Blip size in stream.
-     * 
+     *
      * @return the blip size
      */
     public int getSize() {
@@ -242,7 +260,7 @@ public final class EscherBSERecord exten
 
     /**
      * Blip size in stream.
-     * 
+     *
      * @param size blip size
      */
     public void setSize(int size) {
@@ -251,7 +269,7 @@ public final class EscherBSERecord exten
 
     /**
      * The reference count of this blip.
-     * 
+     *
      * @return the reference count
      */
     public int getRef() {
@@ -260,7 +278,7 @@ public final class EscherBSERecord exten
 
     /**
      * The reference count of this blip.
-     * 
+     *
      * @param ref the reference count
      */
     public void setRef(int ref) {
@@ -269,7 +287,7 @@ public final class EscherBSERecord exten
 
     /**
      * File offset in the delay stream.
-     * 
+     *
      * @return the file offset
      */
     public int getOffset() {
@@ -278,7 +296,7 @@ public final class EscherBSERecord exten
 
     /**
      * File offset in the delay stream.
-     * 
+     *
      * @param offset the file offset
      */
     public void setOffset(int offset) {
@@ -287,7 +305,7 @@ public final class EscherBSERecord exten
 
     /**
      * Defines the way this blip is used.
-     * 
+     *
      * @return the blip usage
      */
     public byte getUsage() {
@@ -296,7 +314,7 @@ public final class EscherBSERecord exten
 
     /**
      * Defines the way this blip is used.
-     * 
+     *
      * @param usage the blip usae
      */
     public void setUsage(byte usage) {
@@ -305,7 +323,7 @@ public final class EscherBSERecord exten
 
     /**
      * The length in characters of the blip name.
-     * 
+     *
      * @return the blip name length
      */
     public byte getName() {
@@ -314,7 +332,7 @@ public final class EscherBSERecord exten
 
     /**
      * The length in characters of the blip name.
-     * 
+     *
      * @param name the blip name length
      */
     public void setName(byte name) {
@@ -347,7 +365,7 @@ public final class EscherBSERecord exten
 
     /**
      * Any remaining data in this record.
-     * 
+     *
      * @return the remaining bytes
      */
     public byte[] getRemainingData() {
@@ -356,7 +374,7 @@ public final class EscherBSERecord exten
 
     /**
      * Any remaining data in this record.
-     * 
+     *
      * @param remainingData the remaining bytes
      */
     public void setRemainingData(byte[] remainingData) {
@@ -388,4 +406,9 @@ public final class EscherBSERecord exten
     public Enum getGenericRecordType() {
         return EscherRecordTypes.BSE;
     }
+
+    @Override
+    public EscherBSERecord copy() {
+        return new EscherBSERecord(this);
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/ddf/EscherBitmapBlip.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ddf/EscherBitmapBlip.java?rev=1871563&r1=1871562&r2=1871563&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ddf/EscherBitmapBlip.java (original)
+++ poi/trunk/src/java/org/apache/poi/ddf/EscherBitmapBlip.java Sat Dec 14 23:44:26 2019
@@ -33,6 +33,14 @@ public class EscherBitmapBlip extends Es
     private final byte[] field_1_UID = new byte[16];
     private byte field_2_marker = (byte) 0xFF;
 
+    public EscherBitmapBlip() {}
+
+    public EscherBitmapBlip(EscherBitmapBlip other) {
+        super(other);
+        System.arraycopy(other.field_1_UID, 0, field_1_UID, 0, field_1_UID.length);
+        field_2_marker = other.field_2_marker;
+    }
+
     @Override
     public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) {
         int bytesAfterHeader = readHeader( data, offset );
@@ -121,4 +129,8 @@ public class EscherBitmapBlip extends Es
         );
     }
 
+    @Override
+    public EscherBitmapBlip copy() {
+        return new EscherBitmapBlip(this);
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/ddf/EscherBlipRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ddf/EscherBlipRecord.java?rev=1871563&r1=1871562&r2=1871563&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ddf/EscherBlipRecord.java (original)
+++ poi/trunk/src/java/org/apache/poi/ddf/EscherBlipRecord.java Sat Dec 14 23:44:26 2019
@@ -39,6 +39,11 @@ public class EscherBlipRecord extends Es
     public EscherBlipRecord() {
     }
 
+    public EscherBlipRecord(EscherBlipRecord other) {
+        super(other);
+        field_pictureData = (other.field_pictureData == null) ? null : other.field_pictureData.clone();
+    }
+
     @Override
     public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) {
         int bytesAfterHeader = readHeader( data, offset );
@@ -120,4 +125,10 @@ public class EscherBlipRecord extends Es
         EscherRecordTypes t = EscherRecordTypes.forTypeID(getRecordId());
         return (t != EscherRecordTypes.UNKNOWN) ? t : EscherRecordTypes.BLIP_START;
     }
+
+
+    @Override
+    public EscherBlipRecord copy() {
+        return new EscherBlipRecord(this);
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/ddf/EscherChildAnchorRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ddf/EscherChildAnchorRecord.java?rev=1871563&r1=1871562&r2=1871563&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ddf/EscherChildAnchorRecord.java (original)
+++ poi/trunk/src/java/org/apache/poi/ddf/EscherChildAnchorRecord.java Sat Dec 14 23:44:26 2019
@@ -38,6 +38,16 @@ public class EscherChildAnchorRecord ext
     private int field_3_dx2;
     private int field_4_dy2;
 
+    public EscherChildAnchorRecord() {}
+
+    public EscherChildAnchorRecord(EscherChildAnchorRecord other) {
+        super(other);
+        field_1_dx1 = other.field_1_dx1;
+        field_2_dy1 = other.field_2_dy1;
+        field_3_dx2 = other.field_3_dx2;
+        field_4_dy2 = other.field_4_dy2;
+    }
+
     @Override
     public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) {
         int bytesRemaining = readHeader( data, offset );
@@ -59,7 +69,7 @@ public class EscherChildAnchorRecord ext
         default:
             throw new RuntimeException("Invalid EscherChildAnchorRecord - neither 8 nor 16 bytes.");
         }
-            
+
         return 8 + size;
     }
 
@@ -98,7 +108,7 @@ public class EscherChildAnchorRecord ext
 
     /**
      * Retrieves offset within the parent coordinate space for the top left point.
-     * 
+     *
      * @return the x offset of the top left point
      */
     public int getDx1()
@@ -108,7 +118,7 @@ public class EscherChildAnchorRecord ext
 
     /**
      * Sets offset within the parent coordinate space for the top left point.
-     * 
+     *
      * @param field_1_dx1 the x offset of the top left point
      */
     public void setDx1( int field_1_dx1 )
@@ -118,7 +128,7 @@ public class EscherChildAnchorRecord ext
 
     /**
      * Gets offset within the parent coordinate space for the top left point.
-     * 
+     *
      * @return the y offset of the top left point
      */
     public int getDy1()
@@ -128,8 +138,8 @@ public class EscherChildAnchorRecord ext
 
     /**
      * Sets offset within the parent coordinate space for the top left point.
-     * 
-     * @param field_2_dy1 the y offset of the top left point 
+     *
+     * @param field_2_dy1 the y offset of the top left point
      */
     public void setDy1( int field_2_dy1 )
     {
@@ -138,7 +148,7 @@ public class EscherChildAnchorRecord ext
 
     /**
      * Retrieves offset within the parent coordinate space for the bottom right point.
-     * 
+     *
      * @return the x offset of the bottom right point
      */
     public int getDx2()
@@ -148,7 +158,7 @@ public class EscherChildAnchorRecord ext
 
     /**
      * Sets offset within the parent coordinate space for the bottom right point.
-     * 
+     *
      * @param field_3_dx2 the x offset of the bottom right point
      */
     public void setDx2( int field_3_dx2 )
@@ -158,7 +168,7 @@ public class EscherChildAnchorRecord ext
 
     /**
      * Gets the offset within the parent coordinate space for the bottom right point.
-     * 
+     *
      * @return the y offset of the bottom right point
      */
     public int getDy2()
@@ -168,7 +178,7 @@ public class EscherChildAnchorRecord ext
 
     /**
      * Sets the offset within the parent coordinate space for the bottom right point.
-     * 
+     *
      * @param field_4_dy2 the y offset of the bottom right point
      */
     public void setDy2( int field_4_dy2 )
@@ -191,4 +201,9 @@ public class EscherChildAnchorRecord ext
     public Enum getGenericRecordType() {
         return EscherRecordTypes.CHILD_ANCHOR;
     }
+
+    @Override
+    public EscherChildAnchorRecord copy() {
+        return new EscherChildAnchorRecord(this);
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/ddf/EscherClientAnchorRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ddf/EscherClientAnchorRecord.java?rev=1871563&r1=1871562&r2=1871563&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ddf/EscherClientAnchorRecord.java (original)
+++ poi/trunk/src/java/org/apache/poi/ddf/EscherClientAnchorRecord.java Sat Dec 14 23:44:26 2019
@@ -59,6 +59,23 @@ public class EscherClientAnchorRecord ex
     private byte[] remainingData = new byte[0];
     private boolean shortRecord;
 
+    public EscherClientAnchorRecord() {}
+
+    public EscherClientAnchorRecord(EscherClientAnchorRecord other) {
+        super(other);
+        field_1_flag = other.field_1_flag;
+        field_2_col1 = other.field_2_col1;
+        field_3_dx1 = other.field_3_dx1;
+        field_4_row1 = other.field_4_row1;
+        field_5_dy1 = other.field_5_dy1;
+        field_6_col2 = other.field_6_col2;
+        field_7_dx2 = other.field_7_dx2;
+        field_8_row2 = other.field_8_row2;
+        field_9_dy2 = other.field_9_dy2;
+        remainingData = (other.remainingData == null) ? null : other.remainingData.clone();
+        shortRecord = other.shortRecord;
+    }
+
     @Override
     public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) {
         int bytesRemaining = readHeader( data, offset );
@@ -368,4 +385,9 @@ public class EscherClientAnchorRecord ex
     public Enum getGenericRecordType() {
         return EscherRecordTypes.CLIENT_ANCHOR;
     }
+
+    @Override
+    public EscherClientAnchorRecord copy() {
+        return new EscherClientAnchorRecord(this);
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/ddf/EscherClientDataRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ddf/EscherClientDataRecord.java?rev=1871563&r1=1871562&r2=1871563&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ddf/EscherClientDataRecord.java (original)
+++ poi/trunk/src/java/org/apache/poi/ddf/EscherClientDataRecord.java Sat Dec 14 23:44:26 2019
@@ -29,9 +29,7 @@ import org.apache.poi.util.LittleEndian;
  * The EscherClientDataRecord is used to store client specific data about the position of a
  * shape within a container.
  */
-public class EscherClientDataRecord
-    extends EscherRecord
-{
+public class EscherClientDataRecord extends EscherRecord {
     //arbitrarily selected; may need to increase
     private static final int MAX_RECORD_LENGTH = 100_000;
 
@@ -39,6 +37,13 @@ public class EscherClientDataRecord
 
     private byte[] remainingData;
 
+    public EscherClientDataRecord() {}
+
+    public EscherClientDataRecord(EscherClientDataRecord other) {
+        super(other);
+        remainingData = (other.remainingData == null) ? null : other.remainingData.clone();
+    }
+
     @Override
     public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) {
         int bytesRemaining = readHeader( data, offset );
@@ -83,7 +88,7 @@ public class EscherClientDataRecord
 
     /**
      * Any data recording this record.
-     * 
+     *
      * @return the remaining bytes
      */
     public byte[] getRemainingData()
@@ -93,7 +98,7 @@ public class EscherClientDataRecord
 
     /**
      * Any data recording this record.
-     * 
+     *
      * @param remainingData the remaining bytes
      */
     public void setRemainingData( byte[] remainingData ) {
@@ -114,4 +119,9 @@ public class EscherClientDataRecord
     public Enum getGenericRecordType() {
         return EscherRecordTypes.CLIENT_DATA;
     }
+
+    @Override
+    public EscherClientDataRecord copy() {
+        return new EscherClientDataRecord(this);
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/ddf/EscherContainerRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ddf/EscherContainerRecord.java?rev=1871563&r1=1871562&r2=1871563&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ddf/EscherContainerRecord.java (original)
+++ poi/trunk/src/java/org/apache/poi/ddf/EscherContainerRecord.java Sat Dec 14 23:44:26 2019
@@ -73,6 +73,14 @@ public final class EscherContainerRecord
 
     private final List<EscherRecord> _childRecords = new ArrayList<>();
 
+    public EscherContainerRecord() {}
+
+    public EscherContainerRecord(EscherContainerRecord other) {
+        super(other);
+        _remainingLength = other._remainingLength;
+        other._childRecords.stream().map(EscherRecord::copy).forEach(_childRecords::add);
+    }
+
     @Override
     public int fillFields(byte[] data, int pOffset, EscherRecordFactory recordFactory) {
         int bytesRemaining = readHeader(data, pOffset);
@@ -284,4 +292,9 @@ public final class EscherContainerRecord
     public Enum getGenericRecordType() {
         return EscherRecordTypes.forTypeID(getRecordId());
     }
+
+    @Override
+    public EscherContainerRecord copy() {
+        return new EscherContainerRecord(this);
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/ddf/EscherDgRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ddf/EscherDgRecord.java?rev=1871563&r1=1871562&r2=1871563&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ddf/EscherDgRecord.java (original)
+++ poi/trunk/src/java/org/apache/poi/ddf/EscherDgRecord.java Sat Dec 14 23:44:26 2019
@@ -34,6 +34,15 @@ public class EscherDgRecord extends Esch
     private int field_1_numShapes;
     private int field_2_lastMSOSPID;
 
+    public EscherDgRecord() {}
+
+    public EscherDgRecord(EscherDgRecord other) {
+        super(other);
+        field_1_numShapes = other.field_1_numShapes;
+        field_2_lastMSOSPID = other.field_2_lastMSOSPID;
+    }
+
+
     @Override
     public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) {
         /*int bytesRemaining =*/ readHeader( data, offset );
@@ -87,7 +96,7 @@ public class EscherDgRecord extends Esch
 
     /**
      * The number of shapes in this drawing group.
-     * 
+     *
      * @return the number of shapes
      */
     public int getNumShapes()
@@ -97,7 +106,7 @@ public class EscherDgRecord extends Esch
 
     /**
      * The number of shapes in this drawing group.
-     * 
+     *
      * @param field_1_numShapes the number of shapes
      */
     public void setNumShapes( int field_1_numShapes )
@@ -107,7 +116,7 @@ public class EscherDgRecord extends Esch
 
     /**
      * The last shape id used in this drawing group.
-     * 
+     *
      * @return the last shape id
      */
     public int getLastMSOSPID()
@@ -117,7 +126,7 @@ public class EscherDgRecord extends Esch
 
     /**
      * The last shape id used in this drawing group.
-     * 
+     *
      * @param field_2_lastMSOSPID the last shape id
      */
     public void setLastMSOSPID( int field_2_lastMSOSPID )
@@ -158,4 +167,9 @@ public class EscherDgRecord extends Esch
     public Enum getGenericRecordType() {
         return EscherRecordTypes.DG;
     }
+
+    @Override
+    public EscherDgRecord copy() {
+        return new EscherDgRecord(this);
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/ddf/EscherDggRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ddf/EscherDggRecord.java?rev=1871563&r1=1871562&r2=1871563&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ddf/EscherDggRecord.java (original)
+++ poi/trunk/src/java/org/apache/poi/ddf/EscherDggRecord.java Sat Dec 14 23:44:26 2019
@@ -20,7 +20,6 @@ package org.apache.poi.ddf;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.BitSet;
-import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
 import java.util.function.Supplier;
@@ -48,6 +47,11 @@ public final class EscherDggRecord exten
         private int field_1_drawingGroupId;
         private int field_2_numShapeIdsUsed;
 
+        public FileIdCluster(FileIdCluster other) {
+            field_1_drawingGroupId = other.field_1_drawingGroupId;
+            field_2_numShapeIdsUsed = other.field_2_numShapeIdsUsed;
+        }
+
         public FileIdCluster( int drawingGroupId, int numShapeIdsUsed ) {
             this.field_1_drawingGroupId = drawingGroupId;
             this.field_2_numShapeIdsUsed = numShapeIdsUsed;
@@ -65,6 +69,12 @@ public final class EscherDggRecord exten
             field_2_numShapeIdsUsed++;
         }
 
+        private static int compareFileIdCluster(FileIdCluster f1, FileIdCluster f2) {
+            int dgDif = f1.getDrawingGroupId() - f2.getDrawingGroupId();
+            int cntDif = f2.getNumShapeIdsUsed() - f1.getNumShapeIdsUsed();
+            return (dgDif != 0) ? dgDif : cntDif;
+        }
+
         @Override
         public Map<String, Supplier<?>> getGenericProperties() {
             return GenericRecordUtil.getGenericProperties(
@@ -74,6 +84,17 @@ public final class EscherDggRecord exten
         }
     }
 
+    public EscherDggRecord() {}
+
+    public EscherDggRecord(EscherDggRecord other) {
+        super(other);
+        field_1_shapeIdMax = other.field_1_shapeIdMax;
+        field_3_numShapesSaved = other.field_3_numShapesSaved;
+        field_4_drawingsSaved = other.field_4_drawingsSaved;
+        other.field_5_fileIdClusters.stream().map(FileIdCluster::new).forEach(field_5_fileIdClusters::add);
+        maxDgId = other.maxDgId;
+    }
+
     @Override
     public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) {
         int bytesRemaining = readHeader( data, offset );
@@ -81,14 +102,14 @@ public final class EscherDggRecord exten
         int size           = 0;
         field_1_shapeIdMax     =  LittleEndian.getInt( data, pos + size );size+=4;
         // field_2_numIdClusters = LittleEndian.getInt( data, pos + size );
-        size+=4; 
+        size+=4;
         field_3_numShapesSaved =  LittleEndian.getInt( data, pos + size );size+=4;
         field_4_drawingsSaved  =  LittleEndian.getInt( data, pos + size );size+=4;
-        
+
         field_5_fileIdClusters.clear();
         // Can't rely on field_2_numIdClusters
         int numIdClusters = (bytesRemaining-size) / 8;
-        
+
         for (int i = 0; i < numIdClusters; i++) {
             int drawingGroupId = LittleEndian.getInt( data, pos + size );
             int numShapeIdsUsed = LittleEndian.getInt( data, pos + size + 4 );
@@ -118,7 +139,7 @@ public final class EscherDggRecord exten
         LittleEndian.putInt( data, pos, getNumIdClusters() );          pos += 4;
         LittleEndian.putInt( data, pos, field_3_numShapesSaved );      pos += 4;
         LittleEndian.putInt( data, pos, field_4_drawingsSaved );       pos += 4;
-        
+
         for (FileIdCluster fic : field_5_fileIdClusters) {
             LittleEndian.putInt( data, pos, fic.getDrawingGroupId() );   pos += 4;
             LittleEndian.putInt( data, pos, fic.getNumShapeIdsUsed() );  pos += 4;
@@ -154,7 +175,7 @@ public final class EscherDggRecord exten
 
     /**
      * The maximum is actually the next available shape id.
-     * 
+     *
      * @param shapeIdMax the next available shape id
      */
     public void setShapeIdMax(int shapeIdMax) {
@@ -163,7 +184,7 @@ public final class EscherDggRecord exten
 
     /**
      * Number of id clusters + 1
-     * 
+     *
      * @return the number of id clusters + 1
      */
     public int getNumIdClusters() {
@@ -181,7 +202,7 @@ public final class EscherDggRecord exten
 
     /**
      * Sets the number of shapes saved
-     * 
+     *
      * @param numShapesSaved the number of shapes saved
      */
     public void setNumShapesSaved(int numShapesSaved) {
@@ -208,7 +229,7 @@ public final class EscherDggRecord exten
 
     /**
      * Gets the maximum drawing group ID
-     * 
+     *
      * @return The maximum drawing group ID
      */
     public int getMaxDrawingGroupId() {
@@ -234,13 +255,13 @@ public final class EscherDggRecord exten
         }
     }
 
-    
+
     /**
      * Add a new cluster
      *
      * @param dgId  id of the drawing group (stored in the record options)
      * @param numShapedUsed initial value of the numShapedUsed field
-     * 
+     *
      * @return the new {@link FileIdCluster}
      */
     public FileIdCluster addCluster(int dgId, int numShapedUsed) {
@@ -254,35 +275,29 @@ public final class EscherDggRecord exten
      * @param numShapedUsed initial value of the numShapedUsed field
      * @param sort if true then sort clusters by drawing group id.(
      *  In Excel the clusters are sorted but in PPT they are not)
-     * 
+     *
      * @return the new {@link FileIdCluster}
      */
     public FileIdCluster addCluster( int dgId, int numShapedUsed, boolean sort ) {
         FileIdCluster ficNew = new FileIdCluster(dgId, numShapedUsed);
         field_5_fileIdClusters.add(ficNew);
         maxDgId = Math.min(maxDgId, dgId);
-        
+
         if (sort) {
             sortCluster();
         }
-        
+
         return ficNew;
     }
 
     private void sortCluster() {
-        field_5_fileIdClusters.sort(new Comparator<FileIdCluster>() {
-            @Override
-            public int compare(FileIdCluster f1, FileIdCluster f2) {
-                int dgDif = f1.getDrawingGroupId() - f2.getDrawingGroupId();
-                int cntDif = f2.getNumShapeIdsUsed() - f1.getNumShapeIdsUsed();
-                return (dgDif != 0) ? dgDif : cntDif;
-            }
-        });
+        field_5_fileIdClusters.sort(FileIdCluster::compareFileIdCluster);
     }
-    
+
+
     /**
      * Finds the next available (1 based) drawing group id
-     * 
+     *
      * @return the next available drawing group id
      */
     public short findNewDrawingGroupId() {
@@ -293,7 +308,7 @@ public final class EscherDggRecord exten
         }
         return (short)bs.nextClearBit(0);
     }
-    
+
     /**
      * Allocates new shape id for the drawing group
      *
@@ -306,7 +321,7 @@ public final class EscherDggRecord exten
     public int allocateShapeId(EscherDgRecord dg, boolean sort) {
         final short drawingGroupId = dg.getDrawingGroupId();
         field_3_numShapesSaved++;
-        
+
         // check for an existing cluster, which has space available
         // see 2.2.46 OfficeArtIDCL (cspidCur) for the 1024 limitation
         // multiple clusters can belong to the same drawing group
@@ -325,16 +340,16 @@ public final class EscherDggRecord exten
             ficAdd = addCluster( drawingGroupId, 0, sort );
             maxDgId = Math.max(maxDgId, drawingGroupId);
         }
-        
+
         int shapeId = index*1024 + ficAdd.getNumShapeIdsUsed();
         ficAdd.incrementUsedShapeId();
-        
+
         dg.setNumShapes( dg.getNumShapes() + 1 );
         dg.setLastMSOSPID( shapeId );
         field_1_shapeIdMax = Math.max(field_1_shapeIdMax, shapeId + 1);
-        
+
         return shapeId;
-    }    
+    }
 
     @Override
     public Enum getGenericRecordType() {
@@ -352,4 +367,9 @@ public final class EscherDggRecord exten
             "drawingsSaved", this::getDrawingsSaved
         );
     }
+
+    @Override
+    public EscherDggRecord copy() {
+        return new EscherDggRecord(this);
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/ddf/EscherMetafileBlip.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ddf/EscherMetafileBlip.java?rev=1871563&r1=1871562&r2=1871563&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ddf/EscherMetafileBlip.java (original)
+++ poi/trunk/src/java/org/apache/poi/ddf/EscherMetafileBlip.java Sat Dec 14 23:44:26 2019
@@ -65,6 +65,26 @@ public final class EscherMetafileBlip ex
     private byte[] raw_pictureData;
     private byte[] remainingData;
 
+    public EscherMetafileBlip() {}
+
+    public EscherMetafileBlip(EscherMetafileBlip other) {
+        super(other);
+        System.arraycopy(other.field_1_UID, 0, field_1_UID, 0, field_1_UID.length);
+        System.arraycopy(other.field_2_UID, 0, field_2_UID, 0, field_2_UID.length);
+        field_2_cb = other.field_2_cb;
+        field_3_rcBounds_x1 = other.field_3_rcBounds_x1;
+        field_3_rcBounds_y1 = other.field_3_rcBounds_y1;
+        field_3_rcBounds_x2 = other.field_3_rcBounds_x2;
+        field_3_rcBounds_y2 = other.field_3_rcBounds_y2;
+        field_4_ptSize_h = other.field_4_ptSize_h;
+        field_4_ptSize_w = other.field_4_ptSize_w;
+        field_5_cbSave = other.field_5_cbSave;
+        field_6_fCompression = other.field_6_fCompression;
+        field_7_fFilter = other.field_7_fFilter;
+        raw_pictureData = (other.raw_pictureData == null) ? null : other.raw_pictureData.clone();
+        remainingData = (other.remainingData == null) ? null : other.remainingData.clone();
+    }
+
     @Override
     public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) {
         int bytesAfterHeader = readHeader( data, offset );
@@ -263,7 +283,7 @@ public final class EscherMetafileBlip ex
     }
 
     /**
-     * Gets the dimensions of the metafile 
+     * Gets the dimensions of the metafile
      *
      * @return the dimensions of the metafile
      */
@@ -283,7 +303,7 @@ public final class EscherMetafileBlip ex
 
     /**
      * Gets the compressed size of the metafile (in bytes)
-     * 
+     *
      * @return the compressed size
      */
     public int getCompressedSize() {
@@ -325,7 +345,7 @@ public final class EscherMetafileBlip ex
     public byte getFilter() {
         return field_7_fFilter;
     }
-    
+
     /**
      * Sets the filter byte - this is usually 0xFE
      *
@@ -335,8 +355,8 @@ public final class EscherMetafileBlip ex
         field_7_fFilter = filter;
     }
 
-    
-    
+
+
     /**
      * Returns any remaining bytes
      *
@@ -345,7 +365,7 @@ public final class EscherMetafileBlip ex
     public byte[] getRemainingData() {
         return remainingData;
     }
-    
+
     /**
      * Return the blip signature
      *
@@ -381,7 +401,7 @@ public final class EscherMetafileBlip ex
         } catch (IOException e) {
         	throw new RuntimeException("Can't compress metafile picture data", e);
         }
-        
+
         setCompressedSize(raw_pictureData.length);
         setCompressed(true);
     }
@@ -398,4 +418,9 @@ public final class EscherMetafileBlip ex
         m.put("filter", this::getFilter);
         return Collections.unmodifiableMap(m);
     }
+
+    @Override
+    public EscherMetafileBlip copy() {
+        return new EscherMetafileBlip(this);
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/ddf/EscherOptRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ddf/EscherOptRecord.java?rev=1871563&r1=1871562&r2=1871563&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ddf/EscherOptRecord.java (original)
+++ poi/trunk/src/java/org/apache/poi/ddf/EscherOptRecord.java Sat Dec 14 23:44:26 2019
@@ -24,11 +24,17 @@ import org.apache.poi.util.Internal;
  * or complex. Simple types are fixed length. Complex properties are variable
  * length.
  */
-public class EscherOptRecord extends AbstractEscherOptRecord
-{
+public class EscherOptRecord extends AbstractEscherOptRecord {
     public static final short RECORD_ID = EscherRecordTypes.OPT.typeID;
     public static final String RECORD_DESCRIPTION = EscherRecordTypes.OPT.description;
 
+    public EscherOptRecord() {}
+
+    public EscherOptRecord(EscherOptRecord other) {
+        super(other);
+    }
+
+
     @Override
     public short getInstance()
     {
@@ -76,4 +82,9 @@ public class EscherOptRecord extends Abs
     public Enum getGenericRecordType() {
         return EscherRecordTypes.OPT;
     }
+
+    @Override
+    public EscherOptRecord copy() {
+        return new EscherOptRecord(this);
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/ddf/EscherPictBlip.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ddf/EscherPictBlip.java?rev=1871563&r1=1871562&r2=1871563&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ddf/EscherPictBlip.java (original)
+++ poi/trunk/src/java/org/apache/poi/ddf/EscherPictBlip.java Sat Dec 14 23:44:26 2019
@@ -58,6 +58,24 @@ public final class EscherPictBlip extend
 
     private byte[] raw_pictureData;
 
+    public EscherPictBlip() {}
+
+    public EscherPictBlip(EscherPictBlip other) {
+        super(other);
+        System.arraycopy(other.field_1_UID, 0, field_1_UID, 0, field_1_UID.length);
+        field_2_cb = other.field_2_cb;
+        field_3_rcBounds_x1 = other.field_3_rcBounds_x1;
+        field_3_rcBounds_y1 = other.field_3_rcBounds_y1;
+        field_3_rcBounds_x2 = other.field_3_rcBounds_x2;
+        field_3_rcBounds_y2 = other.field_3_rcBounds_y2;
+        field_4_ptSize_w = other.field_4_ptSize_w;
+        field_4_ptSize_h = other.field_4_ptSize_h;
+        field_5_cbSave = other.field_5_cbSave;
+        field_6_fCompression = other.field_6_fCompression;
+        field_7_fFilter = other.field_7_fFilter;
+        raw_pictureData = (other.raw_pictureData == null) ? null : other.raw_pictureData.clone();
+    }
+
     @Override
     public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) {
         int bytesAfterHeader = readHeader(data, offset);
@@ -212,7 +230,7 @@ public final class EscherPictBlip extend
     }
 
     /**
-     * Gets the dimensions of the metafile 
+     * Gets the dimensions of the metafile
      *
      * @return the dimensions of the metafile
      */
@@ -232,7 +250,7 @@ public final class EscherPictBlip extend
 
     /**
      * Gets the compressed size of the metafile (in bytes)
-     * 
+     *
      * @return the compressed size
      */
     public int getCompressedSize() {
@@ -274,7 +292,7 @@ public final class EscherPictBlip extend
     public byte getFilter() {
         return field_7_fFilter;
     }
-    
+
     /**
      * Sets the filter byte - this is usually 0xFE
      *
@@ -296,4 +314,9 @@ public final class EscherPictBlip extend
         m.put("filter", this::getFilter);
         return Collections.unmodifiableMap(m);
     }
+
+    @Override
+    public EscherPictBlip copy() {
+        return new EscherPictBlip(this);
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/ddf/EscherRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ddf/EscherRecord.java?rev=1871563&r1=1871562&r2=1871563&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ddf/EscherRecord.java (original)
+++ poi/trunk/src/java/org/apache/poi/ddf/EscherRecord.java Sat Dec 14 23:44:26 2019
@@ -51,6 +51,11 @@ public abstract class EscherRecord imple
         // fields uninitialised
     }
 
+    protected EscherRecord(EscherRecord other) {
+        _options = other._options;
+        _recordId = other._recordId;
+    }
+
     /**
      * Delegates to fillFields(byte[], int, EscherRecordFactory)
      *
@@ -233,12 +238,11 @@ public abstract class EscherRecord imple
      * Escher records may need to be clonable in the future.
      *
      * @return the cloned object
-     *
-     * @throws CloneNotSupportedException if the subclass hasn't implemented {@link Cloneable}
      */
     @Override
-    public EscherRecord clone() throws CloneNotSupportedException {
-        return (EscherRecord)super.clone();
+    @SuppressWarnings("squid:S2975")
+    public final EscherRecord clone() {
+        return copy();
     }
 
     /**
@@ -345,4 +349,6 @@ public abstract class EscherRecord imple
             "recordSize", this::getRecordSize
         );
     }
+
+    public abstract EscherRecord copy();
 }
\ No newline at end of file

Modified: poi/trunk/src/java/org/apache/poi/ddf/EscherSpRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ddf/EscherSpRecord.java?rev=1871563&r1=1871562&r2=1871563&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ddf/EscherSpRecord.java (original)
+++ poi/trunk/src/java/org/apache/poi/ddf/EscherSpRecord.java Sat Dec 14 23:44:26 2019
@@ -78,6 +78,14 @@ public class EscherSpRecord extends Esch
     private int field_1_shapeId;
     private int field_2_flags;
 
+    public EscherSpRecord() {}
+
+    public EscherSpRecord(EscherSpRecord other) {
+        super(other);
+        field_1_shapeId = other.field_1_shapeId;
+        field_2_flags = other.field_2_flags;
+    }
+
     @Override
     public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) {
         /*int bytesRemaining =*/ readHeader( data, offset );
@@ -169,7 +177,7 @@ public class EscherSpRecord extends Esch
 
     /**
      * Sets a number that identifies this shape.
-     * 
+     *
      * @param field_1_shapeId the shape id
      */
     public void setShapeId( int field_1_shapeId )
@@ -179,7 +187,7 @@ public class EscherSpRecord extends Esch
 
     /**
      * The flags that apply to this shape.
-     * 
+     *
      * @return the flags
      *
      * @see #FLAG_GROUP
@@ -202,7 +210,7 @@ public class EscherSpRecord extends Esch
 
     /**
      * The flags that apply to this shape.
-     * 
+     *
      * @param field_2_flags the flags
      *
      * @see #FLAG_GROUP
@@ -226,7 +234,7 @@ public class EscherSpRecord extends Esch
     /**
      * Returns shape type. Must be one of MSOSPT values (see [MS-ODRAW] for
      * details).
-     * 
+     *
      * @return shape type
      */
     public short getShapeType()
@@ -237,7 +245,7 @@ public class EscherSpRecord extends Esch
     /**
      * Sets shape type. Must be one of MSOSPT values (see [MS-ODRAW] for
      * details).
-     * 
+     *
      * @param value
      *            new shape type
      */
@@ -260,4 +268,9 @@ public class EscherSpRecord extends Esch
     public Enum getGenericRecordType() {
         return EscherRecordTypes.SP;
     }
+
+    @Override
+    public EscherSpRecord copy() {
+        return new EscherSpRecord(this);
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/ddf/EscherSpgrRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ddf/EscherSpgrRecord.java?rev=1871563&r1=1871562&r2=1871563&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ddf/EscherSpgrRecord.java (original)
+++ poi/trunk/src/java/org/apache/poi/ddf/EscherSpgrRecord.java Sat Dec 14 23:44:26 2019
@@ -36,6 +36,16 @@ public class EscherSpgrRecord extends Es
     private int field_3_rectX2;
     private int field_4_rectY2;
 
+    public EscherSpgrRecord() {}
+
+    public EscherSpgrRecord(EscherSpgrRecord other) {
+        super(other);
+        field_1_rectX1 = other.field_1_rectX1;
+        field_2_rectY1 = other.field_2_rectY1;
+        field_3_rectX2 = other.field_3_rectX2;
+        field_4_rectY2 = other.field_4_rectY2;
+    }
+
     @Override
     public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) {
         int bytesRemaining = readHeader( data, offset );
@@ -90,7 +100,7 @@ public class EscherSpgrRecord extends Es
 
     /**
      * The starting top-left coordinate of child records.
-     * 
+     *
      * @return the top-left x coordinate
      */
     public int getRectX1()
@@ -100,7 +110,7 @@ public class EscherSpgrRecord extends Es
 
     /**
      * The top-left coordinate of child records.
-     * 
+     *
      * @param x1 the top-left x coordinate
      */
     public void setRectX1( int x1 )
@@ -110,7 +120,7 @@ public class EscherSpgrRecord extends Es
 
     /**
      * The top-left coordinate of child records.
-     * 
+     *
      * @return the top-left y coordinate
      */
     public int getRectY1()
@@ -120,7 +130,7 @@ public class EscherSpgrRecord extends Es
 
     /**
      * The top-left y coordinate of child records.
-     * 
+     *
      * @param y1 the top-left y coordinate
      */
     public void setRectY1( int y1 )
@@ -130,7 +140,7 @@ public class EscherSpgrRecord extends Es
 
     /**
      * The bottom-right x coordinate of child records.
-     * 
+     *
      * @return the bottom-right x coordinate
      */
     public int getRectX2()
@@ -140,7 +150,7 @@ public class EscherSpgrRecord extends Es
 
     /**
      * The bottom-right x coordinate of child records.
-     * 
+     *
      * @param x2 the bottom-right x coordinate
      */
     public void setRectX2( int x2 )
@@ -150,7 +160,7 @@ public class EscherSpgrRecord extends Es
 
     /**
      * The bottom-right y coordinate of child records.
-     * 
+     *
      * @return the bottom-right y coordinate
      */
     public int getRectY2()
@@ -160,7 +170,7 @@ public class EscherSpgrRecord extends Es
 
     /**
      * The bottom-right y coordinate of child records.
-     * 
+     *
      * @param rectY2 the bottom-right y coordinate
      */
     public void setRectY2(int rectY2) {
@@ -182,4 +192,9 @@ public class EscherSpgrRecord extends Es
     public Enum getGenericRecordType() {
         return EscherRecordTypes.SPGR;
     }
+
+    @Override
+    public EscherSpgrRecord copy() {
+        return new EscherSpgrRecord(this);
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/ddf/EscherSplitMenuColorsRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ddf/EscherSplitMenuColorsRecord.java?rev=1871563&r1=1871562&r2=1871563&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ddf/EscherSplitMenuColorsRecord.java (original)
+++ poi/trunk/src/java/org/apache/poi/ddf/EscherSplitMenuColorsRecord.java Sat Dec 14 23:44:26 2019
@@ -36,6 +36,16 @@ public class EscherSplitMenuColorsRecord
     private int field_3_color3;
     private int field_4_color4;
 
+    public EscherSplitMenuColorsRecord() {}
+
+    public EscherSplitMenuColorsRecord(EscherSplitMenuColorsRecord other) {
+        super(other);
+        field_1_color1 = other.field_1_color1;
+        field_2_color2 = other.field_2_color2;
+        field_3_color3 = other.field_3_color3;
+        field_4_color4 = other.field_4_color4;
+    }
+
     @Override
     public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) {
         int bytesRemaining = readHeader( data, offset );
@@ -87,7 +97,7 @@ public class EscherSplitMenuColorsRecord
     }
 
     /**
-     * Gets the fill color 
+     * Gets the fill color
      *
      * @return the fill color
      */
@@ -173,4 +183,9 @@ public class EscherSplitMenuColorsRecord
     public Enum getGenericRecordType() {
         return EscherRecordTypes.SPLIT_MENU_COLORS;
     }
+
+    @Override
+    public EscherSplitMenuColorsRecord copy() {
+        return new EscherSplitMenuColorsRecord(this);
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/ddf/EscherTertiaryOptRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ddf/EscherTertiaryOptRecord.java?rev=1871563&r1=1871562&r2=1871563&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ddf/EscherTertiaryOptRecord.java (original)
+++ poi/trunk/src/java/org/apache/poi/ddf/EscherTertiaryOptRecord.java Sat Dec 14 23:44:26 2019
@@ -20,10 +20,15 @@ package org.apache.poi.ddf;
  * "The OfficeArtTertiaryFOPT record specifies a table of OfficeArtRGFOPTE properties, as defined in section 2.3.1."
  * -- [MS-ODRAW] -- v20110608; Office Drawing Binary File Format
  */
-public class EscherTertiaryOptRecord extends AbstractEscherOptRecord
-{
+public class EscherTertiaryOptRecord extends AbstractEscherOptRecord {
     public static final short RECORD_ID = EscherRecordTypes.USER_DEFINED.typeID;
 
+    public EscherTertiaryOptRecord() {}
+
+    public EscherTertiaryOptRecord(EscherTertiaryOptRecord other) {
+        super(other);
+    }
+
     @Override
     public String getRecordName() {
         return EscherRecordTypes.USER_DEFINED.recordName;
@@ -33,4 +38,9 @@ public class EscherTertiaryOptRecord ext
     public Enum getGenericRecordType() {
         return EscherRecordTypes.USER_DEFINED;
     }
+
+    @Override
+    public EscherTertiaryOptRecord copy() {
+        return new EscherTertiaryOptRecord(this);
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/ddf/EscherTextboxRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ddf/EscherTextboxRecord.java?rev=1871563&r1=1871562&r2=1871563&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ddf/EscherTextboxRecord.java (original)
+++ poi/trunk/src/java/org/apache/poi/ddf/EscherTextboxRecord.java Sat Dec 14 23:44:26 2019
@@ -43,8 +43,11 @@ public final class EscherTextboxRecord e
     /** The data for this record not including the the 8 byte header */
     private byte[] thedata = NO_BYTES;
 
-    public EscherTextboxRecord()
-    {
+    public EscherTextboxRecord() {}
+
+    public EscherTextboxRecord(EscherTextboxRecord other) {
+        super(other);
+        thedata = (other.thedata == null) ? NO_BYTES : other.thedata.clone();
     }
 
     @Override
@@ -83,7 +86,7 @@ public final class EscherTextboxRecord e
      * does not seem to put anything here, but with PowerPoint this will
      * contain the bytes that make up a TextHeaderAtom followed by a
      * TextBytesAtom/TextCharsAtom
-     * 
+     *
      * @return the extra data
      */
     public byte[] getData()
@@ -95,7 +98,7 @@ public final class EscherTextboxRecord e
      * Sets the extra data (in the parent application's format) to be
      * contained by the record. Used when the parent application changes
      * the contents.
-     * 
+     *
      * @param b the buffer which contains the data
      * @param start the start position in the buffer
      * @param length the length of the block
@@ -105,12 +108,12 @@ public final class EscherTextboxRecord e
         thedata = IOUtils.safelyAllocate(length, MAX_RECORD_LENGTH);
         System.arraycopy(b,start,thedata,0,length);
     }
-    
+
     /**
      * Sets the extra data (in the parent application's format) to be
      * contained by the record. Used when the parent application changes
      * the contents.
-     * 
+     *
      * @param b the data
      */
     public void setData(byte[] b) {
@@ -124,15 +127,6 @@ public final class EscherTextboxRecord e
     }
 
     @Override
-    public EscherTextboxRecord clone() {
-        EscherTextboxRecord etr = new EscherTextboxRecord();
-        etr.setOptions(this.getOptions());
-        etr.setRecordId(this.getRecordId());
-        etr.thedata = this.thedata.clone();
-        return etr;
-    }
-
-    @Override
     public String getRecordName() {
         return EscherRecordTypes.CLIENT_TEXTBOX.recordName;
     }
@@ -150,4 +144,9 @@ public final class EscherTextboxRecord e
             "extraData", this::getData
         );
     }
+
+    @Override
+    public EscherTextboxRecord copy() {
+        return new EscherTextboxRecord(this);
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/ddf/UnknownEscherRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ddf/UnknownEscherRecord.java?rev=1871563&r1=1871562&r2=1871563&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ddf/UnknownEscherRecord.java (original)
+++ poi/trunk/src/java/org/apache/poi/ddf/UnknownEscherRecord.java Sat Dec 14 23:44:26 2019
@@ -40,17 +40,20 @@ public final class UnknownEscherRecord e
 
     /** The data for this record not including the the 8 byte header */
     private byte[] thedata = NO_BYTES;
-    private List<EscherRecord> _childRecords;
+    private final List<EscherRecord> _childRecords = new ArrayList<>();
 
-    public UnknownEscherRecord() {
-        _childRecords = new ArrayList<>();
+    public UnknownEscherRecord() {}
+
+    public UnknownEscherRecord(UnknownEscherRecord other) {
+        super(other);
+        other._childRecords.stream().map(EscherRecord::copy).forEach(_childRecords::add);
     }
 
     @Override
     public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) {
         int bytesRemaining = readHeader( data, offset );
 		/*
-		 * Have a check between available bytes and bytesRemaining, 
+		 * Have a check between available bytes and bytesRemaining,
 		 * take the available length if the bytesRemaining out of range.
 		 */
 		int available = data.length - (offset + 8);
@@ -77,7 +80,7 @@ public final class UnknownEscherRecord e
         if (bytesRemaining < 0) {
             bytesRemaining = 0;
         }
-        
+
         thedata = IOUtils.safelyAllocate(bytesRemaining, MAX_RECORD_LENGTH);
         System.arraycopy( data, offset + 8, thedata, 0, bytesRemaining );
         return bytesRemaining + 8;
@@ -123,16 +126,11 @@ public final class UnknownEscherRecord e
 
     @Override
     public void setChildRecords(List<EscherRecord> childRecords) {
-        _childRecords = childRecords;
-    }
-
-    @Override
-    public UnknownEscherRecord clone() {
-        UnknownEscherRecord uer = new UnknownEscherRecord();
-        uer.thedata = this.thedata.clone();
-        uer.setOptions(this.getOptions());
-        uer.setRecordId(this.getRecordId());
-        return uer;
+        if (childRecords == _childRecords) {
+            return;
+        }
+        _childRecords.clear();
+        _childRecords.addAll(childRecords);
     }
 
     @Override
@@ -156,4 +154,9 @@ public final class UnknownEscherRecord e
     public Enum getGenericRecordType() {
         return EscherRecordTypes.UNKNOWN;
     }
+
+    @Override
+    public UnknownEscherRecord copy() {
+        return new UnknownEscherRecord(this);
+    }
 }

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/EscherPlaceholder.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/EscherPlaceholder.java?rev=1871563&r1=1871562&r2=1871563&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/EscherPlaceholder.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/EscherPlaceholder.java Sat Dec 14 23:44:26 2019
@@ -42,6 +42,14 @@ public class EscherPlaceholder extends E
 
     public EscherPlaceholder() {}
 
+    public EscherPlaceholder(EscherPlaceholder other) {
+        super(other);
+        position = other.position;
+        placementId = other.placementId;
+        size = other.size;
+        unused = other.unused;
+    }
+
     @Override
     public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) {
         int bytesRemaining = readHeader( data, offset );
@@ -107,4 +115,9 @@ public class EscherPlaceholder extends E
     public Enum getGenericRecordType() {
         return RecordTypes.OEPlaceholderAtom;
     }
+
+    @Override
+    public EscherPlaceholder copy() {
+        return new EscherPlaceholder(this);
+    }
 }

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/HSLFEscherClientDataRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/HSLFEscherClientDataRecord.java?rev=1871563&r1=1871562&r2=1871563&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/HSLFEscherClientDataRecord.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/HSLFEscherClientDataRecord.java Sat Dec 14 23:44:26 2019
@@ -33,7 +33,7 @@ import org.apache.poi.util.LittleEndian;
  * An atom record that specifies whether a shape is a placeholder shape.
  * The number, position, and type of placeholder shapes are determined by
  * the slide layout as specified in the SlideAtom record.
- * 
+ *
  * @since POI 3.14-Beta2
  */
 public class HSLFEscherClientDataRecord extends EscherClientDataRecord {
@@ -42,19 +42,29 @@ public class HSLFEscherClientDataRecord
     private static final int MAX_RECORD_LENGTH = 1_000_000;
 
     private final List<Record> _childRecords = new ArrayList<>();
-    
-    public List<? extends Record> getHSLFChildRecords() { 
+
+    public HSLFEscherClientDataRecord() {}
+
+    public HSLFEscherClientDataRecord(HSLFEscherClientDataRecord other) {
+        super(other);
+        // TODO: for now only reference others children, later copy them when Record.copy is available
+        // other._childRecords.stream().map(Record::copy).forEach(_childRecords::add);
+        other._childRecords.addAll(other._childRecords);
+    }
+
+
+    public List<? extends Record> getHSLFChildRecords() {
         return _childRecords;
     }
-    
+
     public void removeChild(Class<? extends Record> childClass) {
         _childRecords.removeIf(childClass::isInstance);
     }
-    
+
     public void addChild(Record childRecord) {
         _childRecords.add(childRecord);
     }
-    
+
     @Override
     public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) {
         int bytesRemaining = readHeader( data, offset );
@@ -67,12 +77,12 @@ public class HSLFEscherClientDataRecord
     @Override
     public int serialize(int offset, byte[] data, EscherSerializationListener listener) {
         listener.beforeRecordSerialize( offset, getRecordId(), this );
-        
+
         LittleEndian.putShort(data, offset, getOptions());
         LittleEndian.putShort(data, offset+2, getRecordId());
 
         byte[] childBytes = getRemainingData();
-        
+
         LittleEndian.putInt(data, offset+4, childBytes.length);
         System.arraycopy(childBytes, 0, data, offset+8, childBytes.length);
         int recordSize = 8+childBytes.length;
@@ -84,7 +94,7 @@ public class HSLFEscherClientDataRecord
     public int getRecordSize() {
         return 8 + getRemainingData().length;
     }
-    
+
     @Override
     public byte[] getRemainingData() {
         ByteArrayOutputStream bos = new ByteArrayOutputStream();
@@ -111,10 +121,13 @@ public class HSLFEscherClientDataRecord
             offset += 8 + rlen;
         }
     }
-    
+
     public String getRecordName() {
         return "HSLFClientData";
     }
 
-    
+    @Override
+    public HSLFEscherClientDataRecord copy() {
+        return new HSLFEscherClientDataRecord(this);
+    }
 }

Modified: poi/trunk/src/testcases/org/apache/poi/ddf/TestEscherContainerRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/ddf/TestEscherContainerRecord.java?rev=1871563&r1=1871562&r2=1871563&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/ddf/TestEscherContainerRecord.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/ddf/TestEscherContainerRecord.java Sat Dec 14 23:44:26 2019
@@ -170,6 +170,8 @@ public final class TestEscherContainerRe
         public String getRecordName() { return ""; }
 		@Override
 		public Enum getGenericRecordType() { return EscherRecordTypes.UNKNOWN; }
+		@Override
+		public DummyEscherRecord copy() { return null; }
 	}
 
     @Test

Modified: poi/trunk/src/testcases/org/apache/poi/ddf/TestEscherDump.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/ddf/TestEscherDump.java?rev=1871563&r1=1871562&r2=1871563&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/ddf/TestEscherDump.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/ddf/TestEscherDump.java Sat Dec 14 23:44:26 2019
@@ -17,11 +17,14 @@
 
 package org.apache.poi.ddf;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertTrue;
 
 import java.io.InputStream;
 import java.io.PrintStream;
 import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.List;
 
 import org.apache.poi.POIDataSamples;
 import org.apache.poi.hssf.HSSFTestDataSamples;
@@ -33,8 +36,35 @@ import org.junit.BeforeClass;
 import org.junit.Test;
 
 public class TestEscherDump {
-    static NullPrinterStream nullPS;
-    
+    private static NullPrinterStream nullPS;
+
+    private static final String recordData =
+        "H4sIAAAAAAAAAL2UaVCSWxjHX0SBChABLRXM1FxSEzXTzHK7dpVIcMmwxXCP9KaGTaWlGYLrtGmGmYEmYmqF2qIt4ppmjNG+" +
+        "2dWulUtOUdq1NHjva8v90HT7eM+Z5znP/M9/zpk5v3mONgAoc5AANBDKeVDW0gQAjZkVCti3mKnpAExpB/m8AKTyEiTCNd2J" +
+        "Z+O0o6W+srDCyH3DhzkgUAD76v86QNA4mKTMg4QfnUew/5qA29CZz6ALqGcSgNzOICB05gD1rhODJR2AZu3Ox3YOKAfVUPhH" +
+        "ULtbpdVJ0ccdijw0pY1A56M3Jup7U15jp7X4PPTTecx92/MT9eZwtUICrLJvsB6z0fHG5qbw7mRpFRaOnPYJ6SqXd5AQMSKM" +
+        "jceyMD4NsULkj1OwHncz5cO3pPvCXXPTMNdNa+kDfwku4q0RnFL8YGBI6N+oXHlgzCkGWGRdONJPK1PbusJrhBltylPBMm3e" +
+        "G0kw6DGdLhoU3pmgJ6n1maC1fXrs0uUL6cWG/kGVm3MWHh3pALq4+PH55k7Uu3d+x85u9zxwIzfQuU+3TIG5SkOgrS1tCJb3" +
+        "3nqHrxcx3XlJA6vZJ6Oi1ctaXppQyBQLbLLrPJaKKq+zIexFLrVdZM+r34pJJpNN1hSrWbM/lIyRmKpYRIi7CybTTUzBWt49" +
+        "11HRM/VbCiZ6Gyt9TZmhGXPS75xYjpH366vhgLJu4ZoZfM+/4FvGaBZIE9aZ2SduMrUT4mJA4NpP8F2AhB+dT+D/jY/7DZ84" +
+        "ULbaK4C4crJvZ4qej2+em2+Vni4mPluh2e5xyoGUWYRaoFnWubHcaX+L09Ya0ta4KrP13C2ozMyicr4ovY0fNhT2wfMF7ip8" +
+        "/tD0u96myXcn92gtTnEuGfBJxY0lFG0mJxPWpknjNxmzWvzKj18rpjO4hhQXAtaRVSmJu+D8egI3RdQVXYxzRhs1+HE2iNvM" +
+        "fVe2DsSjqJQbBdUajcaECC3/58MP97Q0Eo+GNTdKbhk1r7UJadrVj0rLplmAqU/BlGeXDObGLtl69vITp9tD25vVY9vUT17u" +
+        "WTGW8idcxUDMMX2PHa8X6xzG0C5cGJcVth40m3ycwCpcfuP4OClu6IpysV/9QuvrdW/Yb3Qj6Ul7e3nybqemdkvLXsXG2N3v" +
+        "qeVE0woXb06pLduuFWUv7NxY8jq1k63fcD5jvG/w/IE8eUNh0Pohz0WRx6tdOlf4XhlbF5pgfYYzn8w6cjYx/8rBXvtWNz8L" +
+        "6uu+ig35t+dgOc4jOpLirmFPtjQdKHovGZ4Bff4LaIPLnx6cbnKFo8JHDoGpJ1+BwKGfgM6GhB+d+F/0acj3PiVEABoProzN" +
+        "1dcsVo9TPoPIF+r9EQI0qtveV4WEI1YhFjfmLxDsyFJptHvx/0BD3bfKJY/XqlFTReyIko4tQSzFFRyGRbkyg7MyuCqTmsiA" +
+        "mAgs3FGB0BOR7LzNuUYMC9QWaXyUTcxELLOFQvaRIQZ1HlgkJtE25Ohym/xzkqxqbFI1fWKsGgKq0m/q9kwkVDJAvdKM+7c8" +
+        "wj8GVPdneU0GVaeLVO6Kd3T2lMQFRNeCRwUyx5LSIxI5RmIFNc2RnuSIfYOeOZ+0CwzE7BFTJO+5cVeUz2nDN7mMYUSYOZyv" +
+        "SyyaRRydLKPYMmqFbS5K8RJ6vQNIGtiuI8AKCEgXsqV9Vz1tgvzovKiD2FPtpNgRlb0keoprdS+hnsP6ICwLBrE9dz26g2YP" +
+        "DszibWNE7zW5xndwlsoqFRh87XTFw8BXiFdv0SDsGBnfNcOu/Qu7y7SLppfzLJq714byzYQ590BA+BN2xyDhR+fZX7CL/s5u" +
+        "Q9f/8ccWX28U3BaGw9qTiSqDfOtHmXXZq8XiHXAYoz901c5V2lVulTXZEMqwnLq8+8ds95s0FFrdl73saRntr/UuUxFHY0WU" +
+        "z5b333qXTe/NagSRrmqkqypoNG12Oz3nE5Yzyt7d05eY66Ci2oTR+rNS3K4OiClGK+07HWtFFLvAqv6sNkpFsLs4Wp8XfRp/" +
+        "11oPk3uTQB0ftHg1C16KRTBl+AbCzVaYfx6VFlJ7GL7Jme8bVOku8FKZL0eGgMVk4qhEnpZogNrtFU5yEyswJ+LbHOKsOPCn" +
+        "cT19LR+PfTgjN4CKCS5Es4LS+7nLt9hQ7ejwGQnEyxebOgJzlHjotWUACpoZsFkAgGqBeUDZAzB6h4N2MFCNhmIuFJMAgPsH" +
+        "eJr+iZEHAAA=";
+
+
     @BeforeClass
     public static void init() throws UnsupportedEncodingException {
         nullPS = new NullPrinterStream();
@@ -43,32 +73,6 @@ public class TestEscherDump {
     // simple test to at least cover some parts of the class
     @Test
     public void testSimple() throws Exception {
-        final String recordData =
-            "H4sIAAAAAAAAAL2UaVCSWxjHX0SBChABLRXM1FxSEzXTzHK7dpVIcMmwxXCP9KaGTaWlGYLrtGmGmYEmYmqF2qIt4ppmjNG+" +
-            "2dWulUtOUdq1NHjva8v90HT7eM+Z5znP/M9/zpk5v3mONgAoc5AANBDKeVDW0gQAjZkVCti3mKnpAExpB/m8AKTyEiTCNd2J" +
-            "Z+O0o6W+srDCyH3DhzkgUAD76v86QNA4mKTMg4QfnUew/5qA29CZz6ALqGcSgNzOICB05gD1rhODJR2AZu3Ox3YOKAfVUPhH" +
-            "ULtbpdVJ0ccdijw0pY1A56M3Jup7U15jp7X4PPTTecx92/MT9eZwtUICrLJvsB6z0fHG5qbw7mRpFRaOnPYJ6SqXd5AQMSKM" +
-            "jceyMD4NsULkj1OwHncz5cO3pPvCXXPTMNdNa+kDfwku4q0RnFL8YGBI6N+oXHlgzCkGWGRdONJPK1PbusJrhBltylPBMm3e" +
-            "G0kw6DGdLhoU3pmgJ6n1maC1fXrs0uUL6cWG/kGVm3MWHh3pALq4+PH55k7Uu3d+x85u9zxwIzfQuU+3TIG5SkOgrS1tCJb3" +
-            "3nqHrxcx3XlJA6vZJ6Oi1ctaXppQyBQLbLLrPJaKKq+zIexFLrVdZM+r34pJJpNN1hSrWbM/lIyRmKpYRIi7CybTTUzBWt49" +
-            "11HRM/VbCiZ6Gyt9TZmhGXPS75xYjpH366vhgLJu4ZoZfM+/4FvGaBZIE9aZ2SduMrUT4mJA4NpP8F2AhB+dT+D/jY/7DZ84" +
-            "ULbaK4C4crJvZ4qej2+em2+Vni4mPluh2e5xyoGUWYRaoFnWubHcaX+L09Ya0ta4KrP13C2ozMyicr4ovY0fNhT2wfMF7ip8" +
-            "/tD0u96myXcn92gtTnEuGfBJxY0lFG0mJxPWpknjNxmzWvzKj18rpjO4hhQXAtaRVSmJu+D8egI3RdQVXYxzRhs1+HE2iNvM" +
-            "fVe2DsSjqJQbBdUajcaECC3/58MP97Q0Eo+GNTdKbhk1r7UJadrVj0rLplmAqU/BlGeXDObGLtl69vITp9tD25vVY9vUT17u" +
-            "WTGW8idcxUDMMX2PHa8X6xzG0C5cGJcVth40m3ycwCpcfuP4OClu6IpysV/9QuvrdW/Yb3Qj6Ul7e3nybqemdkvLXsXG2N3v" +
-            "qeVE0woXb06pLduuFWUv7NxY8jq1k63fcD5jvG/w/IE8eUNh0Pohz0WRx6tdOlf4XhlbF5pgfYYzn8w6cjYx/8rBXvtWNz8L" +
-            "6uu+ig35t+dgOc4jOpLirmFPtjQdKHovGZ4Bff4LaIPLnx6cbnKFo8JHDoGpJ1+BwKGfgM6GhB+d+F/0acj3PiVEABoProzN" +
-            "1dcsVo9TPoPIF+r9EQI0qtveV4WEI1YhFjfmLxDsyFJptHvx/0BD3bfKJY/XqlFTReyIko4tQSzFFRyGRbkyg7MyuCqTmsiA" +
-            "mAgs3FGB0BOR7LzNuUYMC9QWaXyUTcxELLOFQvaRIQZ1HlgkJtE25Ohym/xzkqxqbFI1fWKsGgKq0m/q9kwkVDJAvdKM+7c8" +
-            "wj8GVPdneU0GVaeLVO6Kd3T2lMQFRNeCRwUyx5LSIxI5RmIFNc2RnuSIfYOeOZ+0CwzE7BFTJO+5cVeUz2nDN7mMYUSYOZyv" +
-            "SyyaRRydLKPYMmqFbS5K8RJ6vQNIGtiuI8AKCEgXsqV9Vz1tgvzovKiD2FPtpNgRlb0keoprdS+hnsP6ICwLBrE9dz26g2YP" +
-            "DszibWNE7zW5xndwlsoqFRh87XTFw8BXiFdv0SDsGBnfNcOu/Qu7y7SLppfzLJq714byzYQ590BA+BN2xyDhR+fZX7CL/s5u" +
-            "Q9f/8ccWX28U3BaGw9qTiSqDfOtHmXXZq8XiHXAYoz901c5V2lVulTXZEMqwnLq8+8ds95s0FFrdl73saRntr/UuUxFHY0WU" +
-            "z5b333qXTe/NagSRrmqkqypoNG12Oz3nE5Yzyt7d05eY66Ci2oTR+rNS3K4OiClGK+07HWtFFLvAqv6sNkpFsLs4Wp8XfRp/" +
-            "11oPk3uTQB0ftHg1C16KRTBl+AbCzVaYfx6VFlJ7GL7Jme8bVOku8FKZL0eGgMVk4qhEnpZogNrtFU5yEyswJ+LbHOKsOPCn" +
-            "cT19LR+PfTgjN4CKCS5Es4LS+7nLt9hQ7ejwGQnEyxebOgJzlHjotWUACpoZsFkAgGqBeUDZAzB6h4N2MFCNhmIuFJMAgPsH" +
-            "eJr+iZEHAAA=";
-
         // Create a new instance of the escher dumper
         EscherDump dumper = new EscherDump();
 
@@ -82,17 +86,17 @@ public class TestEscherDump {
     }
 
     @Test
-    public void testWithData() throws Exception {
+    public void testWithData() {
         new EscherDump().dump(8, new byte[] {0, 0, 0, 0, 0, 0, 0, 0}, nullPS);
     }
 
     @Test
-    public  void testWithSamplefile() throws Exception {
+    public void testWithSamplefile() throws Exception {
         //InputStream stream = HSSFTestDataSamples.openSampleFileStream(")
         byte[] data = POIDataSamples.getDDFInstance().readFile("Container.dat");
         new EscherDump().dump(data.length, data, nullPS);
         //new EscherDump().dumpOld(data.length, new ByteArrayInputStream(data), System.out);
-        
+
         data = new byte[2586114];
         try (InputStream stream = HSSFTestDataSamples.openSampleFileStream("44593.xls")) {
             int bytes = IOUtils.readFully(stream, data);
@@ -101,7 +105,21 @@ public class TestEscherDump {
             //new EscherDump().dumpOld(bytes, new ByteArrayInputStream(data), System.out);
         }
     }
-    
+
+    @Test
+    public void testCopy() throws Exception {
+        byte[] data1 = RawDataUtil.decompress(recordData);
+
+        List<EscherRecord> records = new ArrayList<>();
+        EscherRecordFactory recordFactory = new DefaultEscherRecordFactory();
+        EscherRecord r = recordFactory.createRecord(data1, 0);
+        r.fillFields(data1, recordFactory);
+        EscherRecord r2 = r.copy();
+        byte[] data2 = r2.serialize();
+
+        assertArrayEquals(data1, data2);
+    }
+
     /**
      * Implementation of an OutputStream which does nothing, used
      * to redirect stdout to avoid spamming the console with output
@@ -110,6 +128,6 @@ public class TestEscherDump {
         @SuppressWarnings("resource")
         private NullPrinterStream() throws UnsupportedEncodingException {
             super(new NullOutputStream(),true,LocaleUtil.CHARSET_1252.name());
-        }      
-    }    
+        }
+    }
 }



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