3 This file is part of Ext JS 4
5 Copyright (c) 2011 Sencha Inc
7 Contact: http://www.sencha.com/contact
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file. Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
16 * @extend Ext.data.IdGenerator
19 * This class generates UUID's according to RFC 4122. This class has a default id property.
20 * This means that a single instance is shared unless the id property is overridden. Thus,
21 * two {@link Ext.data.Model} instances configured like the following share one generator:
23 * Ext.define('MyApp.data.MyModelX', {
24 * extend: 'Ext.data.Model',
28 * Ext.define('MyApp.data.MyModelY', {
29 * extend: 'Ext.data.Model',
33 * This allows all models using this class to share a commonly configured instance.
35 * # Using Version 1 ("Sequential") UUID's
37 * If a server can provide a proper timestamp and a "cryptographic quality random number"
38 * (as described in RFC 4122), the shared instance can be configured as follows:
40 * Ext.data.IdGenerator.get('uuid').reconfigure({
42 * clockSeq: clock, // 14 random bits
43 * salt: salt, // 48 secure random bits (the Node field)
44 * timestamp: ts // timestamp per Section 4.1.4
47 * // or these values can be split into 32-bit chunks:
49 * Ext.data.IdGenerator.get('uuid').reconfigure({
52 * salt: { lo: saltLow32, hi: saltHigh32 },
53 * timestamp: { lo: timestampLow32, hi: timestamptHigh32 }
56 * This approach improves the generator's uniqueness by providing a valid timestamp and
57 * higher quality random data. Version 1 UUID's should not be used unless this information
58 * can be provided by a server and care should be taken to avoid caching of this data.
60 * See http://www.ietf.org/rfc/rfc4122.txt for details.
62 Ext.define('Ext.data.UuidGenerator', function () {
63 var twoPow14 = Math.pow(2, 14),
64 twoPow16 = Math.pow(2, 16),
65 twoPow28 = Math.pow(2, 28),
66 twoPow32 = Math.pow(2, 32);
68 function toHex (value, length) {
69 var ret = value.toString(16);
70 if (ret.length > length) {
71 ret = ret.substring(ret.length - length); // right-most digits
72 } else if (ret.length < length) {
73 ret = Ext.String.leftPad(ret, length, '0');
78 function rand (lo, hi) {
79 var v = Math.random() * (hi - lo + 1);
80 return Math.floor(v) + lo;
83 function split (bignum) {
84 if (typeof(bignum) == 'number') {
85 var hi = Math.floor(bignum / twoPow32);
87 lo: Math.floor(bignum - hi * twoPow32),
95 extend: 'Ext.data.IdGenerator',
99 id: 'uuid', // shared by default
102 * @property {Number/Object} salt
103 * When created, this value is a 48-bit number. For computation, this value is split
104 * into 32-bit parts and stored in an object with `hi` and `lo` properties.
108 * @property {Number/Object} timestamp
109 * When created, this value is a 60-bit number. For computation, this value is split
110 * into 32-bit parts and stored in an object with `hi` and `lo` properties.
114 * @cfg {Number} version
115 * The Version of UUID. Supported values are:
117 * * 1 : Time-based, "sequential" UUID.
118 * * 4 : Pseudo-random UUID.
124 constructor: function() {
127 me.callParent(arguments);
133 generate: function () {
139 The magic decoder ring (derived from RFC 4122 Section 4.2.2):
141 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
143 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
144 | time_mid | ver | time_hi |
145 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
146 |res| clock_hi | clock_low | salt 0 |M| salt 1 |
147 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
149 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
151 time_mid clock_hi (low 6 bits)
152 time_low | time_hi |clock_lo
154 | | | || | salt[1..5]
156 0badf00d-aced-1def-b123-dfad0badbeef
158 version | multicast (low bit)
160 reserved (upper 2 bits)
162 parts[0] = toHex(ts.lo, 8);
163 parts[1] = toHex(ts.hi & 0xFFFF, 4);
164 parts[2] = toHex(((ts.hi >>> 16) & 0xFFF) | (me.version << 12), 4);
165 parts[3] = toHex(0x80 | ((me.clockSeq >>> 8) & 0x3F), 2) +
166 toHex(me.clockSeq & 0xFF, 2);
167 parts[4] = toHex(me.salt.hi, 4) + toHex(me.salt.lo, 8);
169 if (me.version == 4) {
170 me.init(); // just regenerate all the random values...
172 // sequentially increment the timestamp...
174 if (ts.lo >= twoPow32) { // if (overflow)
180 return parts.join('-').toLowerCase();
183 getRecId: function (rec) {
194 if (me.version == 4) {
195 // See RFC 4122 (Secion 4.4)
196 // o If the state was unavailable (e.g., non-existent or corrupted),
197 // or the saved node ID is different than the current node ID,
198 // generate a random clock sequence value.
199 me.clockSeq = rand(0, twoPow14-1);
201 // we run this on every id generation...
202 salt = me.salt || (me.salt = {});
203 time = me.timestamp || (me.timestamp = {});
205 // See RFC 4122 (Secion 4.4)
206 salt.lo = rand(0, twoPow32-1);
207 salt.hi = rand(0, twoPow16-1);
208 time.lo = rand(0, twoPow32-1);
209 time.hi = rand(0, twoPow28-1);
211 // this is run only once per-instance
212 me.salt = split(me.salt);
213 me.timestamp = split(me.timestamp);
215 // Set multicast bit: "the least significant bit of the first octet of the
216 // node ID" (nodeId = salt for this implementation):
222 * Reconfigures this generator given new config properties.
224 reconfigure: function (config) {
225 Ext.apply(this, config);