001: /*
002: * Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0
003: * (http://h2database.com/html/license.html).
004: * Initial Developer: H2 Group
005: */
006: package org.h2.value;
007:
008: import java.sql.PreparedStatement;
009: import java.sql.SQLException;
010:
011: import org.h2.util.ByteUtils;
012: import org.h2.util.RandomUtils;
013: import org.h2.util.StringUtils;
014:
015: /**
016: * Implementation of the UUID data type.
017: */
018: public class ValueUuid extends Value {
019: // number of bytes
020: public static final int PRECISION = 16;
021:
022: // cd38d882-7ada-4589-b5fb-7da0ca559d9a
023: public static final int DISPLAY_SIZE = 36;
024:
025: private final long high, low;
026:
027: private ValueUuid(long high, long low) {
028: this .high = high;
029: this .low = low;
030: }
031:
032: public int hashCode() {
033: return (int) ((high >>> 32) ^ high ^ (low >>> 32) ^ low);
034: }
035:
036: public static ValueUuid getNewRandom() {
037: long high = RandomUtils.getSecureLong();
038: long low = RandomUtils.getSecureLong();
039: high = (high & (~0xf000L)) | 0x4000L; // version 4 (random)
040: low = (low & 0x3fffffffffffffffL) | 0x8000000000000000L; // variant (Leach-Salz)
041: return new ValueUuid(high, low);
042: }
043:
044: public static ValueUuid get(byte[] binary) {
045: if (binary.length < 32) {
046: return get(ByteUtils.convertBytesToString(binary));
047: }
048: long high = ByteUtils.readLong(binary, 0);
049: long low = ByteUtils.readLong(binary, 16);
050: return (ValueUuid) Value.cache(new ValueUuid(high, low));
051: }
052:
053: public static ValueUuid get(long high, long low) {
054: return (ValueUuid) Value.cache(new ValueUuid(high, low));
055: }
056:
057: public static ValueUuid get(String s) {
058: long high = 0, low = 0;
059: int i = 0;
060: for (int j = 0; i < s.length() && j < 16; i++) {
061: char ch = s.charAt(i);
062: if (ch != '-') {
063: high = (high << 4) | Character.digit(ch, 16);
064: j++;
065: }
066: }
067: for (int j = 0; i < s.length() && j < 16; i++) {
068: char ch = s.charAt(i);
069: if (ch != '-') {
070: low = (low << 4) | Character.digit(ch, 16);
071: j++;
072: }
073: }
074: return (ValueUuid) Value.cache(new ValueUuid(high, low));
075: }
076:
077: public String getSQL() {
078: return StringUtils.quoteStringSQL(getString());
079: }
080:
081: public int getType() {
082: return Value.UUID;
083: }
084:
085: public long getPrecision() {
086: return PRECISION;
087: }
088:
089: private void appendHex(StringBuffer buff, long x, int bytes) {
090: for (int i = bytes * 8 - 4; i >= 0; i -= 8) {
091: buff.append(Integer.toHexString((int) (x >> i) & 0xf));
092: buff
093: .append(Integer
094: .toHexString((int) (x >> (i - 4)) & 0xf));
095: }
096: }
097:
098: public String getString() {
099: StringBuffer buff = new StringBuffer(36);
100: appendHex(buff, high >> 32, 4);
101: buff.append('-');
102: appendHex(buff, high >> 16, 2);
103: buff.append('-');
104: appendHex(buff, high, 2);
105: buff.append('-');
106: appendHex(buff, low >> 48, 2);
107: buff.append('-');
108: appendHex(buff, low, 6);
109: return buff.toString();
110: }
111:
112: protected int compareSecure(Value o, CompareMode mode) {
113: if (o == this ) {
114: return 0;
115: }
116: ValueUuid v = (ValueUuid) o;
117: if (high == v.high) {
118: return (low == v.low) ? 0 : (low > v.low ? 1 : -1);
119: } else {
120: return high > v.high ? 1 : -1;
121: }
122: }
123:
124: public boolean equals(Object other) {
125: return other instanceof ValueUuid
126: && compareSecure((Value) other, null) == 0;
127: }
128:
129: public Object getObject() {
130: // TODO needs to be documented
131: return new long[] { high, low };
132: }
133:
134: public byte[] getBytes() {
135: byte[] buff = new byte[16];
136: for (int i = 0; i < 8; i++) {
137: buff[i] = (byte) ((high >> (8 * (8 - i))) & 255);
138: buff[8 + i] = (byte) ((low >> (8 * (8 - i))) & 255);
139: }
140: return buff;
141: }
142:
143: public void set(PreparedStatement prep, int parameterIndex)
144: throws SQLException {
145: prep.setBytes(parameterIndex, getBytes());
146: }
147:
148: public long getHigh() {
149: return high;
150: }
151:
152: public long getLow() {
153: return low;
154: }
155:
156: public int getDisplaySize() {
157: return DISPLAY_SIZE;
158: }
159:
160: }
|