1+ const HDSItemDef = require ( './HDSItemDef' ) ;
2+
13class HDSModel {
24 /**
35 * JSON definition file
@@ -12,13 +14,26 @@ class HDSModel {
1214 */
1315 #modelData;
1416
17+ /**
18+ * ItemDefs Cache
19+ * KeyValue of itemsDefs
20+ */
21+ #itemsDefs;
22+
23+ /**
24+ * get itemsDefs by streamId and eventType
25+ */
26+ #modelDataByStreamIdEventTypes;
27+
1528 /**
1629 * JSON definition file
1730 * Should come from service/info assets.hds-model
1831 * @type {string }
1932 */
2033 constructor ( modelUrl ) {
2134 this . #modelUrl = modelUrl ;
35+ this . #itemsDefs = { } ;
36+ this . #modelDataByStreamIdEventTypes = { } ;
2237 }
2338
2439 /**
@@ -28,15 +43,47 @@ class HDSModel {
2843 const response = await fetch ( this . #modelUrl) ;
2944 const resultText = await response . text ( ) ;
3045 const result = JSON . parse ( resultText ) ;
31- this . #modelData = deepFreeze ( result ) ;
46+ this . #modelData = result ;
47+ loadModelDataByStreamIdEventTypes ( this . #modelData. items , this . #modelDataByStreamIdEventTypes) ;
48+ deepFreeze ( this . #modelData) ; // make sure it cannot be modified
3249 }
3350
3451 /**
3552 * get item for a key
3653 * @param {string } key
54+ * @param {boolean } [throwErrorIfNotFound] default `true`
55+ */
56+ itemDefForKey ( key , throwErrorIfNotFound = true ) {
57+ if ( this . #itemsDefs[ key ] ) return this . #itemsDefs[ key ] ;
58+ const defData = this . #modelData. items [ key ] ;
59+ if ( ! defData ) {
60+ if ( throwErrorIfNotFound ) throw new Error ( 'Cannot find item definition with key: ' + key ) ;
61+ return null ;
62+ }
63+ this . #itemsDefs[ key ] = new HDSItemDef ( defData ) ;
64+ return this . #itemsDefs[ key ] ;
65+ }
66+
67+ /**
68+ * get a definition for an event
69+ * @param {Event } event
70+ * @param {boolean } [throwErrorIfNotFound] default `true`
3771 */
38- itemForKey ( key ) {
39- return this . #modelData. items [ key ] ;
72+ itemDefForEvent ( event , throwErrorIfNotFound = true ) {
73+ const candidates = [ ] ;
74+ for ( const streamId of event . streamIds ) {
75+ const keyStreamIdEventType = streamId + ':' + event . type ;
76+ const candidate = this . #modelDataByStreamIdEventTypes[ keyStreamIdEventType ] ;
77+ if ( candidate ) candidates . push ( candidate ) ;
78+ }
79+ if ( candidates . length === 0 ) {
80+ if ( throwErrorIfNotFound ) throw new Error ( 'Cannot find definition for event: ' + JSON . stringify ( event ) ) ;
81+ return null ;
82+ }
83+ if ( candidates . length > 1 ) {
84+ throw new Error ( `Found multiple matching definitions "${ candidates . map ( c => ( c . key ) ) . join ( ', ' ) } " for event: ${ JSON . stringify ( event ) } ` ) ;
85+ }
86+ return this . itemDefForKey ( candidates [ 0 ] . key , throwErrorIfNotFound ) ;
4087 }
4188}
4289
@@ -62,3 +109,26 @@ function deepFreeze (object) {
62109
63110 return Object . freeze ( object ) ;
64111}
112+
113+ /**
114+ * @private
115+ * Add key to model items and
116+ * load modeldata item into modelDataByStreamIdEventTypes for fast search
117+ */
118+ function loadModelDataByStreamIdEventTypes ( model , map ) {
119+ for ( const [ key , item ] of Object . entries ( model ) ) {
120+ // add key to item
121+ item . key = key ;
122+ const eventTypes = [ ] ;
123+ if ( item . eventType ) {
124+ eventTypes . push ( item . eventType ) ;
125+ } else {
126+ eventTypes . push ( ...Object . keys ( item . variations . eventType ) ) ;
127+ }
128+ for ( const eventType of eventTypes ) {
129+ const keyStreamIdEventType = item . streamId + ':' + eventType ;
130+ if ( map [ keyStreamIdEventType ] ) throw new Error ( `Duplicate sreamId + eventType "${ keyStreamIdEventType } " for item ${ JSON . stringify ( item ) } ` ) ;
131+ map [ keyStreamIdEventType ] = item ;
132+ }
133+ }
134+ }
0 commit comments