rutile
Version:
Factory automation for Mobile Enterprise.
359 lines (298 loc) • 9.39 kB
JavaScript
//
// {{entity}} Model
//
// segment : {{segment}}
// entity : {{entity}} (collection)
// collect : {{collectedID}}
//
// represent junction table
// case:
//
// var order = new OrderModel.getClass()
//
// var product1 = ProductModel.instance(pid1);
// var product2 = ProductModel.instance(pid2);
//
// var orderItem1 = new orderItem.getClass();
// orderItem.productID = product1.productID;
// orderItem.productName = product1.productName;
// orderItem.price = product1.price;
//
// var orderItem2 = new orderItem.getClass();
// orderItem.productID = product2.productID;
// orderItem.productName = product2.productName;
// orderItem.price = product2.price;
//
// var orderOrderItem = OrderOrderItem.instance(order.getID());
//
// // check instance type and collect its id
// orderOrderItem.add(orderItem1);
// orderOrderItem.add(orderItem2); // check instance type and collect its id
//
// order.save();
// orderOrderItem.save();
// orderItem1.save();
// orderItem2.save();
//
// case:
//
// var user = UserModel.instance(userID);
// var userGroup = UserGroup.instance(userID);
//
// var group1 = GroupModel.instance(gid1);
// var group2 = GruopModel.instance(gid2);
//
// userGroup.add(group1);
// userGroup.add(group2);
//
// userGroup.save();
//
//
//
// * * * * * * * * * * * * * * * * * * * *
// static vriables
// cache identifyer prefix
var MODEL_NAME = 'Model/{{segment}}/{{entity}}';
// {{APP_NAME}}
var {{APP_NAME}} = require('{{APP_NAME}}');
// Utils
var Utils = {{APP_NAME}}.getUtils();
// singleton instance of the Container for this segment
var ContainerFactory = {{APP_NAME}}.getContainerFactory();
var container = ContainerFactory.getContainer('{{segment}}');
// no search for collection
// sanitizer
var ModelSanitizerFactory = {{APP_NAME}}.getModelSanitizerFactory();
var Sanitizer = ModelSanitizerFactory.getSanitizer('{{segment}}/{{entity}}');
// validator
var ModelValidatorFactory = {{APP_NAME}}.getModelValidatorFactory();
var Validator = ModelValidatorFactory.getValidator('{{segment}}/{{entity}}');
// field manifest (also used as case convert tool)
// lower case : original definition
var FieldManifest = { {{#Align_colon}}
"{{#Lc_all}}{{collectorID}}{{/Lc_all}}" : "{{collectorID}}",
"{{#Lc_all}}{{collectedID}}{{/Lc_all}}" : "{{collectedID}}"
{{/Align_colon}}
};
var normalizeField = function(raw_results){
return Utils.normalizeField(FieldManifest,raw_results);
};
// * * * * * * * * * * * * * * * * * * * *
// static services
// you should call these method by 'apply' when using from instance(,prototype) method.
//
// instance service
//
var instantiate = function(id,options){
// check pooled instance in this context,
var instance = container.getPooledInstance(MODEL_NAME,id);
if( instance ){
return instance;
}
// create new for this context
var obj = new ModelConstructor(id,options);
return obj;
};
//
// data persistent implementations.
//
var insert = function(){
var sql = "insert into {{#Escape_reserved}}{{#Lc_first}}{{entity}}{{/Lc_first}}{{/Escape_reserved}} values ($1,$2)";
var collection = Object.keys(this.entity.collection);
var count = 0;
for( var i=0, len=collection.length; i<len; i++ ){
var result = container.db_sync_query(
sql,
[
this.entity.{{collectorID}},
collection[i]
]
);
count++;
}
return count;
};
var remove = function(){
var sql = "delete from {{#Escape_reserved}}{{#Lc_first}}{{entity}}{{/Lc_first}}{{/Escape_reserved}} where {{collectorID}}=$1";
var result = container.db_sync_query(
sql,
[this.entity.{{collectorID}}]
);
return result;
};
var load = function(){
var sql = "select * from {{#Escape_reserved}}{{#Lc_first}}{{entity}}{{/Lc_first}}{{/Escape_reserved}} where {{collectorID}}=$1";
var results = container.db_sync_query(
sql,
[this.entity.{{collectorID}}]
);
results = normalizeField(results);
for( var i=0, len=results.length; i<len; i++ ){
this.entity.collection[results[i].{{collectedID}}]=1;
}
};
var retrieve = function(options){
if( options.ignoreCache == true ){
load.apply(this); // retrieve from db
}else{
var cacheKey = MODEL_NAME + '/' + this.entity.{{collectorID}};
var json = container.cache_sync_get(cacheKey); // retrieve from cache
if( !json ){
load.apply(this);
this.save_cache(); // cache myself
}else{
var parsed = JSON.parse(json);
this.entity.collection = parsed.collection;
this.fresh = parsed.fresh;
}
}
};
// tell the container to commit current transaction
var requestCommit = function(){
this.modified = true;
container.requestCommit();
};
// * * * * * * * * * * * * * * * * * * * *
// cunstructor
function ModelConstructor(){
// instance variables
this.entity = {}; // raw instance of model entity, ensures name space
this.fresh = false; // true, if this entity is loaded from DB, false to be inserted when save()
this.modified = false; // when you modify model property, turn ture and commit requests alises to the container
this.entity.collection = {};
var id = arguments[0];
if( id )
{
// if an argument is defined, that should be an id.
this.entity.{{collectorID}} = id;
var options = {};
if( arguments[1] ){ options = arguments[1]; }
retrieve.apply(this,[{ignoreCache:options.ignoreCache}]); // call private method
}
else
{
// collection always requires key id
return false;
}
// pool this instance
container.setPooledInstance(MODEL_NAME,this.entity.{{collectorID}},this);
}
var Model = ModelConstructor.prototype;
// * * * * * * * * * * * * * * * * * * * *
// instance validation
Model.valid = function(){
return Validator.validate(this);
};
Model.isInstanceOf = function(name){
if( name == MODEL_NAME ){
return true;
}else{
return false;
}
};
// * * * * * * * * * * * * * * * * * * * *
// public data access and mutate api
// (read only) primary key
Model.__defineGetter__('{{collectorID}}', function(){
return this.entity.{{collectorID}};
});
Model.__defineGetter__('collection', function(){
return Object.keys(this.entity.collection);
});
Model.__defineSetter__('collection', function(collection){
this.entity.collection = {}; // init
var this_collection = this.entity.collection;
collection.map(
function({{collectedID}}){
var safe_{{collectedID}} = Sanitizer.sanitize('{{collectedID}}',{{collectedID}});
if( safe_{{collectedID}} ){
this_collection[safe_{{collectedID}}]=1;
}
}
);
requestCommit.apply(this);
});
// * * * * * * * * * * * * * * * * * * * *
// public collection api
Model.add = function(id){
this.entity.collection[id]=1;
requestCommit.apply(this);
};
Model.addEntity = function(entity){
if( entity.isInstanceOf('Model/{{{collectedEntity}}}') ){
this.entity.collection[entity.{{collectedID}}]=1;
requestCommit.apply(this);
}
};
Model.remove = function(id){
delete this.entity.collection[id];
requestCommit.apply(this);
};
Model.removeEntity = function(entity){
if( entity.isInstanceOf('Model/{{{collectedEntity}}}') ){
delete this.entity.collection[entity.{{collectedID}}];
requestCommit.apply(this);
}
};
// bulk setter (id array)
Model.restore = function(json){
this.entity.collection = {}; // init
var collection = json.collection;
var this_collection = this.entity.collection;
collection.map(
function(id){
this_collection[id]=1;
}
);
requestCommit.apply(this);
};
// bulk setter (entity array)
Model.restoreByEntities = function(items){
this.entity.collection = {}; // init
var this_collection = this.entity.collection;
items.map(
function(item){
if( item.isInstanceOf('Model/{{{collectedEntity}}}') ){
this_collection[item.{{collectedID}}]=1;
}
}
);
requestCommit.apply(this);
};
// * * * * * * * * * * * * * * * * * * * *
// public data persistent api
Model.save = function(){
this.save_cache();
if( this.fresh ){
insert.apply(this);
}else{
// db should be refreshed
remove.apply(this);
insert.apply(this);
}
};
Model.remove = function(){
this.remove_cache();
if( !this.fresh ){
remove.apply(this);
}
};
Model.save_cache = function(){
var cacheKey = MODEL_NAME + '/' + this.entity.{{collectorID}};
container.cache_sync_set(cacheKey,JSON.stringify(this.json()));
};
Model.remove_cache = function(){
var cacheKey = MODEL_NAME + '/' + this.entity.{{collectorID}};
container.cache_sync_del(cacheKey);
};
Model.json = function(){
var json = { collection : this.entity.collection };
json.fresh = this.fresh;
return json;
};
// * * * * * * * * * * * * * * * * * * * *
module.exports = {
getClass : ModelConstructor, // provide constructor
instance : instantiate, // create new instance
remove : remove, // remove entity from the collection
};