@@ -485,6 +485,12 @@ function getContainedResources(node) {
485
485
}
486
486
}
487
487
488
+ /**
489
+ * Mapping questionnaires to "linkIds" keys mapped to questionnaire items.
490
+ * It is used to cache the result in the getQItemByLinkIds function.
491
+ * @type {WeakMap<WeakKey, Object> }
492
+ */
493
+ const questionnaire2linkIds = new WeakMap ( ) ;
488
494
489
495
/**
490
496
* Returns a questionnaire item based on the linkIds array of the ancestor
@@ -497,51 +503,73 @@ function getContainedResources(node) {
497
503
*/
498
504
function getQItemByLinkIds ( questionnaire , linkIds ) {
499
505
let currentNode ;
500
- const topLinkId = linkIds [ linkIds . length - 1 ] ;
501
-
502
- if ( questionnaire . group ) {
503
- // Search for an item in a questionnaire specified in DSTU2 format
504
- let collection = questionnaire . group ;
505
-
506
- // Find the questionnaire item that matches the linkId of the topmost known
507
- // item.
508
- while ( collection ?. length > 0 ) {
509
- currentNode = collection . find ( o => o . linkId === topLinkId ) ;
510
- if ( currentNode ) {
511
- break ;
512
- } else {
513
- collection = [ ] . concat ( ...collection . map ( i => [ ] . concat ( i . item || [ ] , i . group || [ ] ) ) ) ;
506
+ // Mapping "linkIds" keys to questionnaire items.
507
+ let linkIds2items ;
508
+ // "linkIds" key.
509
+ const linkIdsKey = linkIds . join ( '|' ) ;
510
+
511
+ // Get the mapping of "linkIds" keys to questionnaire items for the current
512
+ // questionnaire, or create it if it doesn't exist.
513
+ if ( questionnaire2linkIds . has ( questionnaire ) ) {
514
+ linkIds2items = questionnaire2linkIds . get ( questionnaire ) ;
515
+ currentNode = linkIds2items [ linkIdsKey ] ;
516
+ } else {
517
+ linkIds2items = { } ;
518
+ questionnaire2linkIds . set ( questionnaire , linkIds2items ) ;
519
+ }
520
+
521
+ if ( ! Object . prototype . hasOwnProperty . call ( linkIds2items , linkIdsKey ) ) {
522
+ // If the result is not cached yet, we search for the questionnaire item.
523
+ const topLinkId = linkIds [ linkIds . length - 1 ] ;
524
+
525
+ if ( questionnaire . group ) {
526
+ // Search for an item in a questionnaire specified in DSTU2 format.
527
+ let collection = questionnaire . group ;
528
+
529
+ // Find the questionnaire item that matches the linkId of the topmost
530
+ // known item.
531
+ while ( collection ?. length > 0 ) {
532
+ currentNode = collection . find ( o => o . linkId === topLinkId ) ;
533
+ if ( currentNode ) {
534
+ break ;
535
+ } else {
536
+ collection = [ ] . concat ( ...collection . map ( i => [ ] . concat ( i . item || [ ] , i . group || [ ] ) ) ) ;
537
+ }
514
538
}
515
- }
516
539
517
- // Getting a questionnaire item relative to the topmost known item using
518
- // subsequent linkIds.
519
- for ( let i = linkIds . length - 2 ; i >= 0 && currentNode ; -- i ) {
520
- currentNode = currentNode . question ?. find ( o => o . linkId === linkIds [ i ] ) ||
521
- currentNode . group ?. find ( o => o . linkId === linkIds [ i ] ) ;
522
- }
540
+ // Getting a questionnaire item relative to the topmost known item using
541
+ // subsequent linkIds.
542
+ for ( let i = linkIds . length - 2 ; i >= 0 && currentNode ; -- i ) {
543
+ currentNode = currentNode . question ?. find ( o => o . linkId === linkIds [ i ] ) ||
544
+ currentNode . group ?. find ( o => o . linkId === linkIds [ i ] ) ;
545
+ }
523
546
524
- } else {
525
- // Search for an item in a questionnaire specified in STU3, R4 or R5 format
526
- let collection = questionnaire . item ;
527
-
528
- // Find the questionnaire item that matches the linkId of the topmost known
529
- // item.
530
- while ( collection ?. length > 0 ) {
531
- currentNode = collection . find ( o => o . linkId === topLinkId ) ;
532
- if ( currentNode ) {
533
- break ;
534
- } else {
535
- collection = [ ] . concat ( ...collection . map ( i => i . item || [ ] ) ) ;
547
+ } else {
548
+ // Search for an item in a questionnaire specified in STU3, R4 or R5
549
+ // format.
550
+ let collection = questionnaire . item ;
551
+
552
+ // Find the questionnaire item that matches the linkId of the topmost
553
+ // known item.
554
+ while ( collection ?. length > 0 ) {
555
+ currentNode = collection . find ( o => o . linkId === topLinkId ) ;
556
+ if ( currentNode ) {
557
+ break ;
558
+ } else {
559
+ collection = [ ] . concat ( ...collection . map ( i => i . item || [ ] ) ) ;
560
+ }
536
561
}
537
- }
538
562
539
- // Getting a questionnaire item relative to the topmost known item using
540
- // subsequent linkIds.
541
- for ( let i = linkIds . length - 2 ; i >= 0 && currentNode ; -- i ) {
542
- currentNode = currentNode . item ?. find ( o => o . linkId === linkIds [ i ] ) ;
563
+ // Getting a questionnaire item relative to the topmost known item using
564
+ // subsequent linkIds.
565
+ for ( let i = linkIds . length - 2 ; i >= 0 && currentNode ; -- i ) {
566
+ currentNode = currentNode . item ?. find ( o => o . linkId === linkIds [ i ] ) ;
567
+ }
543
568
}
569
+
570
+ questionnaire2linkIds . get ( questionnaire ) [ linkIdsKey ] = currentNode ;
544
571
}
572
+
545
573
return currentNode ;
546
574
}
547
575
0 commit comments