1 // ==========================================================================
  2 // Project:   The M-Project - Mobile HTML5 Application Framework
  3 // Copyright: (c) 2010 M-Way Solutions GmbH. All rights reserved.
  4 //            (c) 2011 panacoda GmbH. All rights reserved.
  5 // Creator:   Sebastian
  6 // Date:      18.11.2010
  7 // License:   Dual licensed under the MIT or GPL Version 2 licenses.
  8 //            http://github.com/mwaylabs/The-M-Project/blob/master/MIT-LICENSE
  9 //            http://github.com/mwaylabs/The-M-Project/blob/master/GPL-LICENSE
 10 // ==========================================================================
 11 
 12 m_require('core/utility/logger.js');
 13 
 14 /**
 15  * @class
 16  *
 17  * M.ModelAttribute encapsulates all meta information about a model record's property:
 18  * * is it required?
 19  * * what data type is it of? (important for mapping to relational database schemas)
 20  * * what validators shall be applied
 21  * All M.ModelAttributes for a model record are saved under {@link M.Model#__meta} property of a model.
 22  * Each ModelAttribute is saved with the record properties name as key.
 23  * That means:
 24  *
 25  * model.record[propA] is the value of the property.
 26  * model.__meta[propA] is the {@link M.ModelAttribute} object for the record property.
 27  *
 28  * @extends M.Object
 29  */
 30 M.ModelAttribute = M.Object.extend(
 31 /** @scope M.ModelAttribute.prototype */ {
 32 
 33     /**
 34      * The type of this object.
 35      *
 36      * @type String
 37      */
 38     type: 'M.ModelAttribute',
 39 
 40     /**
 41      * The data type for the model record property.
 42      * Extremely important e.g. to map model to relational database table.
 43      *
 44      * @type String
 45      */
 46     dataType: null,
 47 
 48     /**
 49      * Indicates whether this property is required to be set before persisting.
 50      * If YES, then automatically @link M.PresenceValidator is added to the property, to check the presence.
 51      * 
 52      * @type Boolean
 53      */
 54     isRequired: NO,
 55 
 56     /**
 57      * Indicates whether an update has been performed on this property with the set method or not.
 58      * @type Boolean
 59      */
 60     isUpdated: NO,
 61 
 62     /**
 63      * Array containing all validators for this model record property.
 64      * E.g. [@link M.PresenceValidator, @link M.NumberValidator]
 65      * @type Object
 66      */
 67     validators: null,
 68 
 69     /**
 70      * Record properties that define references have their referenced entity saved here.
 71      * @type Object
 72      */
 73     refEntity: null,
 74 
 75     /**
 76      * Iterates over validators array and calls validate on each validator with the param object passed to the validator.
 77      * @param {Object} obj The parameter object containing the model id, the record as M.ModelAttribute object and the value of the property.
 78      * @returns {Boolean} Indicates wheter the property is valid (YES|true) or invalid (NO|false).
 79      */
 80     validate: function(obj) {
 81         var isValid = YES;
 82         for (var i in this.validators) {
 83             if(!this.validators[i].validate(obj)) {
 84                isValid = NO; 
 85             }
 86         }
 87         return isValid;
 88     }
 89 });
 90 
 91 //
 92 // CLASS METHODS
 93 //
 94 
 95 /**
 96  * Returns a model attribute.
 97  *
 98  * @param dataType The data type of the attribute: e.g. String 
 99  * @param opts options for the attribute, such as defaultValue, isRequired flag, etc. ...
100  * @returns {Object} {@link M.ModelAttribute} object
101  */
102 M.ModelAttribute.attr = function(dataType, opts) {
103     //console.log('attr in model_attribute');
104     if (!opts) {
105         opts = {};
106     }
107     if (!opts.dataType) {
108         opts.dataType = dataType || 'String';
109     }
110 
111     /* if validators array is not set and attribute is required, define validators as an empty array, (this is for adding M.PresenceValidator automatically */
112     if (!opts.validators && opts.isRequired) {
113         opts.validators = [];
114     }
115 
116     /* if model attribute is required, presence validator is automatically inserted */
117     if (opts.isRequired) {
118         /* check if custom presence validator has been added to validators array, if not add the presence validator*/
119         if( _.select(opts.validators, function(v){return v.type === 'M.PresenceValidator'}).length === 0) {
120             opts.validators.push(M.PresenceValidator);
121         }
122     }
123     return this.extend(opts);
124 };