import { isNilOrEmpty, isObject, notNilEmpty } from 'qx-util'; import { IPSModelObject } from './ipsmodel-object'; import { IPSModelService } from './ipsmodel-service'; import { ModelServiceStore } from './core'; import { IPSModelServiceProxy } from './ipsmodel-service-proxy'; import { IPSAppDataEntity, IPSAppView, IPSControl, IPSDEServiceAPIRS } from './exports'; import { GlobalHooks } from './core/hooks'; /** * 模型服务 * * @export * @abstract * @class PSModelServiceImplBaseBase * @implements {IPSModelService} */ export abstract class PSModelServiceImplBaseBase implements IPSModelService { /** * 数据缓存对象 * * @author chitanda * @date 2021-12-26 16:12:44 * @protected * @type {ModelServiceStore} */ protected store: ModelServiceStore = new ModelServiceStore(); /** * Creates an instance of PSModelServiceImplBaseBase. * * @author chitanda * @date 2021-12-26 17:12:03 * @param {(modelPath: string) => IModel} loadModel 加载模型方法 */ constructor(protected loadModel: (modelPath: string) => IModel) { this.onInit(); } /** * 获取根节点模型对象,如: 系统 or 应用 * * @author chitanda * @date 2022-08-09 10:08:00 * @return {*} {IPSModelObject} */ getRootModel(): IPSModelObject { throw new Error('Method not implemented.'); } /** * 初始化 * * @author chitanda * @date 2022-03-06 17:03:25 */ onInit(): void {} /** * 模型缓存 * * @author chitanda * @date 2022-08-09 10:08:45 * @return {*} {ModelServiceStore} */ getStore(): ModelServiceStore { return this.store; } /** * 获取模型对象 * * @param {string} cls * @param {string} strPath * @return {*} {Promise} */ getPSModel(cls: string, strPath: string, refObj?: IModel, relatedPSModelObject?: IPSModelObject): IPSModelObject { // 从缓存获取 const iPSModelObject = this.store.modelObject.get(strPath); if (iPSModelObject != null) { return iPSModelObject; } const model = this.loadModel(strPath); if (model) { // 创建模型对象 const psModelObj = this.createPSModelObject(cls, refObj, relatedPSModelObject); if (psModelObj != null) { const iPSModelService = this.getPSModelService(cls, psModelObj); psModelObj.init(iPSModelService, strPath, model, relatedPSModelObject); this.store.setModelCache(cls, strPath, psModelObj); return psModelObj!; } throw new Error(`模型对象[${cls}]创建失败!`); } throw new Error(`模型[${strPath}]加载失败!`); } /** * 根据类型建立模型对象 * * @protected * @param {IPSModelObject} parentPSModelObject * @param {string} cls * @param {IModel} [objNode] * @return {*} {IPSModelObject} */ protected createPSModelObject(cls: string, objNode?: IModel, parentPSModelObject?: IPSModelObject): IPSModelObject { return this.onCreatePSModelObject(parentPSModelObject!, cls, objNode)!; } /** * 创建指定对象 * * @protected * @param {IPSModelObject} _parentPSModelObject * @param {string} _cls * @param {IModel} [_objNode] * @return {*} {IPSModelObject} */ protected onCreatePSModelObject(_parentPSModelObject: IPSModelObject, _cls: string, _objNode?: IModel): IPSModelObject | null { throw new Error(`模型对象[${_cls}]创建失败!`); } /** * 根据类型,获取模型服务 * * @author chitanda * @date 2021-12-26 15:12:25 * @protected * @param {string} cls * @param {IPSModelObject} [modelObject] * @return {*} {IPSModelService} */ protected getPSModelService(cls: string, modelObject?: IPSModelObject): IPSModelService { if (modelObject) { const iPSModelService = this.store.modelService.get(modelObject.cls); if (iPSModelService == null) { const iPSModelServiceProxy = this.createPSModelServiceProxy(cls, modelObject); if (iPSModelServiceProxy != null) { iPSModelServiceProxy.init(this, modelObject.cls); this.store.modelService.set(modelObject.cls, iPSModelServiceProxy); return iPSModelServiceProxy; } this.store.modelService.set(modelObject.cls, this); return this; } return iPSModelService; } return this; } /** * 根据类型创建模型代理类 * * @protected * @param {string} _cls * @param {IPSModelObject} _modelObject * @return {*} {IPSModelServiceProxy} */ protected createPSModelServiceProxy(_cls: string, _modelObject: IPSModelObject): IPSModelServiceProxy | null { return null; } /** * 根据路径获取模型 * * @author chitanda * @date 2021-12-26 17:12:50 * @param {IPSModelObject} _relatedPSModelObject * @param {string} filePath * @return {*} {IModel} */ getModel(_relatedPSModelObject: IPSModelObject, filePath: string): IModel { return this.loadModel(filePath); } /** * 查找指定模型 * * @author chitanda * @date 2021-06-08 20:06:44 * @param {IPSModelObject} relatedPSModelObject 相关模型 * @param {string} cls 类型标识 * @param {IModel} obj 模型 * @param {string} [strTag] 方法标识 * @return {*} {IPSModelObject} */ getPSModel4(relatedPSModelObject: IPSModelObject, cls: string, obj: IModel, strTag?: string): IPSModelObject { const modelObject = GlobalHooks.getModel4.call(relatedPSModelObject, cls, obj, strTag); if (modelObject) { return modelObject; } try { const bModelRef = obj.modelref || false; if (bModelRef) { if (notNilEmpty(obj.path)) { const strPath = obj.path; return this.getPSModel(cls, strPath, obj, relatedPSModelObject); } // 相对父模型 if (relatedPSModelObject != null) { return relatedPSModelObject.getChildPSModelObject(cls, obj, strTag); } } else { const path = obj.path || obj.dynaModelFilePath; if (notNilEmpty(path)) { const strPath = path; const iPSModelObject = this.store.modelObject.get(strPath); if (iPSModelObject == null) { const t = this.createPSModelObject(cls, obj, relatedPSModelObject); this.store.setModelCache(cls, strPath, t); t.init(this.getPSModelService(cls, t), '', obj, relatedPSModelObject); return t; } return iPSModelObject; } const t = this.createPSModelObject(cls, obj, relatedPSModelObject); t.init(this.getPSModelService(cls, t), '', obj, relatedPSModelObject); return t; } } catch (err: any) { throw new Error(`异常: ${err.message},类型「${cls}」`); } throw new Error(`类型「${cls}」模型创建异常`); } /** * 从集合里边提取,符合目标key的对象 * * @param {IPSModelObject} _relatedPSModelObject 相关模型 * @param {string} cls 目标对象 * @param {IPSModelObject[]} list 目标集合 * @param {*} data 需要查找的key * @return {*} */ getPSModel5(_relatedPSModelObject: IPSModelObject, cls: string, list: IPSModelObject[], data: string | IModel) { if (list == null || data == null) { if (data != null) { const strTag = this.getPSModelTag(cls, data); throw new Error(`无法获取指定模型[${cls}],标识为[${strTag}]`); } else { throw new Error(`无法获取指定模型[${cls}],没有指定标识`); } } const strTag: string = this.getPSModelTag(cls, data); for (const item of list) { if (this.testPSModel(cls, item, strTag)) { return item; } } throw new Error(`无法获取指定模型[${cls}],标识为[${strTag}]`); } /** * 测试复合目标对象 * * @protected * @param {string} _cls * @param {IPSModelObject} obj * @param {string} strTag * @return {*} {boolean} */ protected testPSModel(_cls: string, obj: IPSModelObject, strTag: string): boolean { if (notNilEmpty(strTag) && notNilEmpty(obj)) { switch (strTag) { case obj.id: // case obj.modelPath: // case obj.codeName: // case obj.name: return true; default: return false; } } return false; } /** * 获取模型标识 * * @protected * @param {string} cls * @param {(string | IModel)} objKey * @return {*} {string} */ protected getPSModelTag(cls: string, objKey: string | IModel): string { if (typeof objKey === 'string') { return objKey as string; } if (isObject(objKey)) { const obj = objKey as IModel; if (obj.modelref === true) { let strTag = obj.path; if (isNilOrEmpty(strTag)) { strTag = obj.id; if (isNilOrEmpty(strTag)) { throw new Error(`无法计算模型[${cls}]标识`); } } return strTag; } let strTag = obj.dynaModelFilePath; if (notNilEmpty(strTag)) { return strTag; } strTag = obj.codeName; if (notNilEmpty(strTag)) { return strTag; } strTag = obj.name; if (notNilEmpty(strTag)) { return strTag; } } throw new Error(`无法计算模型[${cls}]标识`); } /** * * * @param {IModel} obj * @return {*} {IModel} */ getRealObjectNode(obj: IModel): IModel { return obj; } /** * 查找子模型 * * @author chitanda * @date 2022-10-20 11:10:16 * @param {IPSModelObject} relatedPSModelObject * @param {string} cls * @param {IModel} obj * @param {string} strTag * @return {*} {IPSModelObject} */ getChildPSModelObject(relatedPSModelObject: IPSModelObject, cls: string, obj: IModel, strTag: string): IPSModelObject { const modelObject = GlobalHooks.getChildPSModelObject.call(relatedPSModelObject, cls, obj, strTag); if (modelObject) { return modelObject; } throw new Error('getChildPSModelObject Method not implemented.'); } /** * 获取指定类型父模型,如果本身模型符合接口返回自身 * * @param {IPSModelObject} relatedPSModelObject * @param {string} cls * @return {*} {IPSModelObject} */ getParentPSModelObject(relatedPSModelObject: IPSModelObject, cls: string): IPSModelObject; getParentPSModelObject(relatedPSModelObject: IPSModelObject, cls: string, tryMode?: boolean): IPSModelObject; getParentPSModelObject(relatedPSModelObject: IPSModelObject, cls: string, tryMode = true): IPSModelObject { const t = this.getParentPSModelObject2(relatedPSModelObject, cls); if (t == null) { // 应用 if (cls === 'app.IPSApplication') { if (relatedPSModelObject.instanceof('app.IPSApplication')) { return relatedPSModelObject; } } // 实体 else if (cls === 'dataentity.IPSDataEntity') { if (relatedPSModelObject.instanceof('dataentity.IPSDataEntity')) { return relatedPSModelObject; } const ipsAppDataEntity = this.getParentPSModelObject(relatedPSModelObject, 'app.dataentity.IPSAppDataEntity') as IPSAppDataEntity; if (ipsAppDataEntity) { return ipsAppDataEntity.getPSDataEntityMust(); } } // 应用实体 else if (cls === 'app.dataentity.IPSAppDataEntity') { if (relatedPSModelObject.instanceof('control.IPSControl')) { return (relatedPSModelObject as IPSControl).getPSAppDataEntityMust(); } if (relatedPSModelObject.instanceof('app.view.IPSAppView')) { return (relatedPSModelObject as IPSAppView).getPSAppDataEntityMust(); } const ctrl = this.getParentPSModelObject(relatedPSModelObject, 'control.IPSControl', false) as IPSControl; if (ctrl) { return ctrl.getPSAppDataEntityMust(); } const view = this.getParentPSModelObject(relatedPSModelObject, 'app.view.IPSAppView', false) as IPSAppView; if (view) { return view.getPSAppDataEntityMust(); } } // 实体服务接口 else if (cls === 'dataentity.service.IPSDEServiceAPI') { const iPSDEServiceAPIRS = this.getParentPSModelObject(relatedPSModelObject, 'dataentity.service.IPSDEServiceAPIRS') as IPSDEServiceAPIRS; if (iPSDEServiceAPIRS) { return iPSDEServiceAPIRS.getMinorPSDEServiceAPIMust(); } if (relatedPSModelObject.instanceof('dataentity.service.IPSDEServiceAPIMethod')) { const p = relatedPSModelObject.getParentPSModelObject(); if (p && p.instanceof('dataentity.service.IPSDEServiceAPIRS')) { return (p as IPSDEServiceAPIRS).getMinorPSDEServiceAPIMust(); } } } if (tryMode) { throw new Error(`无法从模型[${relatedPSModelObject.cls}]获取指定类型[${cls}]父模型`); } } return t as IPSModelObject; } protected getParentPSModelObject2(relatedPSModelObject: IPSModelObject, cls: string): IPSModelObject | null { if (relatedPSModelObject) { if (relatedPSModelObject.instanceof(cls)) { return relatedPSModelObject; } const p = relatedPSModelObject.getParentPSModelObject(); if (p) { return this.getParentPSModelObject2(p, cls); } } return null; } getFirstPSModelFilePath(relatedPSModelObject: IPSModelObject): string | null { const strFilePath = relatedPSModelObject.modelFilePath; if (notNilEmpty(strFilePath)) { return strFilePath!; } if (relatedPSModelObject.getParentPSModelObject() != null) { return this.getFirstPSModelFilePath(relatedPSModelObject.getParentPSModelObject()); } return null; } }