1
1
import type { Resource } from 'rdf-object' ;
2
2
import type { RdfObjectLoader } from 'rdf-object/lib/RdfObjectLoader' ;
3
3
import type { Logger } from 'winston' ;
4
- import { IRIS_OO } from '../rdf/Iris' ;
4
+ import { IRIS_OO , IRIS_RDF } from '../rdf/Iris' ;
5
5
import { uniqueTypes } from '../rdf/ResourceUtil' ;
6
6
import { ErrorResourcesContext } from '../util/ErrorResourcesContext' ;
7
7
import type { IConfigPreprocessor , IConfigPreprocessorTransform } from './IConfigPreprocessor' ;
@@ -43,17 +43,24 @@ export class ConfigPreprocessorOverride implements IConfigPreprocessor<Record<st
43
43
* @param handleResponse - Override values that were found for this resource.
44
44
*/
45
45
public transform ( config : Resource , handleResponse : Record < string , Resource > ) : IConfigPreprocessorTransform {
46
- for ( const id of Object . keys ( config . properties ) ) {
47
- const overrideValue = handleResponse [ id ] ;
48
- if ( overrideValue ) {
49
- config . properties [ id ] = [ overrideValue ] ;
46
+ // We know this has exactly 1 result due to the canHandle call
47
+ const configType = uniqueTypes ( config , this . componentResources ) [ 0 ] ;
48
+ const overrideType = handleResponse [ IRIS_RDF . type ] ?. value ;
49
+ // In case the type changes we have to delete all the original properties as those correspond to the old type
50
+ if ( overrideType && configType . value !== overrideType ) {
51
+ for ( const id of Object . keys ( config . properties ) ) {
52
+ delete config . properties [ id ] ;
50
53
}
51
54
}
55
+ for ( const property of Object . keys ( handleResponse ) ) {
56
+ config . properties [ property ] = [ handleResponse [ property ] ] ;
57
+ }
58
+
52
59
return { rawConfig : config , finishTransformation : false } ;
53
60
}
54
61
55
62
/**
56
- * Clear all cached overrides so they will be calculated again on the next call.
63
+ * Clear all cached overrides, so they will be calculated again on the next call.
57
64
*/
58
65
public reset ( ) : void {
59
66
this . overrides = undefined ;
@@ -168,24 +175,31 @@ export class ConfigPreprocessorOverride implements IConfigPreprocessor<Record<st
168
175
* @param chain - The chain of Overrides, with a normal resource as the last entry in the array.
169
176
*/
170
177
protected chainToOverrideObject ( chain : Resource [ ] ) : { target : string ; values : Record < string , Resource > } {
171
- const { target, type } = this . getChainTarget ( chain ) ;
178
+ const target = this . getChainTarget ( chain ) ;
172
179
173
180
// Apply all overrides sequentially, starting from the one closest to the target.
174
181
// This ensures the most recent override has priority.
175
- const parameters = this . componentResources [ type . value ] . properties . parameters ;
176
- const mergedOverride : Record < string , Resource > = { } ;
182
+ let mergedOverride : Record < string , Resource > = { } ;
177
183
for ( let i = chain . length - 2 ; i >= 0 ; -- i ) {
178
- const filteredObject = this . filterOverrideObject ( chain [ i ] , target , parameters ) ;
179
- Object . assign ( mergedOverride , filteredObject ) ;
184
+ const validatedObject = this . extractOverrideParameters ( chain [ i ] , target ) ;
185
+ // In case an Override has a different type, the properties of the target don't matter any more,
186
+ // as the object is being replaced completely.
187
+ const mergedType = mergedOverride [ IRIS_RDF . type ] ?. value ;
188
+ const overrideType = validatedObject [ IRIS_RDF . type ] ?. value ;
189
+ if ( overrideType && overrideType !== mergedType ) {
190
+ mergedOverride = validatedObject ;
191
+ } else {
192
+ Object . assign ( mergedOverride , validatedObject ) ;
193
+ }
180
194
}
181
195
return { target : target . value , values : mergedOverride } ;
182
196
}
183
197
184
198
/**
185
- * Finds the final target and its type in an override chain .
199
+ * Finds the final target and validates its type value .
186
200
* @param chain - The chain to find the target of.
187
201
*/
188
- protected getChainTarget ( chain : Resource [ ] ) : { target : Resource ; type : Resource } {
202
+ protected getChainTarget ( chain : Resource [ ] ) : Resource {
189
203
const target = chain [ chain . length - 1 ] ;
190
204
const types = uniqueTypes ( target , this . componentResources ) ;
191
205
if ( ! types || types . length === 0 ) {
@@ -200,17 +214,15 @@ export class ConfigPreprocessorOverride implements IConfigPreprocessor<Record<st
200
214
override : chain [ chain . length - 2 ] ,
201
215
} ) ;
202
216
}
203
- return { target, type : types [ 0 ] } ;
217
+ return target ;
204
218
}
205
219
206
220
/**
207
- * Extracts all relevant parameters of an Override with their corresponding new value.
221
+ * Extracts all parameters of an Override with their corresponding value.
208
222
* @param override - The Override to apply.
209
- * @param target - The target resource to apply the Override to.
210
- * @param parameters - The parameters that are relevant for the target.
223
+ * @param target - The target resource to apply the Override to. Only used for error messages.
211
224
*/
212
- protected filterOverrideObject ( override : Resource , target : Resource , parameters : Resource [ ] ) :
213
- Record < string , Resource > {
225
+ protected extractOverrideParameters ( override : Resource , target : Resource ) : Record < string , Resource > {
214
226
const overrideObjects = override . properties [ IRIS_OO . overrideParameters ] ;
215
227
if ( ! overrideObjects || overrideObjects . length === 0 ) {
216
228
this . logger . warn ( `No overrideParameters found for ${ override . value } .` ) ;
@@ -224,22 +236,19 @@ export class ConfigPreprocessorOverride implements IConfigPreprocessor<Record<st
224
236
const overrideObject = overrideObjects [ 0 ] ;
225
237
226
238
// Only keep the parameters that are known to the type of the target object
227
- const filteredObject : Record < string , Resource > = { } ;
228
- for ( const parameter of parameters ) {
229
- const overrideValues = overrideObject . properties [ parameter . value ] ;
230
- if ( ! overrideValues || overrideValues . length === 0 ) {
231
- continue ;
232
- }
239
+ const validatedObject : Record < string , Resource > = { } ;
240
+ for ( const parameter of Object . keys ( overrideObject . properties ) ) {
241
+ const overrideValues = overrideObject . properties [ parameter ] ;
233
242
if ( overrideValues . length > 1 ) {
234
- throw new ErrorResourcesContext ( `Detected multiple values for override parameter ${ parameter . value } in Override ${ override . value } . RDF lists should be used for defining multiple values.` , {
243
+ throw new ErrorResourcesContext ( `Detected multiple values for override parameter ${ parameter } in Override ${ override . value } . RDF lists should be used for defining multiple values.` , {
235
244
arguments : overrideValues ,
236
245
target,
237
246
override,
238
247
} ) ;
239
248
}
240
- filteredObject [ parameter . value ] = overrideValues [ 0 ] ;
249
+ validatedObject [ parameter ] = overrideValues [ 0 ] ;
241
250
}
242
- return filteredObject ;
251
+ return validatedObject ;
243
252
}
244
253
}
245
254
0 commit comments