Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / docs / source / UuidGenerator.html
1 <!DOCTYPE html>
2 <html>
3 <head>
4   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5   <title>The source code</title>
6   <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
7   <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
8   <style type="text/css">
9     .highlight { display: block; background-color: #ddd; }
10   </style>
11   <script type="text/javascript">
12     function highlight() {
13       document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
14     }
15   </script>
16 </head>
17 <body onload="prettyPrint(); highlight();">
18   <pre class="prettyprint lang-js"><span id='Ext-data-UuidGenerator'>/**
19 </span> * @extend Ext.data.IdGenerator
20  * @author Don Griffin
21  *
22  * This class generates UUID's according to RFC 4122. This class has a default id property.
23  * This means that a single instance is shared unless the id property is overridden. Thus,
24  * two {@link Ext.data.Model} instances configured like the following share one generator:
25  *
26  *     Ext.define('MyApp.data.MyModelX', {
27  *         extend: 'Ext.data.Model',
28  *         idgen: 'uuid'
29  *     });
30  *
31  *     Ext.define('MyApp.data.MyModelY', {
32  *         extend: 'Ext.data.Model',
33  *         idgen: 'uuid'
34  *     });
35  *
36  * This allows all models using this class to share a commonly configured instance.
37  *
38  * # Using Version 1 (&quot;Sequential&quot;) UUID's
39  *
40  * If a server can provide a proper timestamp and a &quot;cryptographic quality random number&quot;
41  * (as described in RFC 4122), the shared instance can be configured as follows:
42  *
43  *     Ext.data.IdGenerator.get('uuid').reconfigure({
44  *         version: 1,
45  *         clockSeq: clock, // 14 random bits
46  *         salt: salt,      // 48 secure random bits (the Node field)
47  *         timestamp: ts    // timestamp per Section 4.1.4
48  *     });
49  *
50  *     // or these values can be split into 32-bit chunks:
51  *
52  *     Ext.data.IdGenerator.get('uuid').reconfigure({
53  *         version: 1,
54  *         clockSeq: clock,
55  *         salt: { lo: saltLow32, hi: saltHigh32 },
56  *         timestamp: { lo: timestampLow32, hi: timestamptHigh32 }
57  *     });
58  *
59  * This approach improves the generator's uniqueness by providing a valid timestamp and
60  * higher quality random data. Version 1 UUID's should not be used unless this information
61  * can be provided by a server and care should be taken to avoid caching of this data.
62  *
63  * See http://www.ietf.org/rfc/rfc4122.txt for details.
64  */
65 Ext.define('Ext.data.UuidGenerator', function () {
66     var twoPow14 = Math.pow(2, 14),
67         twoPow16 = Math.pow(2, 16),
68         twoPow28 = Math.pow(2, 28),
69         twoPow32 = Math.pow(2, 32);
70
71     function toHex (value, length) {
72         var ret = value.toString(16);
73         if (ret.length &gt; length) {
74             ret = ret.substring(ret.length - length); // right-most digits
75         } else if (ret.length &lt; length) {
76             ret = Ext.String.leftPad(ret, length, '0');
77         }
78         return ret;
79     }
80
81     function rand (lo, hi) {
82         var v = Math.random() * (hi - lo + 1);
83         return Math.floor(v) + lo;
84     }
85
86     function split (bignum) {
87         if (typeof(bignum) == 'number') {
88             var hi = Math.floor(bignum / twoPow32);
89             return {
90                 lo: Math.floor(bignum - hi * twoPow32),
91                 hi: hi
92             };
93         }
94         return bignum;
95     }
96
97     return {
98         extend: 'Ext.data.IdGenerator',
99
100         alias: 'idgen.uuid',
101
102         id: 'uuid', // shared by default
103
104 <span id='Ext-data-UuidGenerator-property-salt'>        /**
105 </span>         * @property {Number/Object} salt
106          * When created, this value is a 48-bit number. For computation, this value is split
107          * into 32-bit parts and stored in an object with `hi` and `lo` properties.
108          */
109
110 <span id='Ext-data-UuidGenerator-property-timestamp'>        /**
111 </span>         * @property {Number/Object} timestamp
112          * When created, this value is a 60-bit number. For computation, this value is split
113          * into 32-bit parts and stored in an object with `hi` and `lo` properties.
114          */
115
116 <span id='Ext-data-UuidGenerator-cfg-version'>        /**
117 </span>         * @cfg {Number} version
118          * The Version of UUID. Supported values are:
119          *
120          *  * 1 : Time-based, &quot;sequential&quot; UUID.
121          *  * 4 : Pseudo-random UUID.
122          *
123          * The default is 4.
124          */
125         version: 4,
126
127         constructor: function() {
128             var me = this;
129
130             me.callParent(arguments);
131
132             me.parts = [];
133             me.init();
134         },
135
136         generate: function () {
137             var me = this,
138                 parts = me.parts,
139                 ts = me.timestamp;
140
141             /*
142                The magic decoder ring (derived from RFC 4122 Section 4.2.2):
143
144                +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
145                |                          time_low                             |
146                +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
147                |           time_mid            |  ver  |        time_hi        |
148                +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
149                |res|  clock_hi |   clock_low   |    salt 0   |M|     salt 1    |
150                +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
151                |                         salt (2-5)                            |
152                +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
153
154                          time_mid      clock_hi (low 6 bits)
155                 time_low     | time_hi |clock_lo
156                     |        |     |   || salt[0]
157                     |        |     |   ||   | salt[1..5]
158                     v        v     v   vv   v v
159                     0badf00d-aced-1def-b123-dfad0badbeef
160                                   ^    ^     ^
161                             version    |     multicast (low bit)
162                                        |
163                                     reserved (upper 2 bits)
164             */
165             parts[0] = toHex(ts.lo, 8);
166             parts[1] = toHex(ts.hi &amp; 0xFFFF, 4);
167             parts[2] = toHex(((ts.hi &gt;&gt;&gt; 16) &amp; 0xFFF) | (me.version &lt;&lt; 12), 4);
168             parts[3] = toHex(0x80 | ((me.clockSeq &gt;&gt;&gt; 8) &amp; 0x3F), 2) +
169                        toHex(me.clockSeq &amp; 0xFF, 2);
170             parts[4] = toHex(me.salt.hi, 4) + toHex(me.salt.lo, 8);
171
172             if (me.version == 4) {
173                 me.init(); // just regenerate all the random values...
174             } else {
175                 // sequentially increment the timestamp...
176                 ++ts.lo;
177                 if (ts.lo &gt;= twoPow32) { // if (overflow)
178                     ts.lo = 0;
179                     ++ts.hi;
180                 }
181             }
182
183             return parts.join('-').toLowerCase();
184         },
185
186         getRecId: function (rec) {
187             return rec.getId();
188         },
189
190 <span id='Ext-data-UuidGenerator-method-init'>        /**
191 </span>         * @private
192          */
193         init: function () {
194             var me = this,
195                 salt, time;
196
197             if (me.version == 4) {
198                 // See RFC 4122 (Secion 4.4)
199                 //   o  If the state was unavailable (e.g., non-existent or corrupted),
200                 //      or the saved node ID is different than the current node ID,
201                 //      generate a random clock sequence value.
202                 me.clockSeq = rand(0, twoPow14-1);
203
204                 // we run this on every id generation...
205                 salt = me.salt || (me.salt = {});
206                 time = me.timestamp || (me.timestamp = {});
207
208                 // See RFC 4122 (Secion 4.4)
209                 salt.lo = rand(0, twoPow32-1);
210                 salt.hi = rand(0, twoPow16-1);
211                 time.lo = rand(0, twoPow32-1);
212                 time.hi = rand(0, twoPow28-1);
213             } else {
214                 // this is run only once per-instance
215                 me.salt = split(me.salt);
216                 me.timestamp = split(me.timestamp);
217
218                 // Set multicast bit: &quot;the least significant bit of the first octet of the
219                 // node ID&quot; (nodeId = salt for this implementation):
220                 me.salt.hi |= 0x100;
221             }
222         },
223
224 <span id='Ext-data-UuidGenerator-method-reconfigure'>        /**
225 </span>         * Reconfigures this generator given new config properties.
226          */
227         reconfigure: function (config) {
228             Ext.apply(this, config);
229             this.init();
230         }
231     };
232 }());
233 </pre>
234 </body>
235 </html>