/**
* @module proact-properties
*/
/**
* <p>
* The `ProAct.PropertyProvider` is an abstract class.
* </p>
* <p>
* Many providers can be registered for many kinds of properties.
* </p>
* <p>
* When a ProAct.js object is initialized its fields are turned into properties.
* Depending on the type and the name of the field, as well as meta information the valid
* type of {{#crossLink "ProAct.Property"}}{{/crossLink}} is created and used.
* The `PropertyProviders` have 'filter' method and depending on it the valid kind is decided.
* </p>
* <p>
* ProAct.PropertyProvider is part of the proact-properties module of ProAct.js.
* </p>
*
* @class ProAct.PropertyProvider
* @constructor
*/
function PropertyProvider () {}
ProAct.PropertyProvider = P.PP = PropertyProvider;
(function (P) {
var providers = [];
P.U.ex(P.PP, {
/**
* Registers a `ProAct.PropertyProvider`.
* <p>
* The provider is appended in the end of the list of `ProAct.PropertyProviders`.
* </p>
* <p>
* When a property must be provided if there is a `ProAct.PropertyProvider` registered before
* the passed <i>propertyProvider</i>, with valid filtering for the passed field, it will
* be used instead.
* </p>
*
* @for ProAct.PropertyProvider
* @method registerProvider
* @static
* @param {ProAct.PropertyProvider} propertyProvider
* The `ProAct.PropertyProvider` to register.
*/
registerProvider: function (propertyProvider) {
providers.push(propertyProvider);
},
/**
* Registers a `ProAct.PropertyProvider`.
* <p>
* The provider is prepended in the beginning of the list of `ProAct.PropertyProviders`.
* </p>
* <p>
* It's filtering will be called before any other registered provider.
* </p>
*
* @for ProAct.PropertyProvider
* @method prependProvider
* @static
* @param {ProAct.PropertyProvider} propertyProvider
* The `ProAct.PropertyProvider` to register.
*/
prependProvider: function (propertyProvider) {
providers.unshift(propertyProvider);
},
/**
* Removes a `ProAct.PropertyProvider` from the list of the registered `ProAct.PropertyProviders`.
*
* @for ProAct.PropertyProvider
* @method unregisterProvider
* @static
* @param {ProAct.PropertyProvider} propertyProvider
* The ProAct.PropertyProvider to unregister.
*/
unregisterProvider: function (propertyProvider) {
P.U.remove(providers, propertyProvider);
},
/**
* Removes all `ProAct.PropertyProviders` from the list of the registered `ProAct.PropertyProviders`.
*
* @for ProAct.PropertyProvider
* @static
* @method clearProviders
*/
clearProviders: function () {
providers = [];
},
/**
* Provides a {{#crossLink "ProAct.Property"}}{{/crossLink}} instance using the list of the registered
* `ProAct.PropertyProviders`.
* <p>
* The providers are tried in the order of their registration
* (the order can be changed using {{#crossLink "ProAct.PropertyProvider/prependProvider:method"}}{{/crossLink}}).
* </p>
* <p>
* The {{#crossLink "ProAct.PropertyProvider/filter:method"}}{{/crossLink}} method is used to check
* if a provider is compliant with the passed arguments.
* </p>
* <p>
* If a compliant provider is found, its {{#crossLink "ProAct.PropertyProvider/provide:method"}}{{/crossLink}} method
* is used to provide the {{#crossLink "ProAct.Property"}}{{/crossLink}} instance.
* </p>
*
* @for ProAct.PropertyProvider
* @static
* @param {String} queueName
* The name of the queue all the updates should be pushed to.
* <p>
* If this parameter is null/undefined the default queue of
* {{#crossLink "ProAct/flow:property"}}{{/crossLink}} is used.
* </p>
* <p>
* If this parameter is not a string it is used as the
* <i>object</i>.
* </p>
* @param {Object} object
* The object to provide a {{#crossLink "ProAct.Property"}}{{/crossLink}} instance for.
* @param {String} property
* The field name of the <i>object</i> to turn into a {{#crossLink "ProAct.Property"}}{{/crossLink}}.
* @param {String|Array} meta
* Meta information to be used for filtering and configuration of the {{#crossLink "ProAct.Property"}}{{/crossLink}} instance to be provided.
* @return {ProAct.Property}
* A property provided by registered provider, or null if there is no compliant provider.
*/
provide: function (queueName, object, property, meta) {
if (queueName && !P.U.isString(queueName)) {
meta = property;
property = object;
object = queueName;
queueName = null;
}
var ln = providers.length,
prop = null,
provider = null,
i;
for (i = 0; i < ln; i++) {
provider = providers[i];
if (provider.filter(object, property, meta)) {
break;
} else {
provider = null;
}
}
if (provider) {
prop = provider.provide(queueName, object, property, meta);
}
return prop;
}
});
}(P));
ProAct.PropertyProvider.prototype = {
/**
* Reference to the constructor of this object.
*
* @property constructor
* @type ProAct.PropertyProvider
* @final
* @for ProAct.PropertyProvider
*/
constructor: ProAct.PropertyProvider,
/**
* Used to check if this `ProAct.PropertyProvider` is compliant with the field and meta data
* to be used for creating a {{#crossLink "ProAct.Property"}}{{/crossLink}} instance with
* {{#crossLink "ProAct.PropertyProvider/provide:method"}}{{/crossLink}}.
* <p>
* Abstract - must be implemented by an extender.
* </p>
*
* @for ProAct.PropertyProvider
* @abstract
* @instance
* @method filter
* @param {Object} object
* The object to which a new {{#crossLink "ProAct.Property"}}{{/crossLink}} instance should be provided.
* @param {String} property
* The field name of the <i>object</i> to turn into a {{#crossLink "ProAct.Property"}}{{/crossLink}}.
* Can be used in the filtering process.
* <p>
* For example field name beginning with foo. Can be turned into a FooProperty.
* </p>
* @param {String|Array} meta
* Meta information to be used for filtering and configuration of the {{#crossLink "ProAct.Property"}}{{/crossLink}} instance to be provided.
* @return {Boolean}
* If <i>this</i> provider is compliant with the passed arguments.
*/
filter: function (object, property, meta) {
throw new Error('Abstract! Implement!');
},
/**
* Provides an instance of {{#crossLink "ProAct.Property"}}{{/crossLink}}.
* <p>
* It should be called only after <i>this</i> {{#crossLink "ProAct.PropertyProvider/filter:method"}}{{/crossLink}} method,
* called with the same arguments returns true.
* </p>
* <p>
* Abstract - must be implemented in an extender.
* </p>
*
* @for ProAct.PropertyProvider
* @abstract
* @instance
* @method provide
* @param {String} queueName
* The name of the queue all the updates should be pushed to.
* <p>
* If this parameter is null/undefined the default queue of
* {{#crossLink "ProAct/flow:property"}}{{/crossLink}} is used.
* </p>
* @param {Object} object
* The object to which a new {{#crossLink "ProAct.Property"}}{{/crossLink}} instance should be provided.
* @param {String} property
* The field of the <i>object</i> to turn into a {{#crossLink "ProAct.Property"}}{{/crossLink}}. Can be used in the filtering process.
* @param {String|Array} meta
* Meta information to be used for filtering and configuration of the {{#crossLink "ProAct.Property"}}{{/crossLink}} instance to be provided.
* @return {ProAct.Property}
* A property provided by <i>this</i> provider.
*/
provide: function (queueName, object, property, meta) {
throw new Error('Abstract! Implement!');
}
};
/**
* <p>
* Constructor for `ProAct.SimplePropertyProvider`.
* </p>
* <p>
* Provides {{#crossLink "ProAct.Property"}}{{/crossLink}} instances for fields of simple types - strings, numbers, booleans.
* </p>
* <p>
* `ProAct.SimplePropertyProvider` is part of the proact-properties module of ProAct.js.
* </p>
*
* @class ProAct.SimplePropertyProvider
* @extends ProAct.PropertyProvider
* @constructor
*/
ProAct.SimplePropertyProvider = P.SPP = function () {
P.PP.call(this);
};
ProAct.SimplePropertyProvider.prototype = P.U.ex(Object.create(P.PP.prototype), {
/**
* Reference to the constructor of this object.
*
* @property constructor
* @type ProAct.SimplePropertyProvider
* @final
* @for ProAct.SimplePropertyProvider
*/
constructor: ProAct.SimplePropertyProvider,
/**
* Used to check if this `ProAct.SimplePropertyProvider` is compliant with the field and meta data.
*
* @for ProAct.SimplePropertyProvider
* @instance
* @method filter
* @param {Object} object
* The object to which a new {{#crossLink "ProAct.Property"}}{{/crossLink}} instance should be provided.
* @param {String} property
* The field name of the <i>object</i> to turn into a {{#crossLink "ProAct.Property"}}{{/crossLink}}. Can be used in the filtering process.
* @param {String|Array} meta
* Meta information to be used for filtering and configuration of the {{#crossLink "ProAct.Property"}}{{/crossLink}} instance to be provided.
* @return {Boolean}
* True if the value of <b>object[property]</b> not undefined or null as well as object, array ot function.
*/
filter: function (object, property, meta) {
var v = object[property];
return (v === null || v === undefined) || (!P.U.isFunction(v) && !P.U.isArray(v) && !P.U.isObject(v));
},
/**
* Provides an instance of {{#crossLink "ProAct.Property"}}{{/crossLink}}.
*
* @for ProAct.SimplePropertyProvider
* @instance
* @method provide
* @param {String} queueName
* The name of the queue all the updates should be pushed to.
* <p>
* If this parameter is null/undefined the default queue of
* {{#crossLink "ProAct/flow:property"}}{{/crossLink}} is used.
* </p>
* @param {Object} object
* The object to which a new {{#crossLink "ProAct.Property"}}{{/crossLink}} instance should be provided.
* @param {String} property
* The field of the <i>object</i> to turn into a {{#crossLink "ProAct.Property"}}{{/crossLink}}.
* @param {String|Array} meta
* Meta information to be used for filtering and configuration of the {{#crossLink "ProAct.Property"}}{{/crossLink}} instance to be provided.
* @return {ProAct.Property}
* A {{#crossLink "ProAct.Property"}}{{/crossLink}} instance provided by <i>this</i> provider.
*/
provide: function (queueName, object, property, meta) {
return new P.P(queueName, object, property);
}
});
/**
* <p>
* Constructor for `ProAct.AutoPropertyProvider`.
* </p>
* <p>
* Provides {{#crossLink "ProAct.AutoProperty"}}{{/crossLink}} instances for fields pointing to functions.
* </p>
* <p>
* `ProAct.AutoPropertyProvider` is part of the `proact-properties` module of ProAct.js.
* </p>
*
* @class ProAct.AutoPropertyProvider
* @extends ProAct.PropertyProvider
* @constructor
*/
ProAct.AutoPropertyProvider = P.FPP = function () {
P.PP.call(this);
};
ProAct.AutoPropertyProvider.prototype = P.U.ex(Object.create(P.PP.prototype), {
/**
* Reference to the constructor of this object.
*
* @property constructor
* @type ProAct.AutoPropertyProvider
* @final
* @for ProAct.AutoPropertyProvider
*/
constructor: ProAct.AutoPropertyProvider,
/**
* Used to check if this `ProAct.AutoPropertyProvider` is compliant with the field and meta data.
*
* @for ProAct.AutoPropertyProvider
* @instance
* @method filter
* @param {Object} object
* The object to which a new {{#crossLink "ProAct.AutoProperty"}}{{/crossLink}} instance should be provided.
* @param {String} property
* The field name of the <i>object</i> to turn into a {{#crossLink "ProAct.AutoProperty"}}{{/crossLink}}.
* @param {String|Array} meta
* Meta information to be used for filtering and configuration of the {{#crossLink "ProAct.AutoProperty"}}{{/crossLink}} instance to be provided.
* @return {Boolean}
* True if the value of <b>object[property]</b> a function.
*/
filter: function (object, property, meta) {
return P.U.isFunction(object[property]);
},
/**
* Provides an instance of {{#crossLink "ProAct.AutoProperty"}}{{/crossLink}}.
*
* @for ProAct.AutoPropertyProvider
* @instance
* @method provide
* @param {String} queueName
* The name of the queue all the updates should be pushed to.
* <p>
* If this parameter is null/undefined the default queue of
* {{#crossLink "ProAct/flow:property"}}{{/crossLink}} is used.
* </p>
* @param {Object} object
* The object to which a new {{#crossLink "ProAct.AutoProperty"}}{{/crossLink}} instance should be provided.
* @param {String} property
* The field of the <i>object</i> to turn into a {{#crossLink "ProAct.AutoProperty"}}{{/crossLink}}.
* @param {String|Array} meta
* Meta information to be used for filtering and configuration of the {{#crossLink "ProAct.AutoProperty"}}{{/crossLink}} instance to be provided.
* @return {ProAct.AutoProperty}
* A {{#crossLink "ProAct.AutoProperty"}}{{/crossLink}} instance provided by <i>this</i> provider.
*/
provide: function (queueName, object, property, meta) {
return new P.FP(queueName, object, property);
}
});
/**
* <p>
* Constructor for ProAct.ObjectPropertyProvider.
* </p>
* <p>
* Provides {{#crossLink "ProAct.ObjectProperty"}}{{/crossLink}} instances for fields pointing to objects, different from arrays or functions.
* </p>
* <p>
* `ProAct.ObjectPropertyProvider` is part of the proact-properties module of ProAct.js.
* </p>
*
* @class ProAct.ObjectPropertyProvider
* @extends ProAct.PropertyProvider
* @constructor
*/
ProAct.ObjectPropertyProvider = P.OPP = function () {
P.PP.call(this);
};
ProAct.ObjectPropertyProvider.prototype = P.U.ex(Object.create(P.PP.prototype), {
/**
* Reference to the constructor of this object.
*
* @property constructor
* @type ProAct.ObjectPropertyProvider
* @final
* @for ProAct.ObjectPropertyProvider
*/
constructor: ProAct.ObjectPropertyProvider,
/**
* Used to check if this `ProAct.ObjectPropertyProvider` is compliant with the field and meta data.
*
* @for ProAct.ObjectPropertyProvider
* @instance
* @method filter
* @param {Object} object
* The object to which a new {{#crossLink "ProAct.ObjectProperty"}}{{/crossLink}} instance should be provided.
* @param {String} property
* The field name of the <i>object</i> to turn into a {{#crossLink "ProAct.ObjectProperty"}}{{/crossLink}}.
* @param {String|Array} meta
* Meta information to be used for filtering and configuration of the {{#crossLink "ProAct.ObjectProperty"}}{{/crossLink}} instance to be provided.
* @return {Boolean}
* True if the value of <b>object[property]</b> an object, different from array or function.
*/
filter: function (object, property, meta) {
return P.U.isObject(object[property]);
},
/**
* Provides an instance of {{#crossLink "ProAct.ObjectProperty"}}{{/crossLink}}.
*
* @for ProAct.ObjectPropertyProvider
* @instance
* @method provide
* @param {String} queueName
* The name of the queue all the updates should be pushed to.
* <p>
* If this parameter is null/undefined the default queue of
* {{#crossLink "ProAct/flow:property"}}{{/crossLink}} is used.
* </p>
* @param {Object} object
* The object to which a new {{#crossLink "ProAct.ObjectProperty"}}{{/crossLink}} instance should be provided.
* @param {String} property
* The field of the <i>object</i> to turn into a {{#crossLink "ProAct.ObjectProperty"}}{{/crossLink}}.
* @param {String|Array} meta
* Meta information to be used for filtering and configuration of the {{#crossLink "ProAct.ObjectProperty"}}{{/crossLink}} instance to be provided.
* @return {ProAct.ObjectProperty}
* A {{#crossLink "ProAct.ObjectProperty"}}{{/crossLink}} instance provided by <i>this</i> provider.
*/
provide: function (queueName, object, property, meta) {
return new P.OP(queueName, object, property);
}
});
/**
* <p>
* Constructor for `ProAct.ProxyPropertyProvider`.
* </p>
* <p>
* Provides {{#crossLink "ProAct.ProxyProperty"}}{{/crossLink}} instances for fields that should point to properties.
* </p>
* <p>
* `ProAct.ProxyPropertyProvider` is part of the proact-properties module of ProAct.js.
* </p>
*
* @class ProAct.ProxyPropertyProvider
* @extends ProAct.PropertyProvider
* @constructor
*/
ProAct.ProxyPropertyProvider = P.PXPP = function () {
P.PP.call(this);
};
ProAct.ProxyPropertyProvider.prototype = P.U.ex(Object.create(P.PP.prototype), {
/**
* Reference to the constructor of this object.
*
* @property constructor
* @type ProAct.ProxyPropertyProvider
* @final
* @for ProAct.ProxyPropertyProvider
*/
constructor: ProAct.ProxyPropertyProvider,
/**
* Used to check if this `ProAct.ProxyPropertyProvider` is compliant with the meta data.
*
* @for ProAct.ProxyPropertyProvider
* @instance
* @method filter
* @param {Object} object
* The object to which a new {{#crossLink "ProAct.ProxyProperty"}}{{/crossLink}} instance should be provided.
* @param {String} property
* The field name of the <i>object</i> to turn into a {{#crossLink "ProAct.ProxyProperty"}}{{/crossLink}}.
* @param {ProAct.Property} meta
* If the meta is present and of type {{#crossLink "ProAct.Property"}}{{/crossLink}}, it becomes the target property of the
* {{#crossLink "ProAct.ProxyProperty"}}{{/crossLink}} that will be provided.
* @return {Boolean}
* True if <i>meta</i> argument is present and is instance of {{#crossLink "ProAct.Property"}}{{/crossLink}}.
*/
filter: function (object, property, meta) {
if (!meta || !(meta instanceof ProAct.Property)) {
return false;
}
return meta instanceof ProAct.Property;
},
/**
* Provides an instance of {{#crossLink "ProAct.ProxyProperty"}}{{/crossLink}}.
*
* @for ProAct.ProxyPropertyProvider
* @instance
* @method provide
* @param {String} queueName
* The name of the queue all the updates should be pushed to.
* <p>
* If this parameter is null/undefined the default queue of
* {{#crossLink "ProAct/flow:property"}}{{/crossLink}} is used.
* </p>
* @param {Object} object
* The object to which a new {{#crossLink "ProAct.ProxyProperty"}}{{/crossLink}} instance should be provided.
* @param {String} property
* The field of the <i>object</i> to turn into a {{#crossLink "ProAct.ProxyProperty"}}{{/crossLink}}.
* @param {ProAct.Property} meta
* The target {{#crossLink "ProAct.Property"}}{{/crossLink}} of the {{#crossLink "ProAct.ProxyProperty"}}{{/crossLink}} to be created.
* @return {ProAct.ProxyProperty}
* A {{#crossLink "ProAct.ProxyProperty"}}{{/crossLink}} instance provided by <i>this</i> provider.
*/
provide: function (queueName, object, property, meta) {
return new P.PXP(queueName, object, property, meta);
}
});
P.PP.registerProvider(new P.ProxyPropertyProvider());
P.PP.registerProvider(new P.SimplePropertyProvider());
P.PP.registerProvider(new P.AutoPropertyProvider());
P.PP.registerProvider(new P.ObjectPropertyProvider());