11using Altinn . App . Core . Features . Options ;
22using Altinn . App . Core . Models ;
3+ using Microsoft . IdentityModel . Tokens ;
34using Newtonsoft . Json . Linq ;
45
56namespace Altinn . App . Core . Internal . Pdf ;
67
78/// <summary>
89/// Default implementation of IPdfOptionsMapping
910/// </summary>
10- public class PdfOptionsMapping : IPdfOptionsMapping
11+ public class PdfOptionsMapping : IPdfOptionsMapping
1112{
1213 private readonly IAppOptionsService _appOptionsService ;
1314
@@ -19,160 +20,163 @@ public PdfOptionsMapping(IAppOptionsService appOptionsService)
1920 {
2021 _appOptionsService = appOptionsService ;
2122 }
22-
23-
23+
24+
2425 /// <inheritdoc />
2526 public async Task < Dictionary < string , Dictionary < string , string > > > GetOptionsDictionary ( string formLayout , string language , object data , string instanceId )
26- {
27- IEnumerable < JToken > componentsWithOptionsDefined = GetFormComponentsWithOptionsDefined ( formLayout ) ;
28-
29- Dictionary < string , Dictionary < string , string > > dictionary = new Dictionary < string , Dictionary < string , string > > ( ) ;
27+ {
28+ IEnumerable < JToken > componentsWithOptionsDefined = GetFormComponentsWithOptionsDefined ( formLayout ) ;
3029
31- foreach ( JToken component in componentsWithOptionsDefined )
32- {
33- string optionsId = component . SelectToken ( "optionsId" ) . Value < string > ( ) ;
34- bool hasMappings = component . SelectToken ( "mapping" ) != null ;
35- var secureToken = component . SelectToken ( "secure" ) ;
36- bool isSecureOptions = secureToken != null && secureToken . Value < bool > ( ) ;
37- Dictionary < string , List < string > > keyValues = new Dictionary < string , List < string > > ( ) ;
38- keyValues = hasMappings
39- ? GetComponentKeyValuePairs ( component , data )
40- : new Dictionary < string , List < string > > ( ) ;
41-
42- await GetMappingsForComponent ( language , instanceId , keyValues , isSecureOptions , optionsId , dictionary ) ;
43- }
30+ Dictionary < string , Dictionary < string , string > > dictionary = new Dictionary < string , Dictionary < string , string > > ( ) ;
4431
45- return dictionary ;
32+ foreach ( JToken component in componentsWithOptionsDefined )
33+ {
34+ string ? optionsId = component . SelectToken ( "optionsId" ) ? . Value < string > ( ) ;
35+ if ( optionsId == null )
36+ continue ;
37+ bool hasMappings = component . SelectToken ( "mapping" ) != null ;
38+ var secureToken = component . SelectToken ( "secure" ) ;
39+ bool isSecureOptions = secureToken != null && secureToken . Value < bool > ( ) ;
40+ Dictionary < string , List < string > > keyValues = hasMappings ? GetComponentKeyValuePairs ( component , data ) : new Dictionary < string , List < string > > ( ) ;
41+
42+ await GetMappingsForComponent ( language , instanceId , keyValues , isSecureOptions , optionsId , dictionary ) ;
4643 }
4744
48- private async Task GetMappingsForComponent ( string language , string instanceId , Dictionary < string , List < string > > keyValues ,
49- bool isSecureOptions , string ? optionsId , Dictionary < string , Dictionary < string , string > > dictionary )
45+ return dictionary ;
46+ }
47+
48+ private async Task GetMappingsForComponent ( string language , string instanceId , Dictionary < string , List < string > > mappings , bool isSecureOptions , string optionsId , Dictionary < string , Dictionary < string , string > > dictionary )
5049 {
50+ if ( ! dictionary . ContainsKey ( optionsId ) )
51+ {
52+ dictionary . Add ( optionsId , new Dictionary < string , string > ( ) ) ;
53+ }
54+
5155 var instanceIdentifier = new InstanceIdentifier ( instanceId ) ;
52- foreach ( var pair in keyValues )
56+ if ( mappings . IsNullOrEmpty ( ) )
57+ {
58+ AppOptions appOptions = await GetOptions ( isSecureOptions , instanceIdentifier , optionsId , language , new Dictionary < string , string > ( ) ) ;
59+ AppendOptionsToDictionary ( dictionary [ optionsId ] , appOptions . Options ) ;
60+ return ;
61+ }
62+
63+ foreach ( var pair in mappings )
5364 {
5465 foreach ( var value in pair . Value )
5566 {
56- AppOptions appOptions ;
57- if ( isSecureOptions )
58- {
59- appOptions = await _appOptionsService . GetOptionsAsync ( instanceIdentifier , optionsId ,
60- language ,
61- new Dictionary < string , string > ( ) { { pair . Key , value } } ) ;
62- }
63- else
64- {
65- appOptions = await _appOptionsService . GetOptionsAsync ( optionsId ,
66- language ,
67- new Dictionary < string , string > ( ) { { pair . Key , value } } ) ;
68- }
69-
70- if ( ! dictionary . ContainsKey ( optionsId ) )
71- {
72- dictionary . Add ( optionsId , new Dictionary < string , string > ( ) ) ;
73- }
67+ AppOptions appOptions = await GetOptions ( isSecureOptions , instanceIdentifier , optionsId , language , new Dictionary < string , string > ( ) { { pair . Key , value } } ) ;
7468
7569 AppendOptionsToDictionary ( dictionary [ optionsId ] , appOptions . Options ) ;
7670 }
7771 }
7872 }
7973
80- private static IEnumerable < JToken > GetFormComponentsWithOptionsDefined ( string formLayout )
74+ private async Task < AppOptions > GetOptions ( bool isSecure , InstanceIdentifier instanceIdentifier , string optionsId , string language , Dictionary < string , string > mappings )
75+ {
76+ if ( isSecure )
8177 {
82- JObject formLayoutObject = JObject . Parse ( formLayout ) ;
83-
84- // @ = Current object, ?(expression) = Filter, the rest is just dot notation ref. https://goessner.net/articles/JsonPath/
85- return formLayoutObject . SelectTokens ( "*.data.layout[?(@.optionsId)]" ) ;
78+ return await _appOptionsService . GetOptionsAsync ( instanceIdentifier , optionsId , language , mappings ) ;
8679 }
87-
88- private static Dictionary < string , List < string > > GetComponentKeyValuePairs ( JToken component , object data )
80+ else
8981 {
90- var componentKeyValuePairs = new Dictionary < string , List < string > > ( ) ;
91- JObject jsonData = JObject . FromObject ( data ) ;
82+ return await _appOptionsService . GetOptionsAsync ( optionsId , language , mappings ) ;
83+ }
84+ }
9285
93- Dictionary < string , string > mappings = GetMappingsForComponent ( component ) ;
94- foreach ( var map in mappings )
95- {
96- var selectedDatas = GetMappingValues ( jsonData , map ) ;
86+ private static IEnumerable < JToken > GetFormComponentsWithOptionsDefined ( string formLayout )
87+ {
88+ JObject formLayoutObject = JObject . Parse ( formLayout ) ;
9789
98- componentKeyValuePairs . Add ( map . Value , selectedDatas ) ;
99- }
90+ // @ = Current object, ?(expression) = Filter, the rest is just dot notation ref. https://goessner.net/articles/JsonPath/
91+ return formLayoutObject . SelectTokens ( "*.data.layout[?(@.optionsId)]" ) ;
92+ }
10093
101- return componentKeyValuePairs ;
102- }
94+ private static Dictionary < string , List < string > > GetComponentKeyValuePairs ( JToken component , object data )
95+ {
96+ var componentKeyValuePairs = new Dictionary < string , List < string > > ( ) ;
97+ JObject jsonData = JObject . FromObject ( data ) ;
10398
104- private static Dictionary < string , string > GetMappingsForComponent ( JToken component )
99+ Dictionary < string , string > mappings = GetMappingsForComponent ( component ) ;
100+ foreach ( var map in mappings )
105101 {
106- var maps = new Dictionary < string , string > ( ) ;
107- foreach ( var jToken in component . SelectToken ( "mapping" ) ? . Children ( ) ! )
108- {
109- var map = ( JProperty ) jToken ;
110- maps . Add ( map . Name , map . Value . ToString ( ) ) ;
111- }
102+ var selectedDatas = GetMappingValues ( jsonData , map ) ;
112103
113- return maps ;
104+ componentKeyValuePairs . Add ( map . Value , selectedDatas ) ;
114105 }
115106
116- private static void AppendOptionsToDictionary ( Dictionary < string , string > dictionary , List < AppOption > options )
107+ return componentKeyValuePairs ;
108+ }
109+
110+ private static Dictionary < string , string > GetMappingsForComponent ( JToken component )
111+ {
112+ var maps = new Dictionary < string , string > ( ) ;
113+ foreach ( var jToken in component . SelectToken ( "mapping" ) ? . Children ( ) ! )
117114 {
118- foreach ( AppOption item in options )
119- {
120- if ( ! dictionary . ContainsKey ( item . Label ) )
121- {
122- dictionary . Add ( item . Label , item . Value ) ;
123- }
124- }
115+ var map = ( JProperty ) jToken ;
116+ maps . Add ( map . Name , map . Value . ToString ( ) ) ;
125117 }
126118
119+ return maps ;
120+ }
127121
128-
129- private static List < string > GetMappingValues ( JObject jsonData , KeyValuePair < string , string > map , int depth = 0 )
122+ private static void AppendOptionsToDictionary ( Dictionary < string , string > dictionary , List < AppOption > options )
123+ {
124+ foreach ( AppOption item in options )
130125 {
131- int count = 1 ;
132- if ( MappingHasRepeatingGroup ( map . Key ) )
133- {
134- var mappingUntilFirstGroup = GetMappingUntilFirstGroup ( map . Key ) ;
135- JToken repeatingGroup = jsonData . SelectToken ( mappingUntilFirstGroup ) ;
136- count = repeatingGroup . Children ( ) . Count ( ) ;
137- }
138-
139- List < string > selectedDatas = new List < string > ( ) ;
140- for ( var i = 0 ; i < count ; i ++ )
126+ if ( ! dictionary . ContainsKey ( item . Label ) )
141127 {
142- string replaceText = "{" + depth + "}" ;
143-
144- string select = map . Key . Replace ( replaceText , i . ToString ( ) ) ;
145- if ( MappingHasRepeatingGroup ( select ) )
146- {
147- selectedDatas . AddRange ( GetMappingValues ( jsonData ,
148- new KeyValuePair < string , string > ( select , map . Value ) , ++ depth ) ) ;
149- }
150- else
151- {
152- selectedDatas . Add ( jsonData . SelectToken ( select ) . ToString ( ) ) ;
153- }
128+ dictionary . Add ( item . Label , item . Value ) ;
154129 }
155-
156- return selectedDatas ;
157130 }
131+ }
158132
159- /// <summary>
160- /// Return true if mapping contains a array replacement start "[{"
161- /// </summary>
162- /// <param name="mapping">Field mapping</param>
163- /// <returns></returns>
164- private static bool MappingHasRepeatingGroup ( string mapping )
133+
134+ private static List < string > GetMappingValues ( JObject jsonData , KeyValuePair < string , string > map , int depth = 0 )
135+ {
136+ int count = 1 ;
137+ if ( MappingHasRepeatingGroup ( map . Key ) )
165138 {
166- return mapping . Contains ( "[{" ) ;
139+ var mappingUntilFirstGroup = GetMappingUntilFirstGroup ( map . Key ) ;
140+ JToken repeatingGroup = jsonData . SelectToken ( mappingUntilFirstGroup ) ;
141+ count = repeatingGroup . Children ( ) . Count ( ) ;
167142 }
168143
169- /// <summary>
170- /// Returns mapping of first element in mapping that is a list with replacement string.
171- /// </summary>
172- /// <param name="mapping"></param>
173- /// <returns></returns>
174- private static string GetMappingUntilFirstGroup ( string mapping )
144+ List < string > selectedDatas = new List < string > ( ) ;
145+ for ( var i = 0 ; i < count ; i ++ )
175146 {
176- return mapping . Substring ( 0 , mapping . IndexOf ( "[{" ) ) ;
147+ string replaceText = "{" + depth + "}" ;
148+
149+ string select = map . Key . Replace ( replaceText , i . ToString ( ) ) ;
150+ if ( MappingHasRepeatingGroup ( select ) )
151+ {
152+ selectedDatas . AddRange ( GetMappingValues ( jsonData , new KeyValuePair < string , string > ( select , map . Value ) , depth + 1 ) ) ;
153+ }
154+ else
155+ {
156+ selectedDatas . Add ( jsonData . SelectToken ( select ) . ToString ( ) ) ;
157+ }
177158 }
178- }
159+
160+ return selectedDatas ;
161+ }
162+
163+ /// <summary>
164+ /// Return true if mapping contains a array replacement start "[{"
165+ /// </summary>
166+ /// <param name="mapping">Field mapping</param>
167+ /// <returns></returns>
168+ private static bool MappingHasRepeatingGroup ( string mapping )
169+ {
170+ return mapping . Contains ( "[{" ) ;
171+ }
172+
173+ /// <summary>
174+ /// Returns mapping of first element in mapping that is a list with replacement string.
175+ /// </summary>
176+ /// <param name="mapping"></param>
177+ /// <returns></returns>
178+ private static string GetMappingUntilFirstGroup ( string mapping )
179+ {
180+ return mapping . Substring ( 0 , mapping . IndexOf ( "[{" ) ) ;
181+ }
182+ }
0 commit comments