Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / src / data / IdGenerator.js
1 /*
2
3 This file is part of Ext JS 4
4
5 Copyright (c) 2011 Sencha Inc
6
7 Contact:  http://www.sencha.com/contact
8
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.
11
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
13
14 */
15 /**
16  * @author Don Griffin
17  *
18  * This class is a base for all id generators. It also provides lookup of id generators by
19  * their id.
20  * 
21  * Generally, id generators are used to generate a primary key for new model instances. There
22  * are different approaches to solving this problem, so this mechanism has both simple use
23  * cases and is open to custom implementations. A {@link Ext.data.Model} requests id generation
24  * using the {@link Ext.data.Model#idgen} property.
25  *
26  * # Identity, Type and Shared IdGenerators
27  *
28  * It is often desirable to share IdGenerators to ensure uniqueness or common configuration.
29  * This is done by giving IdGenerator instances an id property by which they can be looked
30  * up using the {@link #get} method. To configure two {@link Ext.data.Model Model} classes
31  * to share one {@link Ext.data.SequentialIdGenerator sequential} id generator, you simply
32  * assign them the same id:
33  *
34  *     Ext.define('MyApp.data.MyModelA', {
35  *         extend: 'Ext.data.Model',
36  *         idgen: {
37  *             type: 'sequential',
38  *             id: 'foo'
39  *         }
40  *     });
41  *
42  *     Ext.define('MyApp.data.MyModelB', {
43  *         extend: 'Ext.data.Model',
44  *         idgen: {
45  *             type: 'sequential',
46  *             id: 'foo'
47  *         }
48  *     });
49  *
50  * To make this as simple as possible for generator types that are shared by many (or all)
51  * Models, the IdGenerator types (such as 'sequential' or 'uuid') are also reserved as
52  * generator id's. This is used by the {@link Ext.data.UuidGenerator} which has an id equal
53  * to its type ('uuid'). In other words, the following Models share the same generator:
54  *
55  *     Ext.define('MyApp.data.MyModelX', {
56  *         extend: 'Ext.data.Model',
57  *         idgen: 'uuid'
58  *     });
59  *
60  *     Ext.define('MyApp.data.MyModelY', {
61  *         extend: 'Ext.data.Model',
62  *         idgen: 'uuid'
63  *     });
64  *
65  * This can be overridden (by specifying the id explicitly), but there is no particularly
66  * good reason to do so for this generator type.
67  *
68  * # Creating Custom Generators
69  * 
70  * An id generator should derive from this class and implement the {@link #generate} method.
71  * The constructor will apply config properties on new instances, so a constructor is often
72  * not necessary.
73  *
74  * To register an id generator type, a derived class should provide an `alias` like so:
75  *
76  *     Ext.define('MyApp.data.CustomIdGenerator', {
77  *         extend: 'Ext.data.IdGenerator',
78  *         alias: 'idgen.custom',
79  *
80  *         configProp: 42, // some config property w/default value
81  *
82  *         generate: function () {
83  *             return ... // a new id
84  *         }
85  *     });
86  *
87  * Using the custom id generator is then straightforward:
88  *
89  *     Ext.define('MyApp.data.MyModel', {
90  *         extend: 'Ext.data.Model',
91  *         idgen: 'custom'
92  *     });
93  *     // or...
94  *
95  *     Ext.define('MyApp.data.MyModel', {
96  *         extend: 'Ext.data.Model',
97  *         idgen: {
98  *             type: 'custom',
99  *             configProp: value
100  *         }
101  *     });
102  *
103  * It is not recommended to mix shared generators with generator configuration. This leads
104  * to unpredictable results unless all configurations match (which is also redundant). In
105  * such cases, a custom generator with a default id is the best approach.
106  *
107  *     Ext.define('MyApp.data.CustomIdGenerator', {
108  *         extend: 'Ext.data.SequentialIdGenerator',
109  *         alias: 'idgen.custom',
110  *
111  *         id: 'custom', // shared by default
112  *
113  *         prefix: 'ID_',
114  *         seed: 1000
115  *     });
116  *
117  *     Ext.define('MyApp.data.MyModelX', {
118  *         extend: 'Ext.data.Model',
119  *         idgen: 'custom'
120  *     });
121  *
122  *     Ext.define('MyApp.data.MyModelY', {
123  *         extend: 'Ext.data.Model',
124  *         idgen: 'custom'
125  *     });
126  *
127  *     // the above models share a generator that produces ID_1000, ID_1001, etc..
128  *
129  */
130 Ext.define('Ext.data.IdGenerator', {
131
132     isGenerator: true,
133
134     /**
135      * Initializes a new instance.
136      * @param {Object} config (optional) Configuration object to be applied to the new instance.
137      */
138     constructor: function(config) {
139         var me = this;
140
141         Ext.apply(me, config);
142
143         if (me.id) {
144             Ext.data.IdGenerator.all[me.id] = me;
145         }
146     },
147
148     /**
149      * @cfg {String} id
150      * The id by which to register a new instance. This instance can be found using the
151      * {@link Ext.data.IdGenerator#get} static method.
152      */
153
154     getRecId: function (rec) {
155         return rec.modelName + '-' + rec.internalId;
156     },
157
158     /**
159      * Generates and returns the next id. This method must be implemented by the derived
160      * class.
161      *
162      * @return {String} The next id.
163      * @method generate
164      * @abstract
165      */
166
167     statics: {
168         /**
169          * @property {Object} all
170          * This object is keyed by id to lookup instances.
171          * @private
172          * @static
173          */
174         all: {},
175
176         /**
177          * Returns the IdGenerator given its config description.
178          * @param {String/Object} config If this parameter is an IdGenerator instance, it is
179          * simply returned. If this is a string, it is first used as an id for lookup and
180          * then, if there is no match, as a type to create a new instance. This parameter
181          * can also be a config object that contains a `type` property (among others) that
182          * are used to create and configure the instance.
183          * @static
184          */
185         get: function (config) {
186             var generator,
187                 id,
188                 type;
189
190             if (typeof config == 'string') {
191                 id = type = config;
192                 config = null;
193             } else if (config.isGenerator) {
194                 return config;
195             } else {
196                 id = config.id || config.type;
197                 type = config.type;
198             }
199
200             generator = this.all[id];
201             if (!generator) {
202                 generator = Ext.create('idgen.' + type, config);
203             }
204
205             return generator;
206         }
207     }
208 });
209