/** * This class is a base for all id generators. It also provides lookup of id generators by * their id. * * Generally, id generators are used to generate a primary key for new model instances. There * are different approaches to solving this problem, so this mechanism has both simple use * cases and is open to custom implementations. A {@link Ext.data.Model} requests id generation * using the {@link Ext.data.Model#identifier} property. * * The following types of `identifiers` are provided: * * * `{@link Ext.data.identifier.Sequential sequential}` * * `{@link Ext.data.identifier.Negative negative}` * * `{@link Ext.data.identifier.Uuid uuid}` * * In most cases (other than `uuid`), the server is the only party that can generate * authoritative id values. This means that any id generated by an `identifier` should be * consider "provisional" and must eventually be reconciled with the server. This makes a * `uuid` very attractive as an `identifier` because they are designed to be generated in * a distributed manner and therefore never require reconciliation. * * It is common for id values to be generated as increasing integer values (1, 2, etc.) by * the server when records are inserted. A `{@link Ext.data.identifier.Negative negative}` * `identifier` may be useful as it generates client-side values of -1, -2, etc.. These * values are of the same data type (integer) and so can typically be read by servers * using typed languages (such as Java or C#) and easily recognized as provisional. * * In the end, the choice of `identifier` strategy requires agreement between client and * server. * * # Identity, Type and Shared Generators * * It is often desirable to share Generators to ensure uniqueness or common configuration. * This is done by giving Generator instances an id property by which they can be looked * up using the {@link Ext.Factory#dataIdentifier dataIdentifier} method. To configure two * {@link Ext.data.Model Model} classes to share one * {@link Ext.data.identifier.Sequential sequential} id generator, you simply assign them * the same id: * * Ext.define('MyApp.data.MyModelA', { * extend: 'Ext.data.Model', * identifier: { * type: 'sequential', * id: 'foo' * } * }); * * Ext.define('MyApp.data.MyModelB', { * extend: 'Ext.data.Model', * identifier: { * type: 'sequential', * id: 'foo' * } * }); * * To make this as simple as possible for generator types that are shared by many (or all) * Models, the Generator types (such as 'sequential' or 'uuid') are also reserved as * generator ids. This is used by the {@link Ext.data.identifier.Uuid} which has an id equal * to its type ('uuid'). In other words, the following Models share the same generator: * * Ext.define('MyApp.data.MyModelX', { * extend: 'Ext.data.Model', * identifier: 'uuid' * }); * * Ext.define('MyApp.data.MyModelY', { * extend: 'Ext.data.Model', * identifier: 'uuid' * }); * * This can be overridden (by specifying the id explicitly), but there is no particularly * good reason to do so for this generator type. * * # Creating Custom Generators * * An id generator should derive from this class and implement the {@link #generate} method. * * To register an id generator type, a derived class should provide an `alias` like so: * * Ext.define('MyApp.data.identifier.Custom', { * extend: 'Ext.data.identifier.Generator', * alias: 'data.identifier.custom', * config: { * configProp: 42 // some config property w/default value * } * * generate: function () { * return ... // a new id * } * }); * * Using the custom id generator is then straightforward: * * Ext.define('MyApp.data.MyModel', { * extend: 'Ext.data.Model', * identifier: 'custom' * }); * // or... * * Ext.define('MyApp.data.MyModel', { * extend: 'Ext.data.Model', * identifier: { * type: 'custom', * configProp: value * } * }); * * It is not recommended to mix shared generators with generator configuration. This leads * to unpredictable results unless all configurations match (which is also redundant). In * such cases, a custom generator with a default id is the best approach. * * Ext.define('MyApp.data.identifier.Custom', { * extend: 'Ext.data.identifier.Sequential', * alias: 'data.identifier.custom', * * config: { * id: 'custom', * prefix: 'ID_', * seed: 1000 * } * }); * * Ext.define('MyApp.data.MyModelX', { * extend: 'Ext.data.Model', * identifier: 'custom' * }); * * Ext.define('MyApp.data.MyModelY', { * extend: 'Ext.data.Model', * identifier: 'custom' * }); * * // the above models share a generator that produces ID_1000, ID_1001, etc.. * */Ext.define('Ext.data.identifier.Generator', { 'abstract': true, mixins: [ 'Ext.mixin.Factoryable' ], alias: 'data.identifier.default', // this is used by Factoryable factoryConfig: { defaultType: 'sequential' // this is not a suitable type to create }, /** * @property {Boolean} isGenerator * `true` in this class to identify an object as an instantiated IdGenerator, or subclass * thereof. */ isGenerator: true, config: { /** * @cfg {String} id * The id for this generator. */ id: null }, /** * Initializes a new instance. * @param {Object} config (optional) Configuration object to be applied to the new instance. */ constructor: function(config) { var me = this, id; me.initConfig(config); id = me.getId(); if (id) { Ext.data.identifier.Generator.all[id] = me; } }, /** * Generates and returns the next id. This method must be implemented by the derived * class. * * @return {Number/String} The next id. * @method generate * @abstract */ privates: { /** * Create a copy of this identifier. * @private * @return {Ext.data.identifier.Generator} The clone */ clone: function(config) { var cfg = this.getInitialConfig(); cfg = config ? Ext.apply({}, config, cfg) : cfg; return new this.self(cfg); }, statics: { /** * @property {Object} all * This object is keyed by id to lookup instances. * @private * @static */ all: {} } }}, function() { var Generator = this, Factory = Ext.Factory, factory = Factory.dataIdentifier; // If there is an id property passed we need to lookup that id in the cache. If that // produces a cache miss, call the normal factory. /** * @member Ext.Factory * @method dataIdentifier * Returns an instance of an ID generator based on the ID you pass in. * @param {String/Object} config The config object or `id` to lookup. * @return {Object} Ext.data.identifier.* The data identifier */ Factory.dataIdentifier = function(config) { var id = Ext.isString(config) ? config : (config && config.id), existing = id && Generator.all[id]; return existing || factory(config); };});