base-domain
Version:
simple module to help build Domain-Driven Design
383 lines (292 loc) • 9.05 kB
JavaScript
var Base, BaseFactory,
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
hasProp = {}.hasOwnProperty;
Base = require('./base');
/**
Base factory class of DDD pattern.
create instance of model
the parent "Base" class just simply gives a @getFacade() method.
@class BaseFactory
@extends Base
@module base-domain
*/
BaseFactory = (function(superClass) {
extend(BaseFactory, superClass);
/**
model name to handle
@property modelName
@static
@protected
@type String
*/
BaseFactory.modelName = null;
/**
name of dict model to create dict of @modelName
@property dictModelName
@static
@protected
@type String
*/
BaseFactory.dictModelName = null;
/**
get anonymous factory class
@method getAnonymousClass
@param {String} modelName
@return {Function}
*/
BaseFactory.getAnonymousClass = function(modelName) {
var AnonymousFactory;
AnonymousFactory = (function(superClass1) {
extend(AnonymousFactory, superClass1);
function AnonymousFactory() {
return AnonymousFactory.__super__.constructor.apply(this, arguments);
}
AnonymousFactory.modelName = modelName;
AnonymousFactory.isAnonymous = true;
return AnonymousFactory;
})(BaseFactory);
return AnonymousFactory;
};
/**
constructor
@constructor
*/
function BaseFactory() {}
/**
get model class this factory handles
@method getModelClass
@return {Function}
*/
BaseFactory._ModelClass = void 0;
BaseFactory.prototype.getModelClass = function() {
return this._ModelClass != null ? this._ModelClass : this._ModelClass = this.getFacade().getModel(this.constructor.modelName);
};
/**
create empty model instance
@method createEmptyModel
@return {BaseModel}
*/
BaseFactory.prototype.createEmptyModel = function() {
return this.createFromObject({});
};
BaseFactory.prototype.createEmpty = function() {
return this.createFromObject({});
};
/**
create instance of model class by plain object
for each prop, values are set by Model#set(prop, value)
@method createFromObject
@public
@param {Object} obj
@param {BaseModel} baseModel fallback properties
@return {BaseModel} model
*/
BaseFactory.prototype.createFromObject = function(obj) {
var ModelClass, model, prop, propInfo, value;
ModelClass = this.getModelClass();
if (obj instanceof ModelClass) {
return obj;
}
obj = this.beforeCreateFromObject(obj);
if ((obj == null) || typeof obj !== 'object') {
return null;
}
model = new ModelClass();
for (prop in obj) {
if (!hasProp.call(obj, prop)) continue;
value = obj[prop];
this.setValueToModel(model, prop, value);
}
propInfo = ModelClass.getPropInfo();
for (prop in propInfo.dic) {
if (model[prop] != null) {
continue;
}
this.setEmptyValueToModel(model, prop, propInfo);
}
return this.afterCreateModel(model);
};
/**
set value to model in creation
@method setValueToModel
@private
*/
BaseFactory.prototype.setValueToModel = function(model, prop, value) {
var typeInfo;
typeInfo = model.getTypeInfo(prop);
switch (typeInfo != null ? typeInfo.name : void 0) {
case 'MODEL_LIST':
return this.setSubModelListToModel(model, prop, value);
case 'MODEL':
return this.setSubModelToModel(model, prop, value);
case 'MODEL_DICT':
return this.setSubModelDictToModel(model, prop, value);
default:
return model.setNonEntityProp(prop, value);
}
};
/**
set empty values to model in creation
@method setEmptyValueToModel
@private
*/
BaseFactory.prototype.setEmptyValueToModel = function(model, prop, propInfo) {
var typeInfo;
typeInfo = propInfo.getTypeInfo(prop);
switch (typeInfo.name) {
case 'MODEL':
if (propInfo.isEntityProp(prop)) {
return this.fetchEntityProp(model, prop, typeInfo);
} else {
return this.createEmptyNonEntityProp(model, prop, typeInfo);
}
break;
case 'MODEL_LIST':
return this.setSubModelListToModel(model, prop, null);
case 'MODEL_DICT':
return this.setSubModelDictToModel(model, prop, null);
default:
return model[prop] = void 0;
}
};
/**
creates list and set it to the model
@method setSubModelListToModel
@private
*/
BaseFactory.prototype.setSubModelListToModel = function(model, prop, value) {
var list, listModelName, subModelFactory, subModelName, typeInfo;
typeInfo = model.getTypeInfo(prop);
subModelName = typeInfo.model;
subModelFactory = this.getFacade().createFactory(subModelName, true);
listModelName = typeInfo.listName;
list = subModelFactory.createList(listModelName, value);
model.setNonEntityProp(prop, list);
};
/**
set submodel to the prop
@method setSubModelToModel
@private
*/
BaseFactory.prototype.setSubModelToModel = function(model, prop, value) {
var SubModel, subModelFactory, subModelName, useAnonymousFactory;
subModelName = model.getTypeInfo(prop).model;
useAnonymousFactory = true;
subModelFactory = this.getFacade().createFactory(subModelName, useAnonymousFactory);
SubModel = subModelFactory.getModelClass();
if (!(value instanceof SubModel)) {
value = subModelFactory.createFromObject(value);
}
if (SubModel.isEntity) {
model.setEntityProp(prop, value);
} else {
model.setNonEntityProp(prop, value);
}
};
/**
set submodel dict to the prop
@method setSubModelToModel
@private
*/
BaseFactory.prototype.setSubModelDictToModel = function(model, prop, value) {
var dict, dictModelName, subModelFactory, subModelName, typeInfo;
typeInfo = model.getTypeInfo(prop);
subModelName = typeInfo.model;
subModelFactory = this.getFacade().createFactory(subModelName, true);
dictModelName = typeInfo.dictName;
dict = subModelFactory.createDict(dictModelName, value);
model.setNonEntityProp(prop, dict);
};
/**
fetch submodel(s) by id
available only when repository of submodel implements 'getByIdSync'
(MasterRepository implements one)
@method fetchEntityProp
@private
*/
BaseFactory.prototype.fetchEntityProp = function(model, prop, typeInfo) {
var Repository, e, id, idPropName, repository, subModel;
idPropName = typeInfo.idPropName;
try {
Repository = this.getFacade().getRepository(typeInfo.model);
if (!Repository.storeMasterTable) {
return;
}
repository = new Repository();
if (!repository.getByIdSync) {
return;
}
} catch (_error) {
e = _error;
return;
}
id = model[idPropName];
subModel = repository.getByIdSync(id);
if (subModel) {
return model.setEntityProp(prop, subModel);
}
};
/**
create empty non-entity model and set to the prop
@method createEmptyNonEntityProp
@private
*/
BaseFactory.prototype.createEmptyNonEntityProp = function(model, prop, typeInfo) {
var factory, submodel;
factory = this.getFacade().createFactory(typeInfo.model, true);
submodel = factory.createEmpty();
return model.setNonEntityProp(prop, submodel);
};
/**
modify plain object before @createFromObject(obj)
@method beforeCreateFromObject
@protected
@abstract
@param {Object} obj
@return {Object} obj
*/
BaseFactory.prototype.beforeCreateFromObject = function(obj) {
return obj;
};
/**
modify model after createFromObject(obj), createEmptyModel()
@method afterCreateModel
@protected
@abstract
@param {BaseModel} model
@return {BaseModel} model
*/
BaseFactory.prototype.afterCreateModel = function(model) {
return model;
};
/**
create model list
@method createList
@public
@param {String} listModelName model name of list
@param {any} obj
@return {BaseList} list
*/
BaseFactory.prototype.createList = function(listModelName, obj) {
var ListFactory, listFactory;
ListFactory = this.getFacade().constructor.ListFactory;
listFactory = ListFactory.create(listModelName, this);
return listFactory.createFromObject(obj);
};
/**
create model dict
@method createDict
@public
@param {String} dictModelName model name of dict
@param {any} obj
@return {BaseDict} dict
*/
BaseFactory.prototype.createDict = function(dictModelName, obj) {
var DictFactory, dictFactory;
DictFactory = this.getFacade().constructor.DictFactory;
dictFactory = DictFactory.create(dictModelName, this);
return dictFactory.createFromObject(obj);
};
return BaseFactory;
})(Base);
module.exports = BaseFactory;