UNPKG

sumeru

Version:

A Realtime Javascript RIA Framework For Mobile WebApp

416 lines (364 loc) 20.3 kB
var runnable = function(fw, getDbCollectionHandler , ObjectId){ //FIXME 引入library库能力 //var objUtils = require(__dirname + '/../library/obj.js'); var serverCollection = function(modelName){ if (typeof modelName == 'undefined') { return null; }; //publish基于的上层modelName this.baseModel = modelName; } serverCollection.prototype = { ObjectId : ObjectId, _getWhereCondition : function(whereMap){ var _whereMap = {}; if(typeof whereMap == 'undefined'){ } else if(Object.prototype.toString.call(whereMap) == '[object Object]'){ //否则就是包含多个key value的object _whereMap = whereMap; } return _whereMap; }, resolveRef : function(items, callback){ //标记本层递归是否存在引用。 var that = this, hasRef = false, refCount = 0; for (var i = 0, l = items.length; i < l; i++){ for (var j in items[i]){ //refence只会存放在数组或object对象里 if (Object.prototype.toString.call(items[i][j]) != '[object Array]' &&Object.prototype.toString.call(items[i][j]) != '[object Object]') { continue; }; var candidate = items[i][j], refInfo; if (Object.prototype.toString.call(items[i][j]) == '[object Array]'){ for (var k = 0; k < candidate.length; k++) { if (candidate[k].isReference && candidate[k].val) { refInfo = candidate[k].val.split('::'); if(refInfo.length == 4 && refInfo[0] == '' && refInfo[1] == 'referenceID'){ hasRef = true; refCount++; var refModel = refInfo[2].replace(/Model\./, ''), refId = refInfo[3]; (function(i, j, k, refModel, refId){ var item = items[i][j][k]; getDbCollectionHandler(refModel, function onGetDBCollectionHandler(err, handler){ if (err != null) { throw err; } if (handler == null) { throw new ReferenceError("'handler' is null"); } handler.find({smr_id : ObjectId(refId)},{}/*,{limit:1}*/).toArray(function(err, subItems){ if(err){ return callback(err, []); } that.resolveRef(subItems, function(err, results){ if (results.length == 0) { items[i][j][k] = ''; } else { items[i][j][k] = results[0]; } if (--refCount == 0) { callback(err, items); }; }); }); }); })(i, j, k, refModel, refId); } } //end if.isReference }; }else{ if (candidate.isReference && candidate.val) { refInfo = candidate.val.split('::'); if(refInfo.length == 4 && refInfo[0] == '' && refInfo[1] == 'referenceID'){ hasRef = true; refCount++; var refModel = refInfo[2].replace(/Model\./, ''), refId = refInfo[3]; (function(i, j, refModel, refId){ var item = items[i][j]; getDbCollectionHandler(refModel, function onGetDBCollectionHandler(err, handler){ if (err != null) { throw err; } if (handler == null) { throw new ReferenceError("'handler' is null"); } handler.find({smr_id : ObjectId(refId)}, {}/*, {limit:1}*/).toArray(function(err, subItems){ if(err){ return callback(err, []); } that.resolveRef(subItems, function(err, results){ if (results.length == 0) { items[i][j] = ''; } else { items[i][j] = results[0]; } if (--refCount == 0) { callback(err, items); }; }); }); }); })(i, j, refModel, refId); } } //end if.isReference } } } if (hasRef === false) { callback(null, items); }; }, /** * @param options {sort : {'time' : -1}, limit : (pagesize + 1) * 5, skip : pagesize * 5} */ find : function(whereMap, options, callback, modelName){ if (arguments.length == 2) { callback = options; options = {}; }; var where = this._getWhereCondition.call(this, whereMap), that = this; getDbCollectionHandler(modelName?modelName:this.baseModel, function onGetDBCollectionHandler(err, handler){ if (err != null) { faildCallback.call(this, "data_write_from_server_dberror", err); throw err; } if (handler == null) { faildCallback.call(this, "data_write_from_server_dberror", "'handler' is null"); throw new ReferenceError("'handler' is null"); } handler.find(where, {}, options).toArray(function(err, items){ if (err) { return callback(err, []); }; //fw.dev('before resolve', JSON.stringify(items)); that.resolveRef(items, callback); }); }); return true; }, /** * External Find, 三方数据查询 * */ extfind : function(/** pubname, arg1, arg2, arg3, callback */){ var args = Array.prototype.slice.call(arguments); var modelName = this.baseModel; var pubname = args.shift(); var callback = args.pop(); fw.external.doFetch(modelName, pubname, args, callback); }, count : function(whereMap, callback, modelName){ var where = this._getWhereCondition.call(this, whereMap), that = this; getDbCollectionHandler(modelName?modelName:this.baseModel, function onGetDBCollectionHandler(err, handler){ if (err != null) { faildCallback.call(this, "data_write_from_server_dberror", err); throw err; } if (handler == null) { faildCallback.call(this, "data_write_from_server_dberror", "'handler' is null"); throw new ReferenceError("'handler' is null"); } handler.count(where, function(err, count){ if (err) { return callback(err, 0); }; callback(null, count); }); }); return true; }, insert: function(structData, successCallback, faildCallback, modelName){ var modelName = modelName || this.baseModel; var doIt = (function(getDbCollectionHandler,modelName,faildCallback,successCallback,structData){ return function(){ getDbCollectionHandler(modelName, function onGetDBCollectionHandler(err, handler){ if (err != null) { faildCallback.call(this, "data_write_from_server_dberror", err); throw err; } if (handler == null) { faildCallback.call(this, "data_write_from_server_dberror", "'handler' is null"); throw new ReferenceError("'handler' is null"); } handler.insert(structData, null, successCallback); }); }; })(getDbCollectionHandler,modelName,faildCallback,successCallback,structData); this.runWithValidation(structData, modelName, doIt, faildCallback); }, update: function(selector, structData, successCallback, faildCallback, modelName){ //fw.dev("updata::",structData); var modelName = modelName || this.baseModel; var doIt = (function(getDbCollectionHandler,modelName,faildCallback,successCallback,structData){ return function(){ getDbCollectionHandler(modelName, function onGetDBCollectionHandler(err, handler){ if (err != null) { faildCallback.call(this, "data_write_from_server_dberror", err); throw err; } if (handler == null) { faildCallback.call(this, "data_write_from_server_dberror", "'handler' is null"); throw new ReferenceError("'handler' is null"); } handler.update(selector, { $set : structData }, null, successCallback); }); }; })(getDbCollectionHandler,modelName,faildCallback,successCallback,structData); this.runWithValidation(structData, modelName, doIt, faildCallback); }, remove: function(selector, successCallback, faildCallback, modelName){ var modelName = modelName || this.baseModel; getDbCollectionHandler(modelName, function onGetDBCollectionHandler(err, handler){ if (err != null) { throw err; } if (handler == null) { throw new ReferenceError("'handler' is null"); } handler.remove(selector, null, successCallback); }); }, getDbCollectionHandler: function(){ return getDbCollectionHandler; }, /** * 返回验证失败的key value validation */ runWithValidation : function(dataMap, modelName, successCallback, faildCallback){ if(!fw.config.get('serverValidation')){successCallback();return;}; var successObjs = [],//successObjs 现在暂时存下来,不发送到客户端。 faildObjs = []; //validation分同步/异步,DB操作 和 validation结果 需要在同步和异步validation都结束之后才能做。 var cbHandler = Library.asyncCallbackHandler.create( function(){ if(faildObjs.length>0){ for(var i=0,ilen=faildObjs.length;i<ilen;i++){ faildObjs[i][fw.idField] = dataMap[fw.idField]; } fw.log("validation faild"); faildCallback.call(this, "data_write_from_server_validation", faildObjs); }else{ fw.dev("validation success"); faildCallback.call(this, "data_write_from_server_validation", faildObjs); successCallback(); } } ); cbHandler.add();// var oneField,label,validations,validation,validationMsg,type,value,resultObj; var _model = fw.server_model.getModelTemp(modelName); var createFaildObj = function(key,value,validationResult){ var _obj = {}; _obj["key"] = key; _obj["value"] = value; _obj["msg"] = validationResult["msg"]; return _obj; }; for(var p in dataMap){ oneField = _model[p]; if(typeof oneField != 'undefined'){ label = oneField["label"]||p; validation = oneField["validation"]; validationMsg = oneField["validationMsg"]; type = oneField["type"]; value = dataMap[p]; if(validation){ if(Library.objUtils.isString(validation)){ validations = validation.split("|"); }else{ validations = [validation]; } for(var i=0,len = validations.length;i<len;i++){ var _validation = validations[i]; //由于length是有参数的所以单独处理 var _lengthMatch = (new RegExp("([min,max]*length)\\[([0-9]+)[\\,]*([0-9]*)\\]")).exec(_validation); if(_lengthMatch){ if(_lengthMatch.length>=3){ _lengthMatch.shift(); _lengthMatch.unshift(value); _lengthMatch.unshift(p); _lengthMatch.unshift(label); var validationResult = fw.validation._svalidation.apply(this,_lengthMatch); if(validationResult){//这个分支不可能有asyn faildObjs.push(createFaildObj(p,value,validationResult)); } } }else{ if(fw.validation._isasynvali(_validation)){ cbHandler.add(); getDbCollectionHandler(modelName, (function(label,p,value,_validation,modelObj){ return function onGetDBCollectionHandler(err, handler){ if (err != null) { cbHandler.decrease(); throw err; }else if (handler == null) { cbHandler.decrease(); throw new ReferenceError("'handler' is null"); }else{ fw.validation._svalidation.call(handler,label,p,value,_validation, function(err,validationResult){ if(!err){ fw.dev("asyn validation end"); if(validationResult === true){ //验证通过 //faildCallback.call(this, "data_write_from_server_validation", validationResult); }else{ var resultObj = {}; resultObj.value = validationResult; resultObj.msg = fw.validation._getvalidationmsg(validationResult,label,_validation); faildObjs.push(createFaildObj(p,value,resultObj)) } }else{ faildCallback.call(this, "data_write_from_server_dberror", validationResult); } cbHandler.decrease(); },modelObj); } } })(label,p,value,_validation,Library.objUtils.extend({},dataMap))); }else{ var validationResult = fw.validation._svalidation.call(this,label,p,value,_validation); if(validationResult){ faildObjs.push(createFaildObj(p,value,validationResult)); } } } } }else if(type=="model"){ /*server 上暂无级联验证 }*/ } }else{ /** var value = dataMap[p]; faildObjs.push(createFaildObj(p,value,'没有定义这个字段。')); */ delete dataMap[p]; fw.dev("validation engine delete the undefined field "+p); } }; fw.dev("_+_+______________________+_+_+_+_+_+_+__++"); fw.dev(JSON.stringify(cbHandler)); fw.dev("_+_+______________________+_+_+_+_+_+_+__++"); cbHandler.enableCallback(); cbHandler.decrease(); } }; exports.create = serverCollection; } if(typeof module !='undefined' && module.exports){ module.exports = function(fw, getDbCollectionHandler , ObjectId){ runnable(fw, getDbCollectionHandler , ObjectId); return exports; } }