]> source.dussan.org Git - poi.git/commitdiff
Replace internal GUID class with ClassID
authorAndreas Beeker <kiwiwings@apache.org>
Tue, 24 Dec 2019 19:48:22 +0000 (19:48 +0000)
committerAndreas Beeker <kiwiwings@apache.org>
Tue, 24 Dec 2019 19:48:22 +0000 (19:48 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1871944 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/hpsf/ClassID.java
src/java/org/apache/poi/hpsf/ClassIDPredefined.java
src/java/org/apache/poi/hssf/record/HyperlinkRecord.java
src/testcases/org/apache/poi/hssf/record/TestHyperlinkRecord.java

index 47eb272daa1d75dce2a31f9946da1989497f8e96..a60b50e86c8d484915ede0bfc7592fe3363af01b 100644 (file)
@@ -19,17 +19,20 @@ package org.apache.poi.hpsf;
 
 import java.util.Arrays;
 
-import org.apache.poi.util.HexDump;
+import org.apache.commons.codec.binary.Hex;
+import org.apache.poi.common.Duplicatable;
+import org.apache.poi.util.LittleEndianInput;
+import org.apache.poi.util.LittleEndianOutput;
 
 /**
  * Represents a class ID (16 bytes). Unlike other little-endian
  * type the {@link ClassID} is not just 16 bytes stored in the wrong
  * order. Instead, it is a double word (4 bytes) followed by two
  * words (2 bytes each) followed by 8 bytes.<p>
- *  
- * The ClassID (or CLSID) is a UUID - see RFC 4122 
+ *
+ * The ClassID (or CLSID) is a UUID - see RFC 4122
  */
-public class ClassID {
+public class ClassID implements Duplicatable {
     /** @deprecated use enum {@link ClassIDPredefined} */ @Deprecated
     public static final ClassID OLE10_PACKAGE  = ClassIDPredefined.OLE_V1_PACKAGE.getClassID();
     /** @deprecated use enum {@link ClassIDPredefined} */ @Deprecated
@@ -84,10 +87,10 @@ public class ClassID {
     public static final ClassID POWERPOINT2007_MACRO = ClassIDPredefined.POWERPOINT_V12_MACRO.getClassID();
     /** @deprecated use enum {@link ClassIDPredefined} */ @Deprecated
     public static final ClassID EQUATION30     = ClassIDPredefined.EQUATION_V3.getClassID();
-       
+
     /** The number of bytes occupied by this object in the byte stream. */
     public static final int LENGTH = 16;
-       
+
     /**
      * The bytes making out the class ID in correct order, i.e. big-endian.
      */
@@ -111,11 +114,18 @@ public class ClassID {
         Arrays.fill(bytes, (byte)0);
     }
 
+    /**
+     * Clones the given ClassID
+     */
+    public ClassID(ClassID other) {
+        System.arraycopy(other.bytes, 0, bytes, 0, bytes.length);
+    }
+
 
     /**
-     * Creates a {@link ClassID} from a human-readable representation of the Class ID in standard 
+     * Creates a {@link ClassID} from a human-readable representation of the Class ID in standard
      * format {@code "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"}.
-     * 
+     *
      * @param externalForm representation of the Class ID represented by this object.
      */
     public ClassID(String externalForm) {
@@ -124,7 +134,16 @@ public class ClassID {
                bytes[i/2] = (byte)Integer.parseInt(clsStr.substring(i, i+2), 16);
         }
     }
-    
+
+    /**
+     * Reads the ClassID from the input
+     * @param lei the input (stream)
+     */
+    public ClassID(LittleEndianInput lei) {
+        byte[] buf = bytes.clone();
+        lei.readFully(buf);
+        read(buf, 0);
+    }
 
     /**
      * @return The number of bytes occupied by this object in the byte stream.
@@ -204,7 +223,7 @@ public class ClassID {
                 ("Destination byte[] must have room for at least 16 bytes, " +
                  "but has a length of only " + dst.length + ".");
         }
-        
+
         /* Write double word. */
         dst[0 + offset] = bytes[3];
         dst[1 + offset] = bytes[2];
@@ -223,7 +242,16 @@ public class ClassID {
         System.arraycopy(bytes, 8, dst, 8 + offset, 8);
     }
 
-
+    /**
+     * Write the class ID to a LittleEndianOutput (stream)
+     *
+     * @param leo the output
+     */
+    public void write(LittleEndianOutput leo) {
+        byte[] buf = bytes.clone();
+        write(buf, 0);
+        leo.write(buf);
+    }
 
     /**
      * Checks whether this {@code ClassID} is equal to another object.
@@ -275,22 +303,23 @@ public class ClassID {
     }
 
     /**
-     * Returns a human-readable representation of the Class ID in standard 
+     * Returns a human-readable representation of the Class ID in standard
      * format {@code "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"}.
-     * 
+     *
      * @return String representation of the Class ID represented by this object.
      */
     @Override
     public String toString() {
-        StringBuilder sbClassId = new StringBuilder(38);
-        sbClassId.append('{');
-        for (int i = 0; i < LENGTH; i++) {
-            sbClassId.append(HexDump.toHex(bytes[i]));
-            if (i == 3 || i == 5 || i == 7 || i == 9) {
-                sbClassId.append('-');
-            }
-        }
-        sbClassId.append('}');
-        return sbClassId.toString();
+        String hex = Hex.encodeHexString(bytes, false);
+        return  "{" + hex.substring(0,8) +
+                "-" + hex.substring(8,12) +
+                "-" + hex.substring(12,16) +
+                "-" + hex.substring(16,20) +
+                "-" + hex.substring(20) + "}";
+    }
+
+    @Override
+    public ClassID copy() {
+        return new ClassID(this);
     }
 }
index 5e81639d412320b2359f702e9314d9ce88eb2352..1974c3164dc94d7acad11e0343416286da854f74 100644 (file)
@@ -86,9 +86,16 @@ public enum ClassIDPredefined {
     /** Plain Text Persistent Handler **/
     TXT_ONLY             ("{5e941d80-bf96-11cd-b579-08002b30bfeb}", ".txt", "text/plain"),
     /** Microsoft Paint **/
-    PAINT                ("{0003000A-0000-0000-C000-000000000046}", null, null)
+    PAINT                ("{0003000A-0000-0000-C000-000000000046}", null, null),
+    /** Standard Hyperlink / STD Moniker **/
+    STD_MONIKER          ("{79EAC9D0-BAF9-11CE-8C82-00AA004BA90B}", null, null),
+    /** URL Moniker **/
+    URL_MONIKER          ("{79EAC9E0-BAF9-11CE-8C82-00AA004BA90B}", null, null),
+    /** File Moniker **/
+    FILE_MONIKER         ("{00000303-0000-0000-C000-000000000046}", null, null)
     ;
-    
+
+
     private static final Map<String,ClassIDPredefined> LOOKUP = new HashMap<>();
 
     static {
@@ -96,18 +103,18 @@ public enum ClassIDPredefined {
             LOOKUP.put(p.externalForm, p);
         }
     }
-    
+
     private final String externalForm;
     private ClassID classId;
     private final String fileExtension;
     private final String contentType;
-    
+
     ClassIDPredefined(final String externalForm, final String fileExtension, final String contentType) {
         this.externalForm = externalForm;
         this.fileExtension = fileExtension;
         this.contentType = contentType;
     }
-    
+
     public ClassID getClassID() {
         synchronized (this) {
             // TODO: init classId directly in the constructor when old statics have been removed from ClassID
@@ -125,7 +132,7 @@ public enum ClassIDPredefined {
     public String getContentType() {
         return contentType;
     }
-    
+
     public static ClassIDPredefined lookup(final String externalForm) {
         return LOOKUP.get(externalForm);
     }
@@ -133,4 +140,8 @@ public enum ClassIDPredefined {
     public static ClassIDPredefined lookup(final ClassID classID) {
         return (classID == null) ? null : LOOKUP.get(classID.toString());
     }
+
+    public boolean equals(ClassID classID) {
+        return getClassID().equals(classID);
+    }
 }
index ae6ae086a7887c5321ecc12d2d79327e078550e1..97888bac6c3ce8ae569a8e275188118a9ea777b6 100644 (file)
 
 package org.apache.poi.hssf.record;
 
+import static org.apache.poi.hpsf.ClassIDPredefined.FILE_MONIKER;
+import static org.apache.poi.hpsf.ClassIDPredefined.STD_MONIKER;
+import static org.apache.poi.hpsf.ClassIDPredefined.URL_MONIKER;
+
+import org.apache.poi.hpsf.ClassID;
 import org.apache.poi.ss.util.CellRangeAddress;
 import org.apache.poi.util.HexDump;
 import org.apache.poi.util.HexRead;
 import org.apache.poi.util.IOUtils;
-import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.LittleEndianInput;
 import org.apache.poi.util.LittleEndianOutput;
 import org.apache.poi.util.POILogFactory;
@@ -37,177 +41,11 @@ import org.apache.poi.util.StringUtil;
  */
 public final class HyperlinkRecord extends StandardRecord {
     public static final short sid = 0x01B8;
-    private static POILogger logger = POILogFactory.getLogger(HyperlinkRecord.class);
+    private static final POILogger logger = POILogFactory.getLogger(HyperlinkRecord.class);
     //arbitrarily selected; may need to increase
     private static final int MAX_RECORD_LENGTH = 100_000;
 
 
-    // TODO: replace with ClassID
-    static final class GUID {
-        /*
-         * this class is currently only used here, but could be moved to a
-         * common package if needed
-         */
-        private static final int TEXT_FORMAT_LENGTH = 36;
-
-        public static final int ENCODED_SIZE = 16;
-
-        /** 4 bytes - little endian */
-        private final int _d1;
-        /** 2 bytes - little endian */
-        private final int _d2;
-        /** 2 bytes - little endian */
-        private final int _d3;
-        /**
-         * 8 bytes - serialized as big endian,  stored with inverted endianness here
-         */
-        private final long _d4;
-
-        public GUID(GUID other) {
-            _d1 = other._d1;
-            _d2 = other._d2;
-            _d3 = other._d3;
-            _d4 = other._d4;
-        }
-
-        public GUID(LittleEndianInput in) {
-            this(in.readInt(), in.readUShort(), in.readUShort(), in.readLong());
-        }
-
-        public GUID(int d1, int d2, int d3, long d4) {
-            _d1 = d1;
-            _d2 = d2;
-            _d3 = d3;
-            _d4 = d4;
-        }
-
-        public void serialize(LittleEndianOutput out) {
-            out.writeInt(_d1);
-            out.writeShort(_d2);
-            out.writeShort(_d3);
-            out.writeLong(_d4);
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (!(obj instanceof GUID)) {
-                return false;
-            }
-            GUID other = (GUID) obj;
-            return _d1 == other._d1 && _d2 == other._d2
-                && _d3 == other._d3 && _d4 == other._d4;
-        }
-
-       @Override
-       public int hashCode() {
-           assert false : "hashCode not designed";
-           return 42; // any arbitrary constant will do
-       }
-
-       public int getD1() {
-            return _d1;
-        }
-
-        public int getD2() {
-            return _d2;
-        }
-
-        public int getD3() {
-            return _d3;
-        }
-
-        public long getD4() {
-            byte[] result = new byte[Long.SIZE/Byte.SIZE];
-            long l = _d4;
-            for (int i = result.length-1; i >= 0; i--) {
-                result[i] = (byte)(l & 0xFF);
-                l >>= 8;
-            }
-
-            return LittleEndian.getLong(result, 0);
-        }
-
-        public String formatAsString() {
-
-            StringBuilder sb = new StringBuilder(36);
-
-            int PREFIX_LEN = "0x".length();
-            sb.append(HexDump.intToHex(_d1).substring(PREFIX_LEN));
-            sb.append("-");
-            sb.append(HexDump.shortToHex(_d2).substring(PREFIX_LEN));
-            sb.append("-");
-            sb.append(HexDump.shortToHex(_d3).substring(PREFIX_LEN));
-            sb.append("-");
-            String d4Chars = HexDump.longToHex(getD4());
-            sb.append(d4Chars, PREFIX_LEN, PREFIX_LEN+4);
-            sb.append("-");
-            sb.append(d4Chars.substring(PREFIX_LEN+4));
-            return sb.toString();
-        }
-
-        @Override
-        public String toString() {
-            StringBuilder sb = new StringBuilder(64);
-            sb.append(getClass().getName()).append(" [");
-            sb.append(formatAsString());
-            sb.append("]");
-            return sb.toString();
-        }
-
-        /**
-         * Read a GUID in standard text form e.g.<br>
-         * 13579BDF-0246-8ACE-0123-456789ABCDEF
-         * <br> -&gt; <br>
-         *  0x13579BDF, 0x0246, 0x8ACE 0x0123456789ABCDEF
-         */
-        public static GUID parse(String rep) {
-            char[] cc = rep.toCharArray();
-            if (cc.length != TEXT_FORMAT_LENGTH) {
-                throw new RecordFormatException("supplied text is the wrong length for a GUID");
-            }
-            int d0 = (parseShort(cc, 0) << 16) + (parseShort(cc, 4) << 0);
-            int d1 = parseShort(cc, 9);
-            int d2 = parseShort(cc, 14);
-            System.arraycopy(cc, 19, cc, 20, 4);
-            long d3 = parseLELong(cc, 20);
-
-            return new GUID(d0, d1, d2, d3);
-        }
-
-        private static long parseLELong(char[] cc, int startIndex) {
-            long acc = 0;
-            for (int i = startIndex + 14; i >= startIndex; i -= 2) {
-                acc <<= 4;
-                acc += parseHexChar(cc[i + 0]);
-                acc <<= 4;
-                acc += parseHexChar(cc[i + 1]);
-            }
-            return acc;
-        }
-
-        private static int parseShort(char[] cc, int startIndex) {
-            int acc = 0;
-            for (int i = 0; i < 4; i++) {
-                acc <<= 4;
-                acc += parseHexChar(cc[startIndex + i]);
-            }
-            return acc;
-        }
-
-        private static int parseHexChar(char c) {
-            if (c >= '0' && c <= '9') {
-                return c - '0';
-            }
-            if (c >= 'A' && c <= 'F') {
-                return c - 'A' + 10;
-            }
-            if (c >= 'a' && c <= 'f') {
-                return c - 'a' + 10;
-            }
-            throw new RecordFormatException("Bad hex char '" + c + "'");
-        }
-    }
-
     /*
      * Link flags
      */
@@ -219,9 +57,6 @@ public final class HyperlinkRecord extends StandardRecord {
     private static final int  HLINK_TARGET_FRAME  = 0x80;  // has 'target frame'
     private static final int  HLINK_UNC_PATH  = 0x100;  // has UNC path
 
-    static final GUID STD_MONIKER = GUID.parse("79EAC9D0-BAF9-11CE-8C82-00AA004BA90B");
-    static final GUID URL_MONIKER = GUID.parse("79EAC9E0-BAF9-11CE-8C82-00AA004BA90B");
-    static final GUID FILE_MONIKER = GUID.parse("00000303-0000-0000-C000-000000000046");
     /** expected Tail of a URL link */
     private static final byte[] URL_TAIL  = HexRead.readFromString("79 58 81 F4  3B 1D 7F 48   AF 2C 82 5D  C4 85 27 63   00 00 00 00  A5 AB 00 00");
     /** expected Tail of a file link */
@@ -233,7 +68,7 @@ public final class HyperlinkRecord extends StandardRecord {
     private CellRangeAddress _range;
 
     /** 16-byte GUID */
-    private GUID _guid;
+    private ClassID _guid;
     /** Some sort of options for file links. */
     private int _fileOpts;
     /** Link options. Can include any of HLINK_* flags. */
@@ -243,7 +78,7 @@ public final class HyperlinkRecord extends StandardRecord {
 
     private String _targetFrame;
     /** Moniker. Makes sense only for URL and file links */
-    private GUID _moniker;
+    private ClassID _moniker;
     /** in 8:3 DOS format No Unicode string header,
      * always 8-bit characters, zero-terminated */
     private String _shortFilename;
@@ -267,12 +102,12 @@ public final class HyperlinkRecord extends StandardRecord {
     public HyperlinkRecord(HyperlinkRecord other) {
         super(other);
         _range = (other._range == null) ? null : other._range.copy();
-        _guid = (other._guid == null) ? null : new GUID(other._guid);
+        _guid = (other._guid == null) ? null : other._guid.copy();
         _fileOpts = other._fileOpts;
         _linkOpts = other._linkOpts;
         _label = other._label;
         _targetFrame = other._targetFrame;
-        _moniker = (other._moniker == null) ? null : new GUID(other._moniker);
+        _moniker = (other._moniker == null) ? null : other._moniker.copy();
         _shortFilename = other._shortFilename;
         _address = other._address;
         _textMark = other._textMark;
@@ -345,16 +180,16 @@ public final class HyperlinkRecord extends StandardRecord {
     }
 
     /**
-     * @return 16-byte guid identifier Seems to always equal {@link #STD_MONIKER}
+     * @return 16-byte guid identifier Seems to always equal {@link org.apache.poi.hpsf.ClassIDPredefined#STD_MONIKER}
      */
-    GUID getGuid() {
+    ClassID getGuid() {
         return _guid;
     }
 
     /**
      * @return 16-byte moniker
      */
-    GUID getMoniker()
+    ClassID getMoniker()
     {
         return _moniker;
     }
@@ -471,9 +306,9 @@ public final class HyperlinkRecord extends StandardRecord {
     public HyperlinkRecord(RecordInputStream in) {
         _range = new CellRangeAddress(in);
 
-        _guid = new GUID(in);
+        _guid = new ClassID(in);
 
-        /**
+        /*
          * streamVersion (4 bytes): An unsigned integer that specifies the version number
          * of the serialization implementation used to save this structure. This value MUST equal 2.
          */
@@ -500,11 +335,11 @@ public final class HyperlinkRecord extends StandardRecord {
         }
 
         if ((_linkOpts & HLINK_URL) != 0 && (_linkOpts & HLINK_UNC_PATH) == 0) {
-            _moniker = new GUID(in);
+            _moniker = new ClassID(in);
 
             if(URL_MONIKER.equals(_moniker)){
                 int length = in.readInt();
-                /**
+                /*
                  * The value of <code>length<code> be either the byte size of the url field
                  * (including the terminating NULL character) or the byte size of the url field plus 24.
                  * If the value of this field is set to the byte size of the url field,
@@ -517,7 +352,7 @@ public final class HyperlinkRecord extends StandardRecord {
                 } else {
                     int nChars = (length - TAIL_SIZE)/2;
                     _address = in.readUnicodeLEString(nChars);
-                    /**
+                    /*
                      * TODO: make sense of the remaining bytes
                      * According to the spec they consist of:
                      * 1. 16-byte  GUID: This field MUST equal
@@ -575,7 +410,7 @@ public final class HyperlinkRecord extends StandardRecord {
     public void serialize(LittleEndianOutput out) {
         _range.serialize(out);
 
-        _guid.serialize(out);
+        _guid.write(out);
         out.writeInt(0x00000002); // TODO const
         out.writeInt(_linkOpts);
 
@@ -594,7 +429,7 @@ public final class HyperlinkRecord extends StandardRecord {
         }
 
         if ((_linkOpts & HLINK_URL) != 0 && (_linkOpts & HLINK_UNC_PATH) == 0) {
-            _moniker.serialize(out);
+            _moniker.write(out);
             if(URL_MONIKER.equals(_moniker)){
                 if (_uninterpretedTail == null) {
                     out.writeInt(_address.length()*2);
@@ -630,7 +465,7 @@ public final class HyperlinkRecord extends StandardRecord {
     protected int getDataSize() {
         int size = 0;
         size += 2 + 2 + 2 + 2;  //rwFirst, rwLast, colFirst, colLast
-        size += GUID.ENCODED_SIZE;
+        size += ClassID.LENGTH;
         size += 4;  //label_opts
         size += 4;  //link_opts
         if ((_linkOpts & HLINK_LABEL) != 0){
@@ -646,7 +481,7 @@ public final class HyperlinkRecord extends StandardRecord {
             size += _address.length()*2;
         }
         if ((_linkOpts & HLINK_URL) != 0 && (_linkOpts & HLINK_UNC_PATH) == 0) {
-            size += GUID.ENCODED_SIZE;
+            size += ClassID.LENGTH;
             if(URL_MONIKER.equals(_moniker)){
                 size += 4;  //address length
                 size += _address.length()*2;
@@ -703,14 +538,14 @@ public final class HyperlinkRecord extends StandardRecord {
 
         buffer.append("[HYPERLINK RECORD]\n");
         buffer.append("    .range   = ").append(_range.formatAsString()).append("\n");
-        buffer.append("    .guid    = ").append(_guid.formatAsString()).append("\n");
+        buffer.append("    .guid    = ").append(_guid.toString()).append("\n");
         buffer.append("    .linkOpts= ").append(HexDump.intToHex(_linkOpts)).append("\n");
         buffer.append("    .label   = ").append(getLabel()).append("\n");
         if ((_linkOpts & HLINK_TARGET_FRAME) != 0) {
             buffer.append("    .targetFrame= ").append(getTargetFrame()).append("\n");
         }
         if((_linkOpts & HLINK_URL) != 0 && _moniker != null) {
-            buffer.append("    .moniker   = ").append(_moniker.formatAsString()).append("\n");
+            buffer.append("    .moniker   = ").append(_moniker.toString()).append("\n");
         }
         if ((_linkOpts & HLINK_PLACE) != 0) {
             buffer.append("    .textMark= ").append(getTextMark()).append("\n");
@@ -725,6 +560,7 @@ public final class HyperlinkRecord extends StandardRecord {
      *
      * @return true, if this is a url link
      */
+    @SuppressWarnings("unused")
     public boolean isUrlLink() {
        return (_linkOpts & HLINK_URL) > 0
            && (_linkOpts & HLINK_ABS) > 0;
@@ -752,10 +588,10 @@ public final class HyperlinkRecord extends StandardRecord {
      */
     public void newUrlLink() {
         _range = new CellRangeAddress(0, 0, 0, 0);
-        _guid = STD_MONIKER;
+        _guid = STD_MONIKER.getClassID();
         _linkOpts = HLINK_URL | HLINK_ABS | HLINK_LABEL;
         setLabel("");
-        _moniker = URL_MONIKER;
+        _moniker = URL_MONIKER.getClassID();
         setAddress("");
         _uninterpretedTail = URL_TAIL;
     }
@@ -765,11 +601,11 @@ public final class HyperlinkRecord extends StandardRecord {
      */
     public void newFileLink() {
         _range = new CellRangeAddress(0, 0, 0, 0);
-        _guid = STD_MONIKER;
+        _guid = STD_MONIKER.getClassID();
         _linkOpts = HLINK_URL | HLINK_LABEL;
         _fileOpts = 0;
         setLabel("");
-        _moniker = FILE_MONIKER;
+        _moniker = FILE_MONIKER.getClassID();
         setAddress(null);
         setShortFilename("");
         _uninterpretedTail = FILE_TAIL;
@@ -780,16 +616,16 @@ public final class HyperlinkRecord extends StandardRecord {
      */
     public void newDocumentLink() {
         _range = new CellRangeAddress(0, 0, 0, 0);
-        _guid = STD_MONIKER;
+        _guid = STD_MONIKER.getClassID();
         _linkOpts = HLINK_LABEL | HLINK_PLACE;
         setLabel("");
-        _moniker = FILE_MONIKER;
+        _moniker = FILE_MONIKER.getClassID();
         setAddress("");
         setTextMark("");
     }
 
     @Override
-    @SuppressWarnings("squid:S2975")
+    @SuppressWarnings({"squid:S2975", "MethodDoesntCallSuperMethod"})
     @Deprecated
     @Removal(version = "5.0.0")
     public HyperlinkRecord clone() {
index b2290b1913cdb4de9ea802efebe3379929b50cba..80b62f8d8a380532c7dba85b9c903019d703e642 100644 (file)
@@ -19,9 +19,14 @@ package org.apache.poi.hssf.record;
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertNotNull;
 
-import org.apache.poi.hssf.record.HyperlinkRecord.GUID;
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+
+import org.apache.poi.hpsf.ClassID;
+import org.apache.poi.hpsf.ClassIDPredefined;
 import org.apache.poi.util.HexDump;
 import org.apache.poi.util.HexRead;
 import org.apache.poi.util.LittleEndianByteArrayInputStream;
@@ -271,7 +276,7 @@ public final class TestHyperlinkRecord {
     };
 
 
-    private void confirmGUID(GUID expectedGuid, GUID actualGuid) {
+    private void confirmGUID(ClassID expectedGuid, ClassID actualGuid) {
                assertEquals(expectedGuid, actualGuid);
        }
 
@@ -283,8 +288,8 @@ public final class TestHyperlinkRecord {
         assertEquals(2, link.getLastRow());
         assertEquals(0, link.getFirstColumn());
         assertEquals(0, link.getLastColumn());
-        confirmGUID(HyperlinkRecord.STD_MONIKER, link.getGuid());
-        confirmGUID(HyperlinkRecord.URL_MONIKER, link.getMoniker());
+        confirmGUID(ClassIDPredefined.STD_MONIKER.getClassID(), link.getGuid());
+        confirmGUID(ClassIDPredefined.URL_MONIKER.getClassID(), link.getMoniker());
         assertEquals(2, link.getLabelOptions());
         int opts = HyperlinkRecord.HLINK_URL | HyperlinkRecord.HLINK_ABS | HyperlinkRecord.HLINK_LABEL;
         assertEquals(0x17, opts);
@@ -303,8 +308,8 @@ public final class TestHyperlinkRecord {
         assertEquals(0, link.getLastRow());
         assertEquals(0, link.getFirstColumn());
         assertEquals(0, link.getLastColumn());
-        confirmGUID(HyperlinkRecord.STD_MONIKER, link.getGuid());
-        confirmGUID(HyperlinkRecord.FILE_MONIKER, link.getMoniker());
+        confirmGUID(ClassIDPredefined.STD_MONIKER.getClassID(), link.getGuid());
+        confirmGUID(ClassIDPredefined.FILE_MONIKER.getClassID(), link.getMoniker());
         assertEquals(2, link.getLabelOptions());
         int opts = HyperlinkRecord.HLINK_URL | HyperlinkRecord.HLINK_LABEL;
         assertEquals(0x15, opts);
@@ -323,8 +328,8 @@ public final class TestHyperlinkRecord {
         assertEquals(1, link.getLastRow());
         assertEquals(0, link.getFirstColumn());
         assertEquals(0, link.getLastColumn());
-        confirmGUID(HyperlinkRecord.STD_MONIKER, link.getGuid());
-        confirmGUID(HyperlinkRecord.URL_MONIKER, link.getMoniker());
+        confirmGUID(ClassIDPredefined.STD_MONIKER.getClassID(), link.getGuid());
+        confirmGUID(ClassIDPredefined.URL_MONIKER.getClassID(), link.getMoniker());
         assertEquals(2, link.getLabelOptions());
         int opts = HyperlinkRecord.HLINK_URL | HyperlinkRecord.HLINK_ABS | HyperlinkRecord.HLINK_LABEL;
         assertEquals(0x17, opts);
@@ -342,7 +347,7 @@ public final class TestHyperlinkRecord {
         assertEquals(3, link.getLastRow());
         assertEquals(0, link.getFirstColumn());
         assertEquals(0, link.getLastColumn());
-        confirmGUID(HyperlinkRecord.STD_MONIKER, link.getGuid());
+        confirmGUID(ClassIDPredefined.STD_MONIKER.getClassID(), link.getGuid());
         assertEquals(2, link.getLabelOptions());
         int opts = HyperlinkRecord.HLINK_LABEL | HyperlinkRecord.HLINK_PLACE;
         assertEquals(0x1C, opts);
@@ -474,49 +479,47 @@ public final class TestHyperlinkRecord {
                HyperlinkRecord hr = new HyperlinkRecord(in);
                byte[] ser = hr.serialize();
                TestcaseRecordInputStream.confirmRecordEncoding(HyperlinkRecord.sid, dataUNC, ser);
-               try {
-                       hr.toString();
-               } catch (NullPointerException e) {
-                   fail("Identified bug with option URL and UNC set at same time");
-               }
+        assertNotNull(hr.toString());
        }
 
     @Test
-       public void testGUID() {
-               GUID g;
-               g = GUID.parse("3F2504E0-4F89-11D3-9A0C-0305E82C3301");
+       public void testGUID() throws IOException {
+               ClassID g;
+               g = new ClassID("3F2504E0-4F89-11D3-9A0C-0305E82C3301");
                confirmGUID(g, 0x3F2504E0, 0x4F89, 0x11D3, 0x9A0C0305E82C3301L);
-               assertEquals("3F2504E0-4F89-11D3-9A0C-0305E82C3301", g.formatAsString());
+               assertEquals("{3F2504E0-4F89-11D3-9A0C-0305E82C3301}", g.toString());
 
-               g = GUID.parse("13579BDF-0246-8ACE-0123-456789ABCDEF");
+               g = new ClassID("13579BDF-0246-8ACE-0123-456789ABCDEF");
                confirmGUID(g, 0x13579BDF, 0x0246, 0x8ACE, 0x0123456789ABCDEFL);
-               assertEquals("13579BDF-0246-8ACE-0123-456789ABCDEF", g.formatAsString());
+               assertEquals("{13579BDF-0246-8ACE-0123-456789ABCDEF}", g.toString());
 
                byte[] buf = new byte[16];
-               g.serialize(new LittleEndianByteArrayOutputStream(buf, 0));
+               g.write(new LittleEndianByteArrayOutputStream(buf, 0));
                String expectedDump = "[DF, 9B, 57, 13, 46, 02, CE, 8A, 01, 23, 45, 67, 89, AB, CD, EF]";
                assertEquals(expectedDump, HexDump.toHex(buf));
 
                // STD Moniker
                g = createFromStreamDump("[D0, C9, EA, 79, F9, BA, CE, 11, 8C, 82, 00, AA, 00, 4B, A9, 0B]");
-               assertEquals("79EAC9D0-BAF9-11CE-8C82-00AA004BA90B", g.formatAsString());
+               assertEquals("{79EAC9D0-BAF9-11CE-8C82-00AA004BA90B}", g.toString());
                // URL Moniker
                g = createFromStreamDump("[E0, C9, EA, 79, F9, BA, CE, 11, 8C, 82, 00, AA, 00, 4B, A9, 0B]");
-               assertEquals("79EAC9E0-BAF9-11CE-8C82-00AA004BA90B", g.formatAsString());
+               assertEquals("{79EAC9E0-BAF9-11CE-8C82-00AA004BA90B}", g.toString());
                // File Moniker
                g = createFromStreamDump("[03, 03, 00, 00, 00, 00, 00, 00, C0, 00, 00, 00, 00, 00, 00, 46]");
-               assertEquals("00000303-0000-0000-C000-000000000046", g.formatAsString());
+               assertEquals("{00000303-0000-0000-C000-000000000046}", g.toString());
        }
 
-       private static GUID createFromStreamDump(String s) {
-               return new GUID(new LittleEndianByteArrayInputStream(HexRead.readFromString(s)));
+       private static ClassID createFromStreamDump(String s) {
+               return new ClassID(new LittleEndianByteArrayInputStream(HexRead.readFromString(s)));
        }
 
-       private void confirmGUID(GUID g, int d1, int d2, int d3, long d4) {
-               assertEquals(HexDump.intToHex(d1), HexDump.intToHex(g.getD1()));
-               assertEquals(HexDump.shortToHex(d2), HexDump.shortToHex(g.getD2()));
-               assertEquals(HexDump.shortToHex(d3), HexDump.shortToHex(g.getD3()));
-               assertEquals(HexDump.longToHex(d4), HexDump.longToHex(g.getD4()));
+       private void confirmGUID(ClassID g, int d1, int d2, int d3, long d4) throws IOException {
+        try (DataInputStream dis = new DataInputStream(new ByteArrayInputStream(g.getBytes()))) {
+            assertEquals(d1, dis.readInt());
+            assertEquals(d2, dis.readShort() & 0xFFFF);
+            assertEquals(d3, dis.readShort() & 0xFFFF);
+            assertEquals(d4, dis.readLong());
+        }
        }
 
        @Test
@@ -527,8 +530,8 @@ public final class TestHyperlinkRecord {
         assertEquals(2, link.getLastRow());
         assertEquals(0, link.getFirstColumn());
         assertEquals(0, link.getLastColumn());
-        confirmGUID(HyperlinkRecord.STD_MONIKER, link.getGuid());
-        confirmGUID(HyperlinkRecord.URL_MONIKER, link.getMoniker());
+        confirmGUID(ClassIDPredefined.STD_MONIKER.getClassID(), link.getGuid());
+        confirmGUID(ClassIDPredefined.URL_MONIKER.getClassID(), link.getMoniker());
         assertEquals(2, link.getLabelOptions());
         int opts = HyperlinkRecord.HLINK_URL | HyperlinkRecord.HLINK_LABEL;
         assertEquals(opts, link.getLinkOptions());