]> git.proxmox.com Git - extjs.git/blame - extjs/packages/core/src/data/identifier/Generator.js
add extjs 6.0.1 sources
[extjs.git] / extjs / packages / core / src / data / identifier / Generator.js
CommitLineData
6527f429
DM
1/**\r
2 * This class is a base for all id generators. It also provides lookup of id generators by\r
3 * their id.\r
4 * \r
5 * Generally, id generators are used to generate a primary key for new model instances. There\r
6 * are different approaches to solving this problem, so this mechanism has both simple use\r
7 * cases and is open to custom implementations. A {@link Ext.data.Model} requests id generation\r
8 * using the {@link Ext.data.Model#identifier} property.\r
9 *\r
10 * The following types of `identifiers` are provided:\r
11 *\r
12 * * `{@link Ext.data.identifier.Sequential sequential}`\r
13 * * `{@link Ext.data.identifier.Negative negative}`\r
14 * * `{@link Ext.data.identifier.Uuid uuid}`\r
15 *\r
16 * In most cases (other than `uuid`), the server is the only party that can generate\r
17 * authoritative id values. This means that any id generated by an `identifier` should be\r
18 * consider "provisional" and must eventually be reconciled with the server. This makes a\r
19 * `uuid` very attractive as an `identifier` because they are designed to be generated in\r
20 * a distributed manner and therefore never require reconciliation.\r
21 *\r
22 * It is common for id values to be generated as increasing integer values (1, 2, etc.) by\r
23 * the server when records are inserted. A `{@link Ext.data.identifier.Negative negative}`\r
24 * `identifier` may be useful as it generates client-side values of -1, -2, etc.. These\r
25 * values are of the same data type (integer) and so can typically be read by servers\r
26 * using typed languages (such as Java or C#) and easily recognized as provisional.\r
27 *\r
28 * In the end, the choice of `identifier` strategy requires agreement between client and\r
29 * server.\r
30 *\r
31 * # Identity, Type and Shared Generators\r
32 *\r
33 * It is often desirable to share Generators to ensure uniqueness or common configuration.\r
34 * This is done by giving Generator instances an id property by which they can be looked\r
35 * up using the {@link Ext.Factory#dataIdentifier dataIdentifier} method. To configure two {@link Ext.data.Model Model} classes\r
36 * to share one {@link Ext.data.identifier.Sequential sequential} id generator, you simply\r
37 * assign them the same id:\r
38 *\r
39 * Ext.define('MyApp.data.MyModelA', {\r
40 * extend: 'Ext.data.Model',\r
41 * identifier: {\r
42 * type: 'sequential',\r
43 * id: 'foo'\r
44 * }\r
45 * });\r
46 *\r
47 * Ext.define('MyApp.data.MyModelB', {\r
48 * extend: 'Ext.data.Model',\r
49 * identifier: {\r
50 * type: 'sequential',\r
51 * id: 'foo'\r
52 * }\r
53 * });\r
54 *\r
55 * To make this as simple as possible for generator types that are shared by many (or all)\r
56 * Models, the Generator types (such as 'sequential' or 'uuid') are also reserved as\r
57 * generator ids. This is used by the {@link Ext.data.identifier.Uuid} which has an id equal\r
58 * to its type ('uuid'). In other words, the following Models share the same generator:\r
59 *\r
60 * Ext.define('MyApp.data.MyModelX', {\r
61 * extend: 'Ext.data.Model',\r
62 * identifier: 'uuid'\r
63 * });\r
64 *\r
65 * Ext.define('MyApp.data.MyModelY', {\r
66 * extend: 'Ext.data.Model',\r
67 * identifier: 'uuid'\r
68 * });\r
69 *\r
70 * This can be overridden (by specifying the id explicitly), but there is no particularly\r
71 * good reason to do so for this generator type.\r
72 *\r
73 * # Creating Custom Generators\r
74 * \r
75 * An id generator should derive from this class and implement the {@link #generate} method.\r
76 *\r
77 * To register an id generator type, a derived class should provide an `alias` like so:\r
78 *\r
79 * Ext.define('MyApp.data.identifier.Custom', {\r
80 * extend: 'Ext.data.identifier.Generator',\r
81 * alias: 'data.identifier.custom',\r
82 * config: {\r
83 * configProp: 42 // some config property w/default value\r
84 * }\r
85 *\r
86 * generate: function () {\r
87 * return ... // a new id\r
88 * }\r
89 * });\r
90 *\r
91 * Using the custom id generator is then straightforward:\r
92 *\r
93 * Ext.define('MyApp.data.MyModel', {\r
94 * extend: 'Ext.data.Model',\r
95 * identifier: 'custom'\r
96 * });\r
97 * // or...\r
98 *\r
99 * Ext.define('MyApp.data.MyModel', {\r
100 * extend: 'Ext.data.Model',\r
101 * identifier: {\r
102 * type: 'custom',\r
103 * configProp: value\r
104 * }\r
105 * });\r
106 *\r
107 * It is not recommended to mix shared generators with generator configuration. This leads\r
108 * to unpredictable results unless all configurations match (which is also redundant). In\r
109 * such cases, a custom generator with a default id is the best approach.\r
110 *\r
111 * Ext.define('MyApp.data.identifier.Custom', {\r
112 * extend: 'Ext.data.identifier.Sequential',\r
113 * alias: 'data.identifier.custom',\r
114 * \r
115 * config: {\r
116 * id: 'custom',\r
117 * prefix: 'ID_',\r
118 * seed: 1000\r
119 * }\r
120 * });\r
121 *\r
122 * Ext.define('MyApp.data.MyModelX', {\r
123 * extend: 'Ext.data.Model',\r
124 * identifier: 'custom'\r
125 * });\r
126 *\r
127 * Ext.define('MyApp.data.MyModelY', {\r
128 * extend: 'Ext.data.Model',\r
129 * identifier: 'custom'\r
130 * });\r
131 *\r
132 * // the above models share a generator that produces ID_1000, ID_1001, etc..\r
133 *\r
134 */\r
135Ext.define('Ext.data.identifier.Generator', {\r
136 'abstract': true,\r
137\r
138 mixins: [\r
139 'Ext.mixin.Factoryable'\r
140 ],\r
141\r
142 alias: 'data.identifier.default', // this is used by Factoryable\r
143\r
144 factoryConfig: {\r
145 defaultType: 'sequential' // this is not a suitable type to create\r
146 },\r
147\r
148 /**\r
149 * @property {Boolean} isGenerator\r
150 * `true` in this class to identify an object as an instantiated IdGenerator, or subclass thereof.\r
151 */\r
152 isGenerator: true,\r
153\r
154 config: {\r
155 /**\r
156 * @cfg {String} id\r
157 * The id for this generator.\r
158 */\r
159 id: null\r
160 },\r
161\r
162 /**\r
163 * Initializes a new instance.\r
164 * @param {Object} config (optional) Configuration object to be applied to the new instance.\r
165 */\r
166 constructor: function (config) {\r
167 var me = this,\r
168 cache, id;\r
169\r
170 me.initConfig(config);\r
171\r
172 id = me.getId();\r
173 if (id) {\r
174 cache = (config && config.cache) || Ext.data.identifier.Generator.all;\r
175 cache[id] = me;\r
176 }\r
177 },\r
178\r
179 /**\r
180 * Generates and returns the next id. This method must be implemented by the derived\r
181 * class.\r
182 *\r
183 * @return {Number/String} The next id.\r
184 * @method generate\r
185 * @abstract\r
186 */\r
187\r
188 privates: {\r
189 /**\r
190 * Create a copy of this identifier.\r
191 * @private\r
192 * @return {Ext.data.identifier.Generator} The clone\r
193 */\r
194 clone: function (config) {\r
195 var cfg = this.getInitialConfig();\r
196 cfg = config ? Ext.apply({}, config, cfg) : cfg;\r
197 return new this.self(cfg);\r
198 },\r
199\r
200 statics: {\r
201 /**\r
202 * @property {Object} all\r
203 * This object is keyed by id to lookup instances.\r
204 * @private\r
205 * @static\r
206 */\r
207 all: {}\r
208 }\r
209 }\r
210},\r
211function () {\r
212 var Generator = this,\r
213 Factory = Ext.Factory,\r
214 factory = Factory.dataIdentifier;\r
215\r
216 // If there is an id property passed we need to lookup that id in the cache. If that\r
217 // produces a cache miss, call the normal factory.\r
218 /**\r
219 * @member Ext.Factory\r
220 * @method dataIdentifier\r
221 * Returns an instance of an ID generator based on the ID you pass in.\r
222 * @param {string} id\r
223 * @return {Object} Ext.data.identifier.* The data identifier\r
224 */\r
225 Factory.dataIdentifier = function (config) {\r
226 var id = Ext.isString(config) ? config : (config && config.id),\r
227 existing = id && ((config && config.cache) || Generator.all)[id];\r
228\r
229 return existing || factory(config);\r
230 };\r
231});\r