11import commonMethod from './commonMethod.mixin'
2- const EventEmitter = require ( 'events' )
32import createInstance from 'appscript/module/createInstance.staticMethod'
43import { usingGenericInstance as populateInstancePropertyFromJson , usingThis as populateInstancePropertyFromJson_this } from 'appscript/module/populateInstancePropertyFromJson.method'
54import addStaticSubclassToClassArray from 'appscript/module/addStaticSubclassToClassArray.staticMethod'
65import { classDecorator as prototypeChainDebug } from 'appscript/module/prototypeChainDebug'
7- import { MultiplePrototypeChain } from 'appscript/module/multiplePrototypeChain'
8- import { add , execute , applyMixin } from 'appscript/utilityFunction/decoratorUtility.js'
6+ import { add , execute , applyMixin , conditional } from 'appscript/utilityFunction/decoratorUtility.js'
7+ import { extendedSubclassPattern } from 'appscript/utilityFunction/extendedSubclassPattern.js'
8+ import { superclassInstanceContextPattern } from 'appscript/utilityFunction/superclassInstanceContextPattern.js'
99import { mix } from 'mixwith'
1010
11+ function cacheInstance ( { cacheArrayName, keyArgumentName = 'key' } ) { // decorator + proxy
12+ return ( target , name , descriptor ) => {
13+ let method = target [ name ]
14+ descriptor . value = new Proxy ( method , {
15+ apply : async ( target , thisArg , argumentsList ) => {
16+ let [ { [ keyArgumentName ] : key } ] = argumentsList // extract key using the specified key parameter name in the method.
17+ let cacheArray = thisArg . instance [ cacheArrayName ] // Sub array of 'this.instance' in which instances are saved.
18+ let instance ;
19+ if ( key in cacheArray ) {
20+ instance = cacheArray [ key ]
21+ } else {
22+ instance = await target . apply ( thisArg , argumentsList )
23+ cacheArray [ key ] = instance // add to class cache
24+ }
25+ return instance
26+ }
27+ } )
28+ return descriptor
29+ }
30+ }
31+
1132/**
1233 * @class
1334 * @usage new instance is created for each check.
@@ -19,7 +40,7 @@ export default ({
1940} ) => {
2041 let mixinArray = [ /*commonMethod*/ ]
2142 let self =
22- @prototypeChainDebug
43+ @conditional ( { decorator : prototypeChainDebug , condition : process . env . SZN_DEBUG } )
2344 @add ( { to : 'static' } , {
2445 createInstance,
2546 populateInstancePropertyFromJson,
@@ -28,112 +49,34 @@ export default ({
2849 @add ( { to : 'prototype' } , {
2950 populateInstancePropertyFromJson_this
3051 } )
31- @execute ( { staticMethod : 'initializeStaticClass' } )
32- @applyMixin ( { mixin } )
52+ @conditional ( { condition : mixin , decorator : applyMixin ( { mixin } ) } )
53+ @extendedSubclassPattern . Superclass ( )
54+ @superclassInstanceContextPattern ( )
55+ @conditional ( { decorator : extendedSubclassPattern . Subclass ( ) , condition : ( methodInstanceName && Superclass ) } )
3356 class ReusableController extends mix ( Superclass ) . with ( ...mixinArray ) {
3457
35- static eventEmitter = new EventEmitter ( ) // i.e. new EventEmitter()
36- static extendedSubclass = {
37- static : { }
38- }
39-
40- static initializeStaticClass ( self ) {
41- // Mutation observer on array for debugging purposes.
42- // self.extendedSubclass.static = new Proxy(self.extendedSubclass.static, {
43- // set: function(target, property, value, receiver) {
44- // target[property] = value;
45- // console.log(self.extendedSubclass.static)
46- // return true;
47- // }
48- // })
49-
50- if ( methodInstanceName && Superclass && Superclass . eventEmitter ) {
51- super . eventEmitter . on ( 'initializationEnd' , ( ) => {
52- let ClassObject = { }
53- ClassObject [ `${ methodInstanceName } ` ] = self
54- super . addStaticSubclassToClassArray ( ClassObject )
55- } )
56- }
57- }
58-
59- static initializeStaticClassControllerLevel ( ) {
60- let Class = this
61- Class . eventEmitter . on ( 'initializationEnd' , ( ) => {
62- let ClassObject = { }
63- ClassObject [ `${ Class . name } ` ] = Class
64- Class . addStaticSubclassToClassArray ( ClassObject )
65- } )
66- }
67-
68- static createContext ( ...args ) {
69- let self = this // specific Controller that is a subclass of 'self' (ReusableController)
70- let contextInstance = new self ( false , ...args )
71-
72- // create a new list object for proxied refrence of subclasses
73- contextInstance . instanceExtendedSubclass = Object . keys ( self . extendedSubclass . static )
74- . reduce ( ( object , key ) => {
75- // add proxied subclass to the list
76- object [ key ] = MultiplePrototypeChain . newChainOnInstanceCreation ( {
77- Class : self . extendedSubclass . static [ key ] ,
78- contextInstance
79- } )
80- return object
81- } , { } )
82- return contextInstance
83- }
84-
85- static callSubclass ( name , args ) {
86- return Reflect . construct ( self . extendedSubclass . static [ name ] , args )
87- }
88-
89- /**
90- * Properties on instnace object (not on the prototype)
91- */
92- AppInstance ; // calling instance that contains the context
93- instance = {
94- nestedUnit : [ ] ,
95- unit : [ ] ,
96- }
97- // conditionTreeKey -> { Json data, properties }
98-
99- constructor ( skipConstructor = false , { portAppInstance} ) {
100- super ( true )
101- if ( skipConstructor ) return ;
102- if ( portAppInstance ) this . AppInstance = portAppInstance
103- }
104-
105- callSubclass ( name , args ) {
106- let contextInstance = this
107- return Reflect . construct ( contextInstance . instanceExtendedSubclass [ name ] , args )
108- }
109-
58+ @cacheInstance ( {
59+ cacheArrayName : 'nestedUnit' ,
60+ keyArgumentName : 'nestedUnitKey'
61+ } )
11062 async getNestedUnit ( { nestedUnitKey, additionalChildNestedUnit = [ ] , pathPointerKey = null } ) {
111- let nestedUnitInstance ;
112- if ( ! ( nestedUnitKey in this . instance . nestedUnit ) ) {
113- nestedUnitInstance = await this . callSubclass ( 'NestedUnit' , [ nestedUnitKey ] )
114- await nestedUnitInstance . initializeInstance ( )
115- // add children trees:
116- nestedUnitInstance . additionalChildNestedUnit = additionalChildNestedUnit
117- // add pathPointerKey to allow applying additional corresponding additional children.
118- nestedUnitInstance . pathPointerKey = pathPointerKey
119- // add to class cache
120- this . instance . nestedUnit [ nestedUnitKey ] = nestedUnitInstance
121- } else {
122- nestedUnitInstance = this . instance . nestedUnit [ nestedUnitKey ]
123- }
124- return nestedUnitInstance
63+ let instance = await this . callSubclass ( 'NestedUnit' , [ nestedUnitKey ] )
64+ await instance . initializeInstance ( )
65+ // add children trees:
66+ instance . additionalChildNestedUnit = additionalChildNestedUnit
67+ // add pathPointerKey to allow applying additional corresponding additional children.
68+ instance . pathPointerKey = pathPointerKey
69+ return instance
12570 }
12671
127- async getUnit ( { unitKey} ) {
128- let unitInstance ;
129- if ( ! ( unitKey in this . instance . unit ) ) {
130- unitInstance = await this . callSubclass ( 'Unit' , [ unitKey ] )
131- await unitInstance . initializeInstance ( )
132- this . instance . unit [ unitKey ] = unitInstance
133- } else {
134- unitInstance = this . instance . unit [ unitKey ]
135- }
136- return unitInstance
72+ @cacheInstance ( {
73+ cacheArrayName : 'unit' ,
74+ keyArgumentName : 'unitKey'
75+ } )
76+ async getUnit ( { unitKey } ) {
77+ let instance = await this . callSubclass ( 'Unit' , [ unitKey ] )
78+ await instance . initializeInstance ( )
79+ return instance
13780 }
13881
13982 }
0 commit comments