UNPKG

base-domain

Version:

simple module to help build Domain-Driven Design

343 lines (232 loc) 7.47 kB
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 ### class BaseFactory extends Base ###* model name to handle @property modelName @static @protected @type String ### @modelName: null ###* name of dict model to create dict of @modelName @property dictModelName @static @protected @type String ### @dictModelName: null ###* get anonymous factory class @method getAnonymousClass @param {String} modelName @return {Function} ### @getAnonymousClass: (modelName) -> class AnonymousFactory extends BaseFactory @modelName : modelName @isAnonymous: true return AnonymousFactory ###* constructor @constructor ### constructor: -> ###* get model class this factory handles @method getModelClass @return {Function} ### @_ModelClass: undefined getModelClass: -> @_ModelClass ?= @getFacade().getModel(@constructor.modelName) ###* create empty model instance @method createEmptyModel @return {BaseModel} ### createEmptyModel: -> @createFromObject({}) createEmpty: -> @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 ### createFromObject: (obj) -> ModelClass = @getModelClass() return obj if obj instanceof ModelClass obj = @beforeCreateFromObject obj if not obj? or typeof obj isnt 'object' return null model = new ModelClass() for own prop, value of obj @setValueToModel model, prop, value propInfo = ModelClass.getPropInfo() for prop of propInfo.dic continue if model[prop]? @setEmptyValueToModel model, prop, propInfo return @afterCreateModel model ###* set value to model in creation @method setValueToModel @private ### setValueToModel: (model, prop, value) -> typeInfo = model.getTypeInfo(prop) switch typeInfo?.name when 'MODEL_LIST' @setSubModelListToModel(model, prop, value) when 'MODEL' @setSubModelToModel(model, prop, value) when 'MODEL_DICT' @setSubModelDictToModel(model, prop, value) else # set normal props model.setNonEntityProp(prop, value) ###* set empty values to model in creation @method setEmptyValueToModel @private ### setEmptyValueToModel: (model, prop, propInfo) -> typeInfo = propInfo.getTypeInfo(prop) switch typeInfo.name when 'MODEL' if propInfo.isEntityProp(prop) @fetchEntityProp(model, prop, typeInfo) # trying to get entity by id else @createEmptyNonEntityProp(model, prop, typeInfo) when 'MODEL_LIST' @setSubModelListToModel(model, prop, null) when 'MODEL_DICT' @setSubModelDictToModel(model, prop, null) else model[prop] = undefined ###* creates list and set it to the model @method setSubModelListToModel @private ### setSubModelListToModel: (model, prop, value) -> typeInfo = model.getTypeInfo(prop) subModelName = typeInfo.model subModelFactory = @getFacade().createFactory(subModelName, on) listModelName = typeInfo.listName list = subModelFactory.createList(listModelName, value) model.setNonEntityProp prop, list return ###* set submodel to the prop @method setSubModelToModel @private ### setSubModelToModel: (model, prop, value) -> subModelName = model.getTypeInfo(prop).model useAnonymousFactory = on # if no factory is declared, altered one is used subModelFactory = @getFacade().createFactory(subModelName, useAnonymousFactory) SubModel = subModelFactory.getModelClass() if value not instanceof SubModel value = subModelFactory.createFromObject(value) if SubModel.isEntity model.setEntityProp(prop, value) else model.setNonEntityProp(prop, value) return ###* set submodel dict to the prop @method setSubModelToModel @private ### setSubModelDictToModel: (model, prop, value) -> typeInfo = model.getTypeInfo(prop) subModelName = typeInfo.model subModelFactory = @getFacade().createFactory(subModelName, on) dictModelName = typeInfo.dictName dict = subModelFactory.createDict(dictModelName, value) model.setNonEntityProp prop, dict return ###* fetch submodel(s) by id available only when repository of submodel implements 'getByIdSync' (MasterRepository implements one) @method fetchEntityProp @private ### fetchEntityProp: (model, prop, typeInfo) -> idPropName = typeInfo.idPropName try Repository = @getFacade().getRepository typeInfo.model return if not Repository.storeMasterTable repository = new Repository() return if not repository.getByIdSync catch e return id = model[idPropName] subModel = repository.getByIdSync(id) model.setEntityProp(prop, subModel) if subModel ###* create empty non-entity model and set to the prop @method createEmptyNonEntityProp @private ### createEmptyNonEntityProp: (model, prop, typeInfo) -> factory = @getFacade().createFactory typeInfo.model, true submodel = factory.createEmpty() model.setNonEntityProp(prop, submodel) ###* modify plain object before @createFromObject(obj) @method beforeCreateFromObject @protected @abstract @param {Object} obj @return {Object} obj ### beforeCreateFromObject: (obj) -> return obj ###* modify model after createFromObject(obj), createEmptyModel() @method afterCreateModel @protected @abstract @param {BaseModel} model @return {BaseModel} model ### afterCreateModel: (model) -> return model ###* create model list @method createList @public @param {String} listModelName model name of list @param {any} obj @return {BaseList} list ### createList: (listModelName, obj) -> ListFactory = @getFacade().constructor.ListFactory listFactory = ListFactory.create(listModelName, @) return listFactory.createFromObject obj ###* create model dict @method createDict @public @param {String} dictModelName model name of dict @param {any} obj @return {BaseDict} dict ### createDict: (dictModelName, obj) -> DictFactory = @getFacade().constructor.DictFactory dictFactory = DictFactory.create(dictModelName, @) return dictFactory.createFromObject obj module.exports = BaseFactory