ASTERIXDB-1271: Revisit UUID Implementation

- Updated UUID implementation to eliminate marshalling to/from a pair
  of longs, replacing with byte [].
- Eliminate all but one call to SecureRandom at init time, avoid risk
  of entropy exhaustion
- Fix exceptions thrown
- Incorporate constant to represent number of bytes, String chars in
  an instance of AUUID
- Split generated from parsed AUUID
- Eliminate intermediate StringBuilder construction on priting paths,
  optimize imports

Change-Id: I9e90d42f6b62f80ad180dbd0c8c852db85b14173
Reviewed-on: https://asterix-gerrit.ics.uci.edu/610
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: abdullah alamoudi <bamousaa@gmail.com>
Reviewed-by: Till Westmann <tillw@apache.org>
diff --git a/asterix-external-data/src/main/java/org/apache/asterix/external/parser/ADMDataParser.java b/asterix-external-data/src/main/java/org/apache/asterix/external/parser/ADMDataParser.java
index 0fe2758..93aa18b 100644
--- a/asterix-external-data/src/main/java/org/apache/asterix/external/parser/ADMDataParser.java
+++ b/asterix-external-data/src/main/java/org/apache/asterix/external/parser/ADMDataParser.java
@@ -55,7 +55,6 @@
 import org.apache.asterix.om.util.container.IObjectPool;
 import org.apache.asterix.om.util.container.ListObjectPool;
 import org.apache.asterix.runtime.operators.file.adm.AdmLexer;
-import org.apache.asterix.runtime.operators.file.adm.AdmLexerException;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
 import org.apache.hyracks.data.std.api.IMutableValueStorage;
 import org.apache.hyracks.data.std.util.ArrayBackedValueStorage;
@@ -296,7 +295,7 @@
                     // Dealing with UUID type that is represented by a string
                     final String tokenImage = admLexer.getLastTokenImage().substring(1,
                             admLexer.getLastTokenImage().length() - 1);
-                    aUUID.fromStringToAMuatbleUUID(tokenImage);
+                    aUUID.parseUUIDString(tokenImage);
                     uuidSerde.serialize(aUUID, out);
                 } else {
                     throw new ParseException(mismatchErrorMessage + objectType.getTypeName());
@@ -1023,7 +1022,7 @@
                 APolygonSerializerDeserializer.parse(unquoted, out);
                 return true;
             case UUID:
-                aUUID.fromStringToAMuatbleUUID(unquoted);
+                aUUID.parseUUIDString(unquoted);
                 uuidSerde.serialize(aUUID, out);
                 return true;
             default:
diff --git a/asterix-external-data/src/main/java/org/apache/asterix/external/parser/AbstractDataParser.java b/asterix-external-data/src/main/java/org/apache/asterix/external/parser/AbstractDataParser.java
index b10b9e9..cfd1b9c 100644
--- a/asterix-external-data/src/main/java/org/apache/asterix/external/parser/AbstractDataParser.java
+++ b/asterix-external-data/src/main/java/org/apache/asterix/external/parser/AbstractDataParser.java
@@ -92,7 +92,7 @@
     protected AMutableString aString = new AMutableString("");
     protected AMutableBinary aBinary = new AMutableBinary(null, 0, 0);
     protected AMutableString aStringFieldName = new AMutableString("");
-    protected AMutableUUID aUUID = new AMutableUUID(0, 0);
+    protected AMutableUUID aUUID = new AMutableUUID();
     // For temporal and spatial data types
     protected AMutableTime aTime = new AMutableTime(0);
     protected AMutableDateTime aDateTime = new AMutableDateTime(0L);
@@ -145,7 +145,7 @@
 
     // For UUID, we assume that the format is the string representation of UUID
     // (xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx) when parsing the data.
-    // Thus, we need to call UUID.fromStringToAMuatbleUUID() to convert it to the internal representation (two long values).
+    // Thus, we need to call UUID.fromStringToAMutableUUID() to convert it to the internal representation (byte []).
     @SuppressWarnings("unchecked")
     protected ISerializerDeserializer<AUUID> uuidSerde = AqlSerializerDeserializerProvider.INSTANCE
             .getSerializerDeserializer(BuiltinType.AUUID);
diff --git a/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/adm/AUUIDPrinter.java b/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/adm/AUUIDPrinter.java
index 86cb7ac..539b49c 100644
--- a/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/adm/AUUIDPrinter.java
+++ b/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/adm/AUUIDPrinter.java
@@ -24,7 +24,6 @@
 import org.apache.asterix.om.base.AUUID;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 import org.apache.hyracks.algebricks.data.IPrinter;
-import org.apache.hyracks.data.std.primitive.LongPointable;
 
 public class AUUIDPrinter implements IPrinter {
 
@@ -36,10 +35,10 @@
 
     @Override
     public void print(byte[] b, int s, int l, PrintStream ps) throws AlgebricksException {
-        long msb = LongPointable.getLong(b, s + 1);
-        long lsb = LongPointable.getLong(b, s + 9);
-
-        ps.print("uuid(\"" + AUUID.toStringLiteralOnly(msb, lsb) + "\")");
+        StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 8);
+        buf.append("uuid(\"");
+        AUUID.appendLiteralOnly(b, s + 1, buf).append("\")");
+        ps.print(buf.toString());
     }
 
 }
diff --git a/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/AUUIDPrinter.java b/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/AUUIDPrinter.java
index 967131f..89f5e31 100644
--- a/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/AUUIDPrinter.java
+++ b/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/AUUIDPrinter.java
@@ -24,7 +24,6 @@
 import org.apache.asterix.om.base.AUUID;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 import org.apache.hyracks.algebricks.data.IPrinter;
-import org.apache.hyracks.data.std.primitive.LongPointable;
 
 public class AUUIDPrinter implements IPrinter {
 
@@ -36,10 +35,10 @@
 
     @Override
     public void print(byte[] b, int s, int l, PrintStream ps) throws AlgebricksException {
-        long msb = LongPointable.getLong(b, s + 1);
-        long lsb = LongPointable.getLong(b, s + 9);
-
-        ps.print("\"" + AUUID.toStringLiteralOnly(msb, lsb) + "\"");
+        StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 2);
+        buf.append('"');
+        AUUID.appendLiteralOnly(b, s + 1, buf).append('"');
+        ps.print(buf.toString());
     }
 
 }
diff --git a/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinter.java b/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinter.java
index 20b87c2..2a59fe4 100644
--- a/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinter.java
+++ b/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinter.java
@@ -24,7 +24,6 @@
 import org.apache.asterix.om.base.AUUID;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 import org.apache.hyracks.algebricks.data.IPrinter;
-import org.apache.hyracks.data.std.primitive.LongPointable;
 
 public class AUUIDPrinter implements IPrinter {
 
@@ -36,10 +35,10 @@
 
     @Override
     public void print(byte[] b, int s, int l, PrintStream ps) throws AlgebricksException {
-        long msb = LongPointable.getLong(b, s + 1);
-        long lsb = LongPointable.getLong(b, s + 9);
-
-        ps.print("\"" + AUUID.toStringLiteralOnly(msb, lsb) + "\"");
+        StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 2);
+        buf.append('"');
+        AUUID.appendLiteralOnly(b, s + 1, buf).append('"');
+        ps.print(buf.toString());
     }
 
 }
diff --git a/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/lossless/AUUIDPrinter.java b/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/lossless/AUUIDPrinter.java
index f21cdff..c36de3a 100644
--- a/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/lossless/AUUIDPrinter.java
+++ b/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/lossless/AUUIDPrinter.java
@@ -24,7 +24,6 @@
 import org.apache.asterix.om.base.AUUID;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 import org.apache.hyracks.algebricks.data.IPrinter;
-import org.apache.hyracks.data.std.primitive.LongPointable;
 
 public class AUUIDPrinter implements IPrinter {
 
@@ -36,10 +35,10 @@
 
     @Override
     public void print(byte[] b, int s, int l, PrintStream ps) throws AlgebricksException {
-        long msb = LongPointable.getLong(b, s + 1);
-        long lsb = LongPointable.getLong(b, s + 9);
-
-        ps.print("\"" + AUUID.toStringLiteralOnly(msb, lsb) + "\"");
+        StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 2);
+        buf.append('"');
+        AUUID.appendLiteralOnly(b, s + 1, buf).append('"');
+        ps.print(buf.toString());
     }
 
 }
diff --git a/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/serde/AUUIDSerializerDeserializer.java b/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/serde/AUUIDSerializerDeserializer.java
index 8df0b0d..9ed398e 100644
--- a/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/serde/AUUIDSerializerDeserializer.java
+++ b/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/serde/AUUIDSerializerDeserializer.java
@@ -21,12 +21,10 @@
 
 import java.io.DataInput;
 import java.io.DataOutput;
-import java.io.IOException;
 
 import org.apache.asterix.om.base.AUUID;
 import org.apache.hyracks.api.dataflow.value.ISerializerDeserializer;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
-import org.apache.hyracks.dataflow.common.data.marshalling.Integer64SerializerDeserializer;
 
 public class AUUIDSerializerDeserializer implements ISerializerDeserializer<AUUID> {
 
@@ -39,20 +37,12 @@
 
     @Override
     public AUUID deserialize(DataInput in) throws HyracksDataException {
-        long msb = Integer64SerializerDeserializer.INSTANCE.deserialize(in);
-        long lsb = Integer64SerializerDeserializer.INSTANCE.deserialize(in);
-        // for each deserialization, a new object is created. maybe we should change this.
-        return new AUUID(msb, lsb);
+        return AUUID.readFrom(in);
     }
 
     @Override
     public void serialize(AUUID instance, DataOutput out) throws HyracksDataException {
-        try {
-            Integer64SerializerDeserializer.INSTANCE.serialize(instance.getMostSignificantBits(), out);
-            Integer64SerializerDeserializer.INSTANCE.serialize(instance.getLeastSignificantBits(), out);
-        } catch (IOException e) {
-            throw new HyracksDataException(e);
-        }
+        instance.writeTo(out);
     }
 
 }
diff --git a/asterix-om/src/main/java/org/apache/asterix/om/base/AGeneratedUUID.java b/asterix-om/src/main/java/org/apache/asterix/om/base/AGeneratedUUID.java
new file mode 100644
index 0000000..da1b35b
--- /dev/null
+++ b/asterix-om/src/main/java/org/apache/asterix/om/base/AGeneratedUUID.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.asterix.om.base;
+
+import java.security.SecureRandom;
+import java.util.Random;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class AGeneratedUUID extends AUUID {
+
+    private static class Holder {
+        static final byte [] hostUnique = new byte[4];
+
+        static {
+            new SecureRandom().nextBytes(hostUnique);
+       }
+    }
+    static final Random random = new Random();
+    static final AtomicInteger nextInstance = new AtomicInteger(random.nextInt());
+
+    public AGeneratedUUID() {
+        int unique = nextInstance.getAndIncrement();
+
+        // fill with pseudo-random bytes
+        random.nextBytes(uuidBytes);
+
+        // overwrite the first four bytes with the host unique value
+        System.arraycopy(Holder.hostUnique, 0, uuidBytes, 0, 4);
+
+        // overwrite the next four bytes with the thread unique value
+        uuidBytes[5] = (byte)(unique >> 24);
+        uuidBytes[6] = (byte)(unique >> 16);
+        uuidBytes[7] = (byte)(unique >> 8);
+        uuidBytes[8] = (byte)unique;
+    }
+
+    public void nextUUID() {
+        // increment the UUID value
+        for (int i = UUID_BYTES - 1; i >= 8; i--) {
+            if (++uuidBytes[i] != 0) {
+                break;
+            }
+        }
+    }
+}
diff --git a/asterix-om/src/main/java/org/apache/asterix/om/base/AMutableUUID.java b/asterix-om/src/main/java/org/apache/asterix/om/base/AMutableUUID.java
index 48946de..c9e581c 100644
--- a/asterix-om/src/main/java/org/apache/asterix/om/base/AMutableUUID.java
+++ b/asterix-om/src/main/java/org/apache/asterix/om/base/AMutableUUID.java
@@ -19,46 +19,107 @@
 
 package org.apache.asterix.om.base;
 
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+
 public class AMutableUUID extends AUUID {
-    private final long[] uuidBits;
-    private final byte[] randomBytes;
 
-    public AMutableUUID(long msb, long lsb) {
-        super(msb, lsb);
-        randomBytes = new byte[16];
-        uuidBits = new long[2];
+    public void parseUUIDString(String tokenImage) throws HyracksDataException {
+        if (tokenImage.length() != UUID_CHARS) {
+            throw new HyracksDataException("This is not a correct UUID value: " + tokenImage);
+        }
+        byte [] hexBytes = new byte[UUID_CHARS];
+        for (int i = 0; i < tokenImage.length(); i++) {
+            hexBytes[i] = (byte)tokenImage.charAt(i);
+        }
+        parseUUIDHexBytes(hexBytes, 0);
     }
 
-    public void nextUUID() {
-        Holder.srnd.nextBytes(randomBytes);
-        uuidBitsFromBytes(uuidBits, randomBytes);
-        msb = uuidBits[0];
-        lsb = uuidBits[1];
+    public void parseUUIDHexBytes(byte[] serString, int offset) throws HyracksDataException {
+        // First part - 8 bytes
+        decodeBytesFromHex(serString, offset, uuidBytes, 0, 8);
+        offset += 8;
+
+        // Skip the hyphen part
+        offset += 1;
+
+        // Second part - 4 bytes
+        decodeBytesFromHex(serString, offset, uuidBytes, 4, 4);
+        offset += 4;
+
+        // Skip the hyphen part
+        offset += 1;
+
+        // Third part - 4 bytes
+        decodeBytesFromHex(serString, offset, uuidBytes, 6, 4);
+        offset += 4;
+
+        // Skip the hyphen part
+        offset += 1;
+
+        // Fourth part - 4 bytes
+        decodeBytesFromHex(serString, offset, uuidBytes, 8, 4);
+        offset += 4;
+
+        // Skip the hyphen part
+        offset += 1;
+
+        // The last part - 12 bytes
+        decodeBytesFromHex(serString, offset, uuidBytes, 10, 12);
     }
 
-    // Set the most significant bits and the least significant bits.
-    public void setValue(long msb, long lsb) {
-        this.msb = msb;
-        this.lsb = lsb;
+    // Calculate a long value from a hex string.
+    private static void decodeBytesFromHex(byte[] hexArray, int hexArrayOffset, byte[] outputArray, int outputOffset, int length)
+            throws HyracksDataException {
+        for (int i = hexArrayOffset; i < hexArrayOffset + length; ) {
+            int hi = transformHexCharToInt(hexArray[i++]);
+            outputArray[outputOffset++] = (byte) (hi << 4 | transformHexCharToInt(hexArray[i++]));
+        }
     }
 
-    // Since AUUID is a wrapper of java.util.uuid,
-    // we can use the same method that creates a UUID from a String.
-    public void fromStringToAMuatbleUUID(String value) {
-        String[] components = value.split("-");
-        if (components.length != 5)
-            throw new IllegalArgumentException("Invalid UUID string: " + value);
-        for (int i = 0; i < 5; i++)
-            components[i] = "0x" + components[i];
-
-        msb = Long.decode(components[0]).longValue();
-        msb <<= 16;
-        msb |= Long.decode(components[1]).longValue();
-        msb <<= 16;
-        msb |= Long.decode(components[2]).longValue();
-
-        lsb = Long.decode(components[3]).longValue();
-        lsb <<= 48;
-        lsb |= Long.decode(components[4]).longValue();
+    // Interpret a character to the corresponding integer value.
+    private static int transformHexCharToInt(byte val) throws HyracksDataException {
+        switch (val) {
+            case '0':
+                return 0;
+            case '1':
+                return 1;
+            case '2':
+                return 2;
+            case '3':
+                return 3;
+            case '4':
+                return 4;
+            case '5':
+                return 5;
+            case '6':
+                return 6;
+            case '7':
+                return 7;
+            case '8':
+                return 8;
+            case '9':
+                return 9;
+            case 'a':
+            case 'A':
+                return 10;
+            case 'b':
+            case 'B':
+                return 11;
+            case 'c':
+            case 'C':
+                return 12;
+            case 'd':
+            case 'D':
+                return 13;
+            case 'e':
+            case 'E':
+                return 14;
+            case 'f':
+            case 'F':
+                return 15;
+            default:
+                throw new HyracksDataException("This is not a correct UUID value.");
+        }
     }
+
 }
diff --git a/asterix-om/src/main/java/org/apache/asterix/om/base/AUUID.java b/asterix-om/src/main/java/org/apache/asterix/om/base/AUUID.java
index bb54988..329ae53 100644
--- a/asterix-om/src/main/java/org/apache/asterix/om/base/AUUID.java
+++ b/asterix-om/src/main/java/org/apache/asterix/om/base/AUUID.java
@@ -19,85 +19,42 @@
 
 package org.apache.asterix.om.base;
 
-import java.security.SecureRandom;
-import java.util.UUID;
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.Arrays;
 
 import org.apache.asterix.common.exceptions.AsterixException;
 import org.apache.asterix.om.types.BuiltinType;
 import org.apache.asterix.om.types.IAType;
 import org.apache.asterix.om.visitors.IOMVisitor;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
 import org.json.JSONException;
 import org.json.JSONObject;
 
 public class AUUID implements IAObject {
 
-    protected static class Holder {
-        static final SecureRandom srnd = new SecureRandom();
-    }
+    public static final int UUID_CHARS = 36;
+    public static final int UUID_BYTES = 16;
 
-    protected long msb;
-    protected long lsb;
+    protected final byte [] uuidBytes;
 
-    public AUUID(UUID uuid) {
-        msb = uuid.getMostSignificantBits();
-        lsb = uuid.getLeastSignificantBits();
-    }
+    protected static final char [] CHARS;
 
-    public AUUID(long msb, long lsb) {
-        this.msb = msb;
-        this.lsb = lsb;
-    }
 
-    public long getMostSignificantBits() {
-        return msb;
-    }
-
-    public long getLeastSignificantBits() {
-        return lsb;
-    }
-
-    public static AUUID randomUUID() {
-        long[] bits = new long[2];
-        byte[] randomBytes = new byte[16];
-        Holder.srnd.nextBytes(randomBytes);
-        uuidBitsFromBytes(bits, randomBytes);
-        return new AUUID(bits[0], bits[1]);
-    }
-
-    public void generateNextRandomUUID() {
-        byte[] randomBytes = new byte[16];
-        Holder.srnd.nextBytes(randomBytes);
-        uuidBitsFromBytes(randomBytes);
-    }
-
-    protected void uuidBitsFromBytes(byte[] randomBytes) {
-        this.msb = 0;
-        this.lsb = 0;
-        randomBytes[6] &= 0x0f; /* clear version        */
-        randomBytes[6] |= 0x40; /* set to version 4     */
-        randomBytes[8] &= 0x3f; /* clear variant        */
-        randomBytes[8] |= 0x80; /* set to IETF variant  */
-        for (int i = 0; i < 8; ++i) {
-            this.msb = (this.msb << 8) | (randomBytes[i] & 0xff);
-        }
-        for (int i = 8; i < 16; ++i) {
-            this.lsb = (this.lsb << 8) | (randomBytes[i] & 0xff);
+    static {
+        CHARS = new char [16];
+        for (int i = 0; i < 16; i++) {
+            CHARS[i] = Character.forDigit(i, 16);
         }
     }
 
-    protected static void uuidBitsFromBytes(long[] bits, byte[] randomBytes) {
-        bits[0] = 0;
-        bits[1] = 0;
-        randomBytes[6] &= 0x0f; /* clear version        */
-        randomBytes[6] |= 0x40; /* set to version 4     */
-        randomBytes[8] &= 0x3f; /* clear variant        */
-        randomBytes[8] |= 0x80; /* set to IETF variant  */
-        for (int i = 0; i < 8; ++i) {
-            bits[0] = (bits[0] << 8) | (randomBytes[i] & 0xff);
-        }
-        for (int i = 8; i < 16; ++i) {
-            bits[1] = (bits[1] << 8) | (randomBytes[i] & 0xff);
-        }
+    protected AUUID() {
+        this(new byte[UUID_BYTES]);
+    }
+
+    public AUUID(byte [] bytes) {
+        this.uuidBytes = bytes;
     }
 
     @Override
@@ -123,55 +80,57 @@
             return false;
         }
         AUUID oUUID = (AUUID) obj;
-        return oUUID.msb == this.msb && oUUID.lsb == this.lsb;
+        return Arrays.equals(oUUID.uuidBytes, this.uuidBytes);
     }
 
     @Override
     public int hash() {
-        long hilo = msb ^ lsb;
-        return ((int) (hilo >> 32)) ^ (int) hilo;
+        return Arrays.hashCode(uuidBytes);
     }
 
     @Override
     public String toString() {
-        return "AUUID: {" + toStringLiteralOnly(msb, lsb) + "}";
-
+        StringBuilder buf = new StringBuilder(UUID_CHARS + 9);
+        buf.append("AUUID: {");
+        return appendLiteralOnly(buf).append('}').toString();
     }
 
-    public String toStringLiteralOnly() {
-        return toStringLiteralOnly(msb, lsb);
+    public StringBuilder appendLiteralOnly(StringBuilder buf) {
+        return appendLiteralOnly(uuidBytes, 0, buf);
     }
 
-    public static String toStringLiteralOnly(long msbValue, long lsbValue) {
-        return digits(msbValue >> 32, 8) + "-" + digits(msbValue >> 16, 4) + "-" + digits(msbValue, 4) + "-"
-                + digits(lsbValue >> 48, 4) + "-" + digits(lsbValue, 12);
-
+    private static StringBuilder digits(byte b [], int offset, int count, StringBuilder result) {
+        for (int i = 0; i < count; i++) {
+            result.append(CHARS[(b[offset + i] >> 4) & 0xf]);
+            result.append(CHARS[b[offset + i] & 0xf]);
+        }
+        return result;
     }
 
-    // Since AUUID is a wrapper of java.util.uuid,
-    // we can use the same method that creates a UUID from a String.
-    public static AUUID fromString(String name) {
-        String[] components = name.split("-");
-        if (components.length != 5)
-            throw new IllegalArgumentException("Invalid UUID string: " + name);
-        for (int i = 0; i < 5; i++)
-            components[i] = "0x" + components[i];
-
-        long msb = Long.decode(components[0]).longValue();
-        msb <<= 16;
-        msb |= Long.decode(components[1]).longValue();
-        msb <<= 16;
-        msb |= Long.decode(components[2]).longValue();
-
-        long lsb = Long.decode(components[3]).longValue();
-        lsb <<= 48;
-        lsb |= Long.decode(components[4]).longValue();
-
-        return new AUUID(msb, lsb);
+    public static StringBuilder appendLiteralOnly(byte [] bytes, int offset, StringBuilder result) {
+        digits(bytes, offset, 4, result).append('-');
+        digits(bytes, offset + 4, 2, result).append('-');
+        digits(bytes, offset + 6, 2, result).append('-');
+        digits(bytes, offset + 8, 2, result).append('-');
+        return digits(bytes, offset + 10, 6, result);
     }
 
-    private static String digits(long val, int digits) {
-        long hi = 1L << (digits * 4);
-        return Long.toHexString(hi | (val & (hi - 1))).substring(1);
+    public void writeTo(DataOutput out) throws HyracksDataException {
+        try {
+            out.write(uuidBytes);
+        } catch (IOException e) {
+            throw new HyracksDataException(e);
+        }
     }
+
+    public static AUUID readFrom(DataInput in) throws HyracksDataException {
+        AUUID instance = new AUUID();
+        try {
+            in.readFully(instance.uuidBytes);
+        } catch (IOException e) {
+            throw new HyracksDataException(e);
+        }
+        return instance;
+    }
+
 }
diff --git a/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AUUIDFromStringConstructorDescriptor.java b/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AUUIDFromStringConstructorDescriptor.java
index c7168c4..b5caf18 100644
--- a/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AUUIDFromStringConstructorDescriptor.java
+++ b/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AUUIDFromStringConstructorDescriptor.java
@@ -69,16 +69,15 @@
                     private ArrayBackedValueStorage outInput = new ArrayBackedValueStorage();
                     private ICopyEvaluator eval = args[0].createEvaluator(outInput);
                     private String errorMessage = "This can not be an instance of UUID";
-                    private AMutableUUID aUUID = new AMutableUUID(0, 0);
+                    private AMutableUUID uuid = new AMutableUUID();
                     @SuppressWarnings("unchecked")
                     private ISerializerDeserializer<AUUID> uuidSerde = AqlSerializerDeserializerProvider.INSTANCE
                             .getSerializerDeserializer(BuiltinType.AUUID);
                     @SuppressWarnings("unchecked")
                     private ISerializerDeserializer<ANull> nullSerde = AqlSerializerDeserializerProvider.INSTANCE
                             .getSerializerDeserializer(BuiltinType.ANULL);
-                    private long msb = 0;
-                    private long lsb = 0;
-                    private long tmpLongValue = 0;
+
+
 
                     private final UTF8StringPointable utf8Ptr = new UTF8StringPointable();
 
@@ -90,51 +89,12 @@
                             byte[] serString = outInput.getByteArray();
                             if (serString[0] == ATypeTag.SERIALIZED_STRING_TYPE_TAG) {
                                 utf8Ptr.set(serString, 1, outInput.getLength() - 1);
-                                msb = 0;
-                                lsb = 0;
-                                tmpLongValue = 0;
 
                                 // first byte: tag, next x bytes: length
                                 int offset = utf8Ptr.getCharStartOffset();
-                                // First part - 8 bytes
-                                msb = calculateLongFromHex(serString, offset, 8);
-                                msb <<= 16;
-                                offset += 8;
 
-                                // Skip the hyphen part
-                                offset += 1;
-
-                                // Second part - 4 bytes
-                                tmpLongValue = calculateLongFromHex(serString, offset, 4);
-                                msb |= tmpLongValue;
-                                msb <<= 16;
-                                offset += 4;
-
-                                // Skip the hyphen part
-                                offset += 1;
-
-                                // Third part - 4 bytes
-                                tmpLongValue = calculateLongFromHex(serString, offset, 4);
-                                msb |= tmpLongValue;
-                                offset += 4;
-
-                                // Skip the hyphen part
-                                offset += 1;
-
-                                // Fourth part - 4 bytes
-                                lsb = calculateLongFromHex(serString, offset, 4);
-                                lsb <<= 48;
-                                offset += 4;
-
-                                // Skip the hyphen part
-                                offset += 1;
-
-                                // The last part - 12 bytes
-                                tmpLongValue = calculateLongFromHex(serString, offset, 12);
-                                lsb |= tmpLongValue;
-
-                                aUUID.setValue(msb, lsb);
-                                uuidSerde.serialize(aUUID, out);
+                                uuid.parseUUIDHexBytes(serString, offset);
+                                uuidSerde.serialize(uuid, out);
 
                             } else if (serString[0] == ATypeTag.SERIALIZED_NULL_TYPE_TAG)
                                 nullSerde.serialize(ANull.NULL, out);
@@ -145,70 +105,6 @@
                         }
                     }
 
-                    // Calculate a long value from a hex string.
-                    private long calculateLongFromHex(byte[] hexArray, int offset, int length)
-                            throws AlgebricksException {
-                        int tmpIntVal = 0;
-                        long tmpLongVal = 0;
-                        for (int i = offset; i < offset + length; i++) {
-                            tmpIntVal = transformHexCharToInt(hexArray[i]);
-                            if (tmpIntVal != -1) {
-                                tmpLongVal = tmpLongVal * 16 + tmpIntVal;
-                            } else {
-                                throw new AlgebricksException("This is not a correct UUID value.");
-                            }
-                        }
-                        return tmpLongVal;
-                    }
-
-                    // Interpret a character to the corresponding integer value.
-                    private int transformHexCharToInt(byte val) throws AlgebricksException {
-                        switch (val) {
-                            case '0':
-                                return 0;
-                            case '1':
-                                return 1;
-                            case '2':
-                                return 2;
-                            case '3':
-                                return 3;
-                            case '4':
-                                return 4;
-                            case '5':
-                                return 5;
-                            case '6':
-                                return 6;
-                            case '7':
-                                return 7;
-                            case '8':
-                                return 8;
-                            case '9':
-                                return 9;
-                            case 'a':
-                            case 'A':
-                                return 10;
-                            case 'b':
-                            case 'B':
-                                return 11;
-                            case 'c':
-                            case 'C':
-                                return 12;
-                            case 'd':
-                            case 'D':
-                                return 13;
-                            case 'e':
-                            case 'E':
-                                return 14;
-                            case 'f':
-                            case 'F':
-                                return 15;
-                            case '-':
-                                // We need to skip this hyphen part.
-                                return -1;
-                            default:
-                                throw new AlgebricksException("This is not a correct UUID value.");
-                        }
-                    }
                 };
             }
         };
diff --git a/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CreateUUIDDescriptor.java b/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CreateUUIDDescriptor.java
index 587581e..be2f700 100644
--- a/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CreateUUIDDescriptor.java
+++ b/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CreateUUIDDescriptor.java
@@ -19,7 +19,7 @@
 package org.apache.asterix.runtime.evaluators.functions;
 
 import org.apache.asterix.formats.nontagged.AqlSerializerDeserializerProvider;
-import org.apache.asterix.om.base.AMutableUUID;
+import org.apache.asterix.om.base.AGeneratedUUID;
 import org.apache.asterix.om.base.AUUID;
 import org.apache.asterix.om.functions.AsterixBuiltinFunctions;
 import org.apache.asterix.om.functions.IFunctionDescriptor;
@@ -58,7 +58,7 @@
             @Override
             public ICopyEvaluator createEvaluator(final IDataOutputProvider output) throws AlgebricksException {
                 return new ICopyEvaluator() {
-                    final AMutableUUID uuid = new AMutableUUID(0, 0);
+                    final AGeneratedUUID uuid = new AGeneratedUUID();
 
                     @Override
                     public void evaluate(IFrameTupleReference tuple) throws AlgebricksException {