Your own UUID : UUID GUID « Development Class « Java






Your own UUID

     

/**
 * Copyright (C) 2001-2005 Connected Systems Inc. All rights reserved.
 * This software is the confidential and proprietary information of
 * Connected Systems Inc. ("Confidential Information").
 */
//package biz.evot.util.uuid;

import java.io.Serializable;

public class UUID implements Serializable, Cloneable, Comparable {
  /**
   * 
   */
  private static final long serialVersionUID = 112102158432121213L;

  private final static String kHexChars = "0123456789abcdefABCDEF";

  public final static byte INDEX_CLOCK_HI = 6;

  public final static byte INDEX_CLOCK_MID = 4;

  public final static byte INDEX_CLOCK_LO = 0;

  public final static byte INDEX_TYPE = 6;

  // Clock seq. & variant are multiplexed...
  public final static byte INDEX_CLOCK_SEQUENCE = 8;

  public final static byte INDEX_VARIATION = 8;

  public final static byte TYPE_NULL = 0;

  public final static byte TYPE_TIME_BASED = 1;

  public final static byte TYPE_DCE = 2; // Not

  // used

  public final static byte TYPE_NAME_BASED = 3;

  public final static byte TYPE_RANDOM_BASED = 4;

  /*
   * 'Standard' namespaces defined (suggested) by UUID specs:
   */
  public final static String NAMESPACE_DNS = "6ba7b810-9dad-11d1-80b4-00c04fd430c8";

  public final static String NAMESPACE_URL = "6ba7b811-9dad-11d1-80b4-00c04fd430c8";

  public final static String NAMESPACE_OID = "6ba7b812-9dad-11d1-80b4-00c04fd430c8";

  public final static String NAMESPACE_X500 = "6ba7b814-9dad-11d1-80b4-00c04fd430c8";

  /*
   * By default let's cache desc, can be turned off. For hash code there's no
   * point in turning it off (since the int is already part of the instance
   * memory allocation); if you want to save those 4 bytes (or possibly bit
   * more if alignment is bad) just comment out hash caching.
   */
  private static boolean sDescCaching = true;

  /**
   * The shared null UUID. Would be nice to do lazy instantiation, but if the
   * instance really has to be a singleton, that would mean class-level
   * locking (synchronized getNullUUID()), which would be some overhead... So
   * let's just bite the bullet the first time assuming creation of the null
   * UUID (plus wasted space if it's not needed) can be ignored.
   */
  private final static UUID sNullUUID = new UUID();

  private final byte[] mId = new byte[16];

  // Both string presentation and hash value may be cached...
  private transient String mDesc = null;

  private transient int mHashCode = 0;

  /* *** Object creation: *** */

  /**
   * Default constructor creates a NIL UUID, one that contains all zeroes
   * 
   * Note that the clearing of array is actually unnecessary as JVMs are
   * required to clear up the allocated arrays by default.
   */
  public UUID() {
    /*
     * for (int i = 0; i < 16; ++i) { mId[i] = (byte)0; }
     */
  }

  /**
   * Constructor for cases where you already have the 16-byte binary
   * representation of the UUID (for example if you save UUIDs binary takes
   * less than half of space string representation takes).
   * 
   * @param data
   *            array that contains the binary representation of UUID
   */
  public UUID(byte[] data) {
    /*
     * Could call the other constructor... and/or use System.arraycopy.
     * However, it's likely that those would make this slower to use, and
     * initialization is really simple as is in any case.
     */
    for (int i = 0; i < 16; ++i) {
      mId[i] = data[i];
    }
  }

  /**
   * Constructor for cases where you already have the binary representation of
   * the UUID (for example if you save UUIDs binary takes less than half of
   * space string representation takes) in a byte array
   * 
   * @param data
   *            array that contains the binary representation of UUID
   * @param start
   *            byte offset where UUID starts
   */
  public UUID(byte[] data, int start) {
    for (int i = 0; i < 16; ++i) {
      mId[i] = data[start + i];
    }
  }

  /**
   * Protected constructor used by UUIDGenerator
   * 
   * @param type
   *            UUID type
   * @param data
   *            16 byte UUID contents
   */
  UUID(int type, byte[] data) {
    for (int i = 0; i < 16; ++i) {
      mId[i] = data[i];
    }
    // Type is multiplexed with time_hi:
    mId[INDEX_TYPE] &= (byte) 0x0F;
    mId[INDEX_TYPE] |= (byte) (type << 4);
    // Variant masks first two bits of the clock_seq_hi:
    mId[INDEX_VARIATION] &= (byte) 0x3F;
    mId[INDEX_VARIATION] |= (byte) 0x80;
  }

  /**
   * Constructor for creating UUIDs from the canonical string representation
   * 
   * Note that implementation is optimized for speed, not necessarily code
   * clarity... Also, since what we get might not be 100% canonical (see
   * below), let's not yet populate mDesc here.
   * 
   * @param id
   *            String that contains the canonical representation of the UUID
   *            to build; 36-char string (see UUID specs for details).
   *            Hex-chars may be in upper-case too; UUID class will always
   *            output them in lowercase.
   */
  public UUID(String id) throws NumberFormatException {
    if (id == null) {
      throw new NullPointerException();
    }
    if (id.length() != 36) {
      throw new NumberFormatException(
          "UUID has to be represented by the standard 36-char representation");
    }

    for (int i = 0, j = 0; i < 36; ++j) {
      // Need to bypass hyphens:
      switch (i) {
      case 8:
      case 13:
      case 18:
      case 23:
        if (id.charAt(i) != '-') {
          throw new NumberFormatException(
              "UUID has to be represented by the standard 36-char representation");
        }
        ++i;
      }
      char c = id.charAt(i);

      if (c >= '0' && c <= '9') {
        mId[j] = (byte) ((c - '0') << 4);
      } else if (c >= 'a' && c <= 'f') {
        mId[j] = (byte) ((c - 'a' + 10) << 4);
      } else if (c >= 'A' && c <= 'F') {
        mId[j] = (byte) ((c - 'A' + 10) << 4);
      } else {
        throw new NumberFormatException("Non-hex character '" + c + "'");
      }

      c = id.charAt(++i);

      if (c >= '0' && c <= '9') {
        mId[j] |= (byte) (c - '0');
      } else if (c >= 'a' && c <= 'f') {
        mId[j] |= (byte) (c - 'a' + 10);
      } else if (c >= 'A' && c <= 'F') {
        mId[j] |= (byte) (c - 'A' + 10);
      } else {
        throw new NumberFormatException("Non-hex character '" + c + "'");
      }
      ++i;
    }
  }

  /**
   * Default cloning behaviour (bitwise copy) is just fine...
   * 
   * Could clear out cached string presentation, but there's probably no point
   * in doing that.
   */
  public Object clone() {
    try {
      return super.clone();
    } catch (CloneNotSupportedException e) {
      // shouldn't happen
      return null;
    }
  }

  /* *** Configuration: *** */
  public static void setDescCaching(boolean state) {
    sDescCaching = state;
  }

  /* *** Accessors: *** */

  /**
   * Accessor for getting the shared null UUID
   * 
   * @return the shared null UUID
   */
  public static UUID getNullUUID() {
    return sNullUUID;
  }

  public boolean isNullUUID() {
    // Assuming null uuid is usually used for nulls:
    if (this == sNullUUID) {
      return true;
    }
    // Could also check hash code; null uuid has -1 as hash?
    byte[] data = mId;
    int i = mId.length;
    byte zero = (byte) 0;
    while (--i >= 0) {
      if (data[i] != zero) {
        return false;
      }
    }

    return true;
  }

  /**
   * Returns the UUID type code
   * 
   * @return UUID type
   */
  public int getType() {
    return (mId[INDEX_TYPE] & 0xFF) >> 4;
  }

  /**
   * Returns the UUID as a 16-byte byte array
   * 
   * @return 16-byte byte array that contains UUID bytes in the network byte
   *         order
   */
  public byte[] asByteArray() {
    byte[] result = new byte[16];
    toByteArray(result);
    return result;
  }

  /**
   * Fills in the 16 bytes (from index pos) of the specified byte array with
   * the UUID contents.
   * 
   * @param dst
   *            Byte array to fill
   * @param pos
   *            Offset in the array
   */
  public void toByteArray(byte[] dst, int pos) {
    byte[] src = mId;
    for (int i = 0; i < 16; ++i) {
      dst[pos + i] = src[i];
    }
  }

  public void toByteArray(byte[] dst) {
    toByteArray(dst, 0);
  }

  /**
   * 'Synonym' for 'asByteArray'
   */
  public byte[] toByteArray() {
    return asByteArray();
  }

  /* *** Standard methods from Object overridden: *** */

  /**
   * Could use just the default hash code, but we can probably create a better
   * identity hash (ie. same contents generate same hash) manually, without
   * sacrificing speed too much. Although multiplications with modulos would
   * generate better hashing, let's use just shifts, and do 2 bytes at a time.
   * <p>
   * Of course, assuming UUIDs are randomized enough, even simpler approach
   * might be good enough?
   * <p>
   * Is this a good hash? ... one of these days I better read more about basic
   * hashing techniques I swear!
   */
  private final static int[] kShifts = { 3, 7, 17, 21, 29, 4, 9 };

  public int hashCode() {
    if (mHashCode == 0) {
      // Let's handle first and last byte separately:
      int result = mId[0] & 0xFF;

      result |= (result << 16);
      result |= (result << 8);

      for (int i = 1; i < 15; i += 2) {
        int curr = (mId[i] & 0xFF) << 8 | (mId[i + 1] & 0xFF);
        int shift = kShifts[i >> 1];

        if (shift > 16) {
          result ^= (curr << shift) | (curr >>> (32 - shift));
        } else {
          result ^= (curr << shift);
        }
      }

      // and then the last byte:
      int last = mId[15] & 0xFF;
      result ^= (last << 3);
      result ^= (last << 13);

      result ^= (last << 27);
      // Let's not accept hash 0 as it indicates 'not hashed yet':
      if (result == 0) {
        mHashCode = -1;
      } else {
        mHashCode = result;
      }
    }
    return mHashCode;
  }

  public String toString() {
    /*
     * Could be synchronized, but there isn't much harm in just taking our
     * chances (ie. in the worst case we'll form the string more than
     * once... but result is the same)
     */

    if (mDesc == null) {
      StringBuffer b = new StringBuffer(36);

      for (int i = 0; i < 16; ++i) {
        // Need to bypass hyphens:
        switch (i) {
        case 4:
        case 6:
        case 8:
        case 10:
          b.append('-');
        }
        int hex = mId[i] & 0xFF;
        b.append(kHexChars.charAt(hex >> 4));
        b.append(kHexChars.charAt(hex & 0x0f));
      }
      if (!sDescCaching) {
        return b.toString();
      }
      mDesc = b.toString();
    }
    return mDesc;
  }

  /* *** Comparison methods: *** */

  private final static int[] sTimeCompare = new int[] { INDEX_CLOCK_HI, INDEX_CLOCK_HI + 1,
      INDEX_CLOCK_MID, INDEX_CLOCK_MID + 1, INDEX_CLOCK_LO, INDEX_CLOCK_LO + 1, INDEX_CLOCK_LO + 2,
      INDEX_CLOCK_LO + 3, };

  /**
   * Let's also make UUIDs sortable. This will mostly/only be useful with
   * time-based UUIDs; they will sorted by time of creation. The order will be
   * strictly correct with UUIDs produced over one JVM's lifetime; that is, if
   * more than one JVMs create UUIDs and/or system is rebooted the order may
   * not be 100% accurate between UUIDs created under different JVMs.
   * 
   * For all UUIDs, type is first compared, and UUIDs of different types are
   * sorted together (ie. null UUID is before all other UUIDs, then time-based
   * UUIDs etc). If types are the same, time-based UUIDs' time stamps
   * (including additional clock counter) are compared, so UUIDs created first
   * are ordered first. For all other types (and for time-based UUIDs with
   * same time stamp, which should only occur when comparing a UUID with
   * itself, or with UUIDs created on different JVMs or external systems)
   * binary comparison is done over all 16 bytes.
   * 
   * @param o
   *            Object to compare this UUID to; should be a UUID
   * 
   * @return -1 if this UUID should be ordered before the one passed, 1 if
   *         after, and 0 if they are the same
   * 
   * @throws ClassCastException
   *             if o is not a UUID.
   */
  public int compareTo(Object o) {
    UUID other = (UUID) o;

    int thisType = getType();
    int thatType = other.getType();

    /*
     * Let's first order by type:
     */
    if (thisType > thatType) {
      return 1;
    } else if (thisType < thatType) {
      return -1;
    }

    /*
     * And for time-based UUIDs let's compare time stamps first, then the
     * rest... For all other types, we'll just do straight byte-by-byte
     * comparison.
     */
    byte[] thisId = mId;
    byte[] thatId = other.mId;
    int i = 0;
    if (thisType == TYPE_TIME_BASED) {
      for (; i < 8; ++i) {
        int index = sTimeCompare[i];
        int cmp = (((int) thisId[index]) & 0xFF) - (((int) thatId[index]) & 0xFF);
        if (cmp != 0) {
          return cmp;
        }
      }
      // Let's fall down to full comparison otherwise
    }

    for (; i < 16; ++i) {
      int cmp = (((int) thisId[i]) & 0xFF) - (((int) thatId[i]) & 0xFF);
      if (cmp != 0) {
        return cmp;
      }
    }

    return 0;
  }

  /**
   * Checking equality of UUIDs is easy; just compare the 128-bit number.
   */
  public boolean equals(Object o) {
    if (!(o instanceof UUID)) {
      return false;
    }
    byte[] otherId = ((UUID) o).mId;
    byte[] thisId = mId;
    for (int i = 0; i < 16; ++i) {
      if (otherId[i] != thisId[i]) {
        return false;
      }
    }
    return true;
  }

  /**
   * Constructs a new UUID instance given the canonical string representation
   * of an UUID.
   * 
   * Note that calling this method returns the same result as would using the
   * matching (1 string arg) constructor.
   * 
   * @param id
   *            Canonical string representation used for constructing an UUID
   *            instance
   * 
   * @throws NumberFormatException
   *             if 'id' is invalid UUID
   */
  public static UUID valueOf(String id) throws NumberFormatException {
    return new UUID(id);
  }

  /**
   * Constructs a new UUID instance given a byte array that contains the (16
   * byte) binary representation.
   * 
   * Note that calling this method returns the same result as would using the
   * matching constructor
   * 
   * @param src
   *            Byte array that contains the UUID definition
   * @param start
   *            Offset in the array where the UUID starts
   */
  public static UUID valueOf(byte[] src, int start) {
    return new UUID(src, start);
  }

  /**
   * Constructs a new UUID instance given a byte array that contains the (16
   * byte) binary representation.
   * 
   * Note that calling this method returns the same result as would using the
   * matching constructor
   * 
   * @param src
   *            Byte array that contains the UUID definition
   */
  public static UUID valueOf(byte[] src) {
    return new UUID(src);
  }

  public static void main(String[] args) {
  }
}

   
    
    
    
    
  








Related examples in the same category

1.Random GUID
2.Algorithm for generating Random GUID
3.Get a unique identifier Using java.rmi.dgc.VMID
4.Using java.util.UUID
5.Create your own basic UUID
6.Session ID generator
7.UUID generator from Sun Microsystems
8.UUID generator from http://www1.ics.uci.edu
9.Using java.util.concurrent.AtomicLong: A numerical id, start at zero and increment by one.
10.A 32 byte GUID generator
11.A unique identifier
12.Generate pseudo-GUID sequences
13.Generates a UUID
14.Generates random UUIDs
15.Generator for Globally unique Strings
16.ID generator
17.Simple Id Generator
18.UUID generation
19.UUID generator of 32 bytes long values
20.Simple Long Id Generator
21.Long Sequence Generator
22.UUID generator
23.Thread-safe version of the Axiom UUIDGenerator
24.Convert an array of bytes into a List of Strings using UTF-8.
25.Your own UUID 2
26.Create GUIDs according to the principles at http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt.
27.Get Unique Id