componentsjs 4.4.1 → 5.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/bin/compile-config.js +1 -1
  3. package/components/context.jsonld +74 -2
  4. package/lib/construction/ConfigConstructor.js +7 -14
  5. package/lib/construction/argument/ArgumentConstructorHandlerHash.js +3 -2
  6. package/lib/construction/strategy/ConstructionStrategyCommonJsString.js +3 -0
  7. package/lib/construction/strategy/IConstructionStrategy.d.ts +2 -2
  8. package/lib/loading/ComponentRegistry.d.ts +1 -1
  9. package/lib/loading/ComponentRegistry.js +1 -1
  10. package/lib/loading/ComponentRegistryFinalizer.js +18 -3
  11. package/lib/loading/ComponentsManagerBuilder.js +1 -1
  12. package/lib/loading/ConfigRegistry.d.ts +1 -1
  13. package/lib/preprocess/ConfigPreprocessorComponent.d.ts +3 -1
  14. package/lib/preprocess/ConfigPreprocessorComponent.js +38 -12
  15. package/lib/preprocess/ConfigPreprocessorComponentMapped.d.ts +4 -3
  16. package/lib/preprocess/ConfigPreprocessorComponentMapped.js +17 -18
  17. package/lib/preprocess/GenericsContext.d.ts +30 -0
  18. package/lib/preprocess/GenericsContext.js +63 -0
  19. package/lib/preprocess/ParameterHandler.d.ts +4 -2
  20. package/lib/preprocess/ParameterHandler.js +22 -20
  21. package/lib/preprocess/constructorargumentsmapping/ConstructorArgumentsElementMappingHandlerCollectEntries.d.ts +3 -2
  22. package/lib/preprocess/constructorargumentsmapping/ConstructorArgumentsElementMappingHandlerCollectEntries.js +24 -10
  23. package/lib/preprocess/constructorargumentsmapping/ConstructorArgumentsElementMappingHandlerElements.d.ts +2 -1
  24. package/lib/preprocess/constructorargumentsmapping/ConstructorArgumentsElementMappingHandlerElements.js +8 -5
  25. package/lib/preprocess/constructorargumentsmapping/ConstructorArgumentsElementMappingHandlerFields.d.ts +2 -1
  26. package/lib/preprocess/constructorargumentsmapping/ConstructorArgumentsElementMappingHandlerFields.js +16 -9
  27. package/lib/preprocess/constructorargumentsmapping/ConstructorArgumentsElementMappingHandlerKeyValue.d.ts +4 -3
  28. package/lib/preprocess/constructorargumentsmapping/ConstructorArgumentsElementMappingHandlerKeyValue.js +12 -12
  29. package/lib/preprocess/constructorargumentsmapping/ConstructorArgumentsElementMappingHandlerList.d.ts +2 -1
  30. package/lib/preprocess/constructorargumentsmapping/ConstructorArgumentsElementMappingHandlerList.js +9 -22
  31. package/lib/preprocess/constructorargumentsmapping/IConstructorArgumentsElementMappingHandler.d.ts +5 -2
  32. package/lib/preprocess/constructorargumentsmapping/IConstructorArgumentsMapper.d.ts +5 -2
  33. package/lib/preprocess/parameterproperty/IParameterPropertyHandler.d.ts +5 -2
  34. package/lib/preprocess/parameterproperty/ParameterPropertyHandlerDefault.d.ts +6 -3
  35. package/lib/preprocess/parameterproperty/ParameterPropertyHandlerDefault.js +20 -3
  36. package/lib/preprocess/parameterproperty/ParameterPropertyHandlerDefaultScoped.d.ts +2 -2
  37. package/lib/preprocess/parameterproperty/ParameterPropertyHandlerDefaultScoped.js +16 -5
  38. package/lib/preprocess/parameterproperty/ParameterPropertyHandlerFixed.d.ts +5 -3
  39. package/lib/preprocess/parameterproperty/ParameterPropertyHandlerFixed.js +25 -2
  40. package/lib/preprocess/parameterproperty/ParameterPropertyHandlerLazy.d.ts +2 -2
  41. package/lib/preprocess/parameterproperty/ParameterPropertyHandlerLazy.js +10 -3
  42. package/lib/preprocess/parameterproperty/ParameterPropertyHandlerRange.d.ts +18 -4
  43. package/lib/preprocess/parameterproperty/ParameterPropertyHandlerRange.js +195 -30
  44. package/lib/rdf/Iris.js +24 -24
  45. package/lib/rdf/RdfParser.d.ts +2 -2
  46. package/lib/rdf/RdfParser.js +17 -5
  47. package/lib/rdf/RdfStreamIncluder.d.ts +1 -1
  48. package/lib/rdf/RdfStreamIncluder.js +2 -2
  49. package/package.json +10 -10
  50. package/lib/preprocess/parameterproperty/ParameterPropertyHandlerRequired.d.ts +0 -11
  51. package/lib/preprocess/parameterproperty/ParameterPropertyHandlerRequired.js +0 -23
  52. package/lib/preprocess/parameterproperty/ParameterPropertyHandlerUnique.d.ts +0 -12
  53. package/lib/preprocess/parameterproperty/ParameterPropertyHandlerUnique.js +0 -34
package/CHANGELOG.md CHANGED
@@ -1,6 +1,52 @@
1
1
  # Changelog
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ <a name="v5.0.0-beta.2"></a>
5
+ ## [v5.0.0-beta.2](https://github.com/LinkedSoftwareDependencies/Components.js/compare/v5.0.0-beta.1...v5.0.0-beta.2) - 2021-12-09
6
+
7
+ ### Added
8
+ * [Handle keyof parameter ranges](https://github.com/LinkedSoftwareDependencies/Components.js/commit/0f55ba05bff5311d111ca97256aaa2e7be7ae83b)
9
+
10
+ <a name="v5.0.0-beta.1"></a>
11
+ ## [v5.0.0-beta.1](https://github.com/LinkedSoftwareDependencies/Components.js/compare/v5.0.0-beta.0...v5.0.0-beta.1) - 2021-12-07
12
+
13
+ ### Added
14
+ * [Handle generics in nested components](https://github.com/LinkedSoftwareDependencies/Components.js/commit/d33d4c2668974087873943b3d5c66300fa3df65b)
15
+ * [Handle generics in parameter ranges](https://github.com/LinkedSoftwareDependencies/Components.js/commit/d3358b74ab25a3aca13d6dfc97b16cfd836d4ba9)
16
+ * [Add generic vocabulary changes to context](https://github.com/LinkedSoftwareDependencies/Components.js/commit/b8af018bb8f344833c07d1ef795a6b08d414c2ad)
17
+
18
+ <a name="v5.0.0-beta.0"></a>
19
+ ## [v5.0.0-beta.0](https://github.com/LinkedSoftwareDependencies/Components.js/compare/v4.5.0...v5.0.0-beta.0) - 2021-11-30
20
+
21
+ ### BREAKING CHANGES
22
+ * [Remove required and unique param flags in favor of parameter ranges](https://github.com/LinkedSoftwareDependencies/Components.js/commit/0df26318e4803b06660b3458fc75d565c4b60f67):
23
+ This allows more complex ranges to be defined, such as nested arrays, or arrays of union types.
24
+ **Because of this change, arrays now must always be explicitly defined within an RDF list (or @list in JSON-LD).**
25
+ If one param value is provided, it is considered a singular value.
26
+ If the param value contains an RDF list, it is considered an array.
27
+ If multiple param values are provided without RDF list, an error is thrown.
28
+
29
+ ### Added
30
+ * Validate parameter values by type:
31
+ * [Validate param ranges with union and intersection types](https://github.com/LinkedSoftwareDependencies/Components.js/commit/d08ecdb94051d3e88e7e1ea09f0f77518fb0debf)
32
+ * [Validate types of resource-based param values](https://github.com/LinkedSoftwareDependencies/Components.js/commit/2be90ccb416215261ef9c785e89302f3c4ef9264)
33
+ * [Validate param ranges with tuple types](https://github.com/LinkedSoftwareDependencies/Components.js/commit/05d84c4c1d4bde6bcb5a99d53df4e66ca69536bf)
34
+ * [Validate param ranges with literal types](https://github.com/LinkedSoftwareDependencies/Components.js/commit/7373b0fc06bdaf95a8099b9f58b741cd6f4f1b9d)
35
+
36
+ ### Changed
37
+ * [Allow IRIs to be casted to string params](https://github.com/LinkedSoftwareDependencies/Components.js/commit/978985684dcba67629d44bfd0e5cf75293c5ea7a)
38
+ * [Allow components to be registered to multiple modules](https://github.com/LinkedSoftwareDependencies/Components.js/commit/e575e64ebd26092a6bb005d837023e35877e9308)
39
+ * [Make relative IRIs make use of importPaths-based URLs if possible](https://github.com/LinkedSoftwareDependencies/Components.js/commit/6a2e18c3bf6a1b95f826b66ee0ef8b154f10c3cc)
40
+
41
+ ### Fixed
42
+ * [Fix raw JSON values not being serializable to strings](https://github.com/LinkedSoftwareDependencies/Components.js/commit/96fe46eda1e153e87b29689196506ce6fbbdae58)
43
+
44
+ <a name="v4.5.0"></a>
45
+ ## [v4.5.0](https://github.com/LinkedSoftwareDependencies/Components.js/compare/v4.4.1...v4.5.0) - 2021-08-30
46
+
47
+ ### Changed
48
+ * [Migrate to @rdfjs/types](https://github.com/LinkedSoftwareDependencies/Components.js/commit/b2f9f2e0c5512e743b324f48f332d96e4214ec84)
49
+
4
50
  <a name="v4.4.1"></a>
5
51
  ## [v4.4.1](https://github.com/LinkedSoftwareDependencies/Components.js/compare/v4.4.0...v4.4.1) - 2021-07-26
6
52
 
@@ -30,7 +30,7 @@ if (args.e) {
30
30
  exportVariableName = args.e;
31
31
  }
32
32
  const asFunction = !!args.f;
33
- __1.compileConfig(mainModulePath, configPath, configResourceUri, exportVariableName, asFunction)
33
+ (0, __1.compileConfig)(mainModulePath, configPath, configResourceUri, exportVariableName, asFunction)
34
34
  .then((output) => process.stdout.write(`${output}\n`))
35
35
  .catch(error => {
36
36
  process.stderr.write(`${error.stack}\n`);
@@ -22,9 +22,19 @@
22
22
  "components": {
23
23
  "@id": "oo:component"
24
24
  },
25
+ "component": {
26
+ "@id": "oo:component",
27
+ "@type": "@id"
28
+ },
25
29
  "parameters": {
26
30
  "@id": "oo:parameter"
27
31
  },
32
+ "memberKeys": {
33
+ "@id": "oo:memberKey"
34
+ },
35
+ "genericTypeParameters": {
36
+ "@id": "oo:genericTypeParameter"
37
+ },
28
38
  "constructorArguments": {
29
39
  "@id": "oo:constructorArguments",
30
40
  "@container": "@list"
@@ -61,6 +71,66 @@
61
71
  "undefined": {
62
72
  "@id": "oo:isUndefined"
63
73
  },
74
+ "ParameterRange": {
75
+ "@id": "oo:ParameterRange"
76
+ },
77
+ "ParameterRangeUndefined": {
78
+ "@id": "oo:ParameterRangeUndefined"
79
+ },
80
+ "ParameterRangeArray": {
81
+ "@id": "oo:ParameterRangeArray"
82
+ },
83
+ "ParameterRangeRest": {
84
+ "@id": "oo:ParameterRangeRest"
85
+ },
86
+ "ParameterRangeKeyof": {
87
+ "@id": "oo:ParameterRangeKeyof"
88
+ },
89
+ "ParameterRangeLiteral": {
90
+ "@id": "oo:ParameterRangeLiteral"
91
+ },
92
+ "parameterRangeValue": {
93
+ "@id": "oo:parameterRangeValue",
94
+ "@type": "@id"
95
+ },
96
+ "parameterRangeValueLiteral": {
97
+ "@id": "oo:parameterRangeValue"
98
+ },
99
+ "ParameterRangeUnion": {
100
+ "@id": "oo:ParameterRangeUnion"
101
+ },
102
+ "ParameterRangeIntersection": {
103
+ "@id": "oo:ParameterRangeIntersection"
104
+ },
105
+ "parameterRangeElements": {
106
+ "@id": "oo:parameterRangeElements",
107
+ "@type": "@id"
108
+ },
109
+ "ParameterRangeCollectEntries": {
110
+ "@id": "oo:ParameterRangeCollectEntries"
111
+ },
112
+ "parameterRangeCollectEntriesParameters": {
113
+ "@id": "oo:parameterRangeCollectEntriesParameter",
114
+ "@type": "@id"
115
+ },
116
+ "ParameterRangeGenericComponent": {
117
+ "@id": "oo:ParameterRangeGenericComponent"
118
+ },
119
+ "genericTypeInstances": {
120
+ "@id": "oo:genericTypeInstance",
121
+ "@type": "@id"
122
+ },
123
+ "ParameterRangeGenericTypeReference": {
124
+ "@id": "oo:ParameterRangeGenericTypeReference"
125
+ },
126
+ "parameterRangeGenericType": {
127
+ "@id": "oo:parameterRangeGenericType",
128
+ "@type": "@id"
129
+ },
130
+ "parameterRangeGenericBindings": {
131
+ "@id": "oo:parameterRangeGenericBindings",
132
+ "@type": "@id"
133
+ },
64
134
 
65
135
  "rdfs": "http://www.w3.org/2000/01/rdf-schema#",
66
136
  "comment": {
@@ -116,7 +186,8 @@
116
186
  },
117
187
  "fields": {
118
188
  "@id": "om:field",
119
- "@type": "om:ObjectMapEntry"
189
+ "@type": "om:ObjectMapEntry",
190
+ "@container": "@list"
120
191
  },
121
192
  "elements": {
122
193
  "@id": "om:elements",
@@ -125,7 +196,8 @@
125
196
  },
126
197
  "collectEntries": {
127
198
  "@id": "om:collectsEntriesFrom",
128
- "@type": "@id"
199
+ "@type": "@id",
200
+ "@container": "@list"
129
201
  },
130
202
  "keyRaw": {
131
203
  "@id": "om:fieldName"
@@ -31,22 +31,15 @@ class ConfigConstructor {
31
31
  this.moduleState = options.moduleState;
32
32
  }
33
33
  async getArgumentValues(values, settings) {
34
- // Unwrap unique values out of the array
35
- if (values.length > 0 && values[0].property.unique && values[0].property.unique.value === 'true') {
36
- return this.getArgumentValue(values[0], settings);
34
+ if (values.length === 0) {
35
+ return this.constructionStrategy.createUndefined();
37
36
  }
38
- // Unwrap RDF list-based values out of the array
39
- if (values.length > 0 && values.some(value => value.list)) {
40
- if (values.length > 1) {
41
- throw new ErrorResourcesContext_1.ErrorResourcesContext(`Detected multiple values for an argument while only a single RDF list is allowed`, {
42
- arguments: values.flatMap(value => value.list ? value.list : [value]),
43
- });
44
- }
45
- return this.getArgumentValue(values[0], settings);
37
+ if (values.length > 1) {
38
+ throw new ErrorResourcesContext_1.ErrorResourcesContext(`Detected multiple values for an argument. RDF lists should be used for defining multiple values.`, {
39
+ arguments: values,
40
+ });
46
41
  }
47
- // Otherwise, keep the array form
48
- const elements = await Promise.all(values.map(element => this.getArgumentValue(element, settings)));
49
- return this.constructionStrategy.createArray({ settings, elements });
42
+ return this.getArgumentValue(values[0], settings);
50
43
  }
51
44
  async getArgumentValue(value, settings) {
52
45
  // Check if this args resource can be handled by one of the built-in handlers.
@@ -7,11 +7,12 @@ const ErrorResourcesContext_1 = require("../../util/ErrorResourcesContext");
7
7
  */
8
8
  class ArgumentConstructorHandlerHash {
9
9
  canHandle(value, settings, argsCreator) {
10
- return Boolean(value.property.fields || value.property.hasFields);
10
+ return Boolean(value.property.fields);
11
11
  }
12
12
  async handle(argument, settings, argsCreator) {
13
+ const fields = argument.property.fields.list || [];
13
14
  // Determine all key-value pairs
14
- const entries = await Promise.all(argument.properties.fields.map(async (entry) => {
15
+ const entries = await Promise.all(fields.map(async (entry) => {
15
16
  // Validate entry
16
17
  if (!entry.property.key) {
17
18
  throw new ErrorResourcesContext_1.ErrorResourcesContext(`Missing key in fields entry`, { entry, argument });
@@ -103,6 +103,9 @@ class ConstructionStrategyCommonJsString {
103
103
  return `new function() { return Promise.resolve(${await options.supplier()}); }`;
104
104
  }
105
105
  createPrimitive(options) {
106
+ if (typeof options.value === 'object') {
107
+ return JSON.stringify(options.value);
108
+ }
106
109
  return typeof options.value === 'string' ? `'${options.value}'` : `${options.value}`;
107
110
  }
108
111
  getVariableValue(options) {
@@ -111,9 +111,9 @@ export interface ICreationStrategyPrimitiveOptions<Instance> {
111
111
  */
112
112
  settings: IConstructionSettings;
113
113
  /**
114
- * A string or number value.
114
+ * A string, number or object value.
115
115
  */
116
- value: string | number;
116
+ value: string | number | any;
117
117
  }
118
118
  export interface ICreationStrategyVariableOptions<Instance> {
119
119
  /**
@@ -1,6 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  import type { Readable } from 'stream';
3
- import type * as RDF from 'rdf-js';
3
+ import type * as RDF from '@rdfjs/types';
4
4
  import type { Resource, RdfObjectLoader } from 'rdf-object';
5
5
  import type { Logger } from 'winston';
6
6
  import type { IModuleState } from './ModuleStateBuilder';
@@ -55,7 +55,7 @@ class ComponentRegistry {
55
55
  registerModuleResource(moduleResource) {
56
56
  if (moduleResource.property.components) {
57
57
  for (const component of moduleResource.properties.components) {
58
- component.property.module = moduleResource;
58
+ component.properties.module.push(moduleResource);
59
59
  this.registerComponent(component);
60
60
  }
61
61
  }
@@ -75,11 +75,26 @@ class ComponentRegistryFinalizer {
75
75
  * @param extendingConstructorArgs The constructor argument resources to inherit from.
76
76
  */
77
77
  inheritConstructorArgumentsEntry(constructorArg, extendingConstructorArgs) {
78
+ // Make sure that we have fields in list-form
79
+ if (constructorArg.property.fields && !constructorArg.property.fields.list) {
80
+ if (constructorArg.properties.fields.length > 1) {
81
+ throw new ErrorResourcesContext_1.ErrorResourcesContext(`Invalid fields: Only one value can be defined, or an RDF list must be provided`, {
82
+ constructorArg,
83
+ });
84
+ }
85
+ constructorArg.property.fields = this.objectLoader.createCompactedResource({
86
+ list: constructorArg.properties.fields,
87
+ });
88
+ }
78
89
  for (const extendingConstructorArg of extendingConstructorArgs) {
79
90
  if (extendingConstructorArg.property.fields) {
80
- for (const field of extendingConstructorArg.properties.fields) {
81
- if (!constructorArg.properties.fields.includes(field)) {
82
- constructorArg.properties.fields.push(field);
91
+ // Inherit fields
92
+ for (const field of extendingConstructorArg.property.fields.list || extendingConstructorArg.properties.fields) {
93
+ if (!constructorArg.property.fields) {
94
+ constructorArg.property.fields = this.objectLoader.createCompactedResource({ list: [] });
95
+ }
96
+ if (!constructorArg.property.fields.list.includes(field)) {
97
+ constructorArg.property.fields.list.push(field);
83
98
  }
84
99
  }
85
100
  }
@@ -33,7 +33,7 @@ class ComponentsManagerBuilder {
33
33
  Boolean(options.skipContextValidation);
34
34
  }
35
35
  static createLogger(logLevel = 'warn') {
36
- return winston_1.createLogger({
36
+ return (0, winston_1.createLogger)({
37
37
  level: logLevel,
38
38
  format: winston_1.format.combine(winston_1.format.label({ label: 'Components.js' }), winston_1.format.colorize(), winston_1.format.timestamp(), winston_1.format.printf(({ level: levelInner, message, label: labelInner, timestamp }) => `${timestamp} [${labelInner}] ${levelInner}: ${message}`)),
39
39
  transports: [new winston_1.transports.Console({
@@ -1,6 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  import type { Readable } from 'stream';
3
- import type * as RDF from 'rdf-js';
3
+ import type * as RDF from '@rdfjs/types';
4
4
  import type { RdfObjectLoader } from 'rdf-object';
5
5
  import type { Logger } from 'winston';
6
6
  import type { IModuleState } from './ModuleStateBuilder';
@@ -1,5 +1,6 @@
1
1
  import type { Resource, RdfObjectLoader } from 'rdf-object';
2
2
  import type { Logger } from 'winston';
3
+ import { GenericsContext } from './GenericsContext';
3
4
  import type { IConfigPreprocessor } from './IConfigPreprocessor';
4
5
  import type { ParameterHandler } from './ParameterHandler';
5
6
  /**
@@ -15,12 +16,13 @@ export declare class ConfigPreprocessorComponent implements IConfigPreprocessor<
15
16
  constructor(options: IComponentConfigPreprocessorOptions);
16
17
  canHandle(config: Resource): IComponentConfigPreprocessorHandleResponse | undefined;
17
18
  transform(config: Resource, handleResponse: IComponentConfigPreprocessorHandleResponse): Resource;
19
+ protected createGenericsContext(handleResponse: IComponentConfigPreprocessorHandleResponse, config: Resource): GenericsContext;
18
20
  /**
19
21
  * Determine the constructor arguments of the given config.
20
22
  * @param config A config.
21
23
  * @param handleResponse Return value of the {#canHandle}.
22
24
  */
23
- transformConstructorArguments(config: Resource, handleResponse: IComponentConfigPreprocessorHandleResponse): Resource[];
25
+ transformConstructorArguments(config: Resource, handleResponse: IComponentConfigPreprocessorHandleResponse): Resource;
24
26
  /**
25
27
  * Let this config inherit parameter values from previously instantiated configs.
26
28
  * This will check for inheritanceValues that are defined on the component,
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ConfigPreprocessorComponent = void 0;
4
4
  const Iris_1 = require("../rdf/Iris");
5
5
  const ErrorResourcesContext_1 = require("../util/ErrorResourcesContext");
6
+ const GenericsContext_1 = require("./GenericsContext");
6
7
  /**
7
8
  * Handles config that refer to a component as type.
8
9
  * The component may have parameters that can be applied on the config.
@@ -82,34 +83,59 @@ class ConfigPreprocessorComponent {
82
83
  if (requireElement) {
83
84
  configRaw.property.requireElement = requireElement;
84
85
  }
85
- configRaw.properties.arguments = this.transformConstructorArguments(config, handleResponse);
86
+ configRaw.property.arguments = this.transformConstructorArguments(config, handleResponse);
86
87
  // Validate the input config
87
88
  this.validateConfig(config, handleResponse);
88
89
  return configRaw;
89
90
  }
91
+ createGenericsContext(handleResponse, config) {
92
+ const genericsContext = new GenericsContext_1.GenericsContext(this.objectLoader, handleResponse.component.properties.genericTypeParameters);
93
+ // Populate with manually defined generic type bindings
94
+ const genericTypesInner = handleResponse.component.properties.genericTypeParameters;
95
+ if (genericTypesInner.length < config.properties.genericTypeInstances.length) {
96
+ throw new ErrorResourcesContext_1.ErrorResourcesContext(`Invalid generic type instantiations: more generic types are passed than are defined on the component.`, {
97
+ config,
98
+ component: handleResponse.component,
99
+ });
100
+ }
101
+ for (const [i, genericTypeInstance] of config.properties.genericTypeInstances.entries()) {
102
+ // Remap generic type IRI to inner generic type IRI
103
+ const genericTypeIdInner = genericTypesInner[i].value;
104
+ genericsContext.bindings[genericTypeIdInner] = genericTypeInstance.properties.parameterRangeGenericBindings;
105
+ genericsContext.genericTypeIds[genericTypeIdInner] = true;
106
+ }
107
+ return genericsContext;
108
+ }
90
109
  /**
91
110
  * Determine the constructor arguments of the given config.
92
111
  * @param config A config.
93
112
  * @param handleResponse Return value of the {#canHandle}.
94
113
  */
95
114
  transformConstructorArguments(config, handleResponse) {
96
- // Create a single-arg hash constructor, and add all params as key-value pairs
97
- const param0 = this.objectLoader.createCompactedResource({
98
- // Hack to enforce ArgumentConstructorHandlerHash
99
- hasFields: '"true"',
100
- });
115
+ const entries = [];
116
+ const genericsContext = this.createGenericsContext(handleResponse, config);
101
117
  for (const fieldData of handleResponse.component.properties.parameters) {
102
118
  const field = this.objectLoader.createCompactedResource({});
103
119
  field.property.key = this.objectLoader.createCompactedResource(`"${fieldData.term.value}"`);
104
- for (const value of this.parameterHandler.applyParameterValues(handleResponse.component, fieldData, config)) {
105
- field.properties.value.push(value);
120
+ const value = this.parameterHandler
121
+ .applyParameterValues(handleResponse.component, fieldData, config, genericsContext);
122
+ if (value) {
123
+ field.property.value = value;
106
124
  }
107
- param0.properties.fields.push(field);
125
+ entries.push(field);
108
126
  }
127
+ // Create a single-arg hash constructor, and add all params as key-value pairs
128
+ const param0 = this.objectLoader.createCompactedResource({
129
+ fields: {
130
+ list: entries,
131
+ },
132
+ });
109
133
  // Create constructor arguments list
110
- const args = this.objectLoader.createCompactedResource({});
111
- args.list = [param0];
112
- return [args];
134
+ return this.objectLoader.createCompactedResource({
135
+ list: [
136
+ param0,
137
+ ],
138
+ });
113
139
  }
114
140
  /**
115
141
  * Let this config inherit parameter values from previously instantiated configs.
@@ -2,6 +2,7 @@ import type { Resource } from 'rdf-object';
2
2
  import type { IComponentConfigPreprocessorHandleResponse } from './ConfigPreprocessorComponent';
3
3
  import { ConfigPreprocessorComponent } from './ConfigPreprocessorComponent';
4
4
  import type { IConstructorArgumentsMapper } from './constructorargumentsmapping/IConstructorArgumentsMapper';
5
+ import type { GenericsContext } from './GenericsContext';
5
6
  /**
6
7
  * Handles config that refer to a component as type.
7
8
  * The component may have parameters that can be applied on the config.
@@ -10,7 +11,7 @@ import type { IConstructorArgumentsMapper } from './constructorargumentsmapping/
10
11
  export declare class ConfigPreprocessorComponentMapped extends ConfigPreprocessorComponent implements IConstructorArgumentsMapper {
11
12
  private readonly mappingHandlers;
12
13
  canHandle(config: Resource): IComponentConfigPreprocessorHandleResponse | undefined;
13
- transformConstructorArguments(config: Resource, handleResponse: IComponentConfigPreprocessorHandleResponse): Resource[];
14
- applyConstructorArgumentsParameters(configRoot: Resource, constructorArgs: Resource, configElement: Resource): Resource[];
15
- getParameterValue(configRoot: Resource, parameter: Resource, configElement: Resource, rawValue: boolean): Resource[];
14
+ transformConstructorArguments(config: Resource, handleResponse: IComponentConfigPreprocessorHandleResponse): Resource;
15
+ applyConstructorArgumentsParameters(configRoot: Resource, constructorArgs: Resource, configElement: Resource, genericsContext: GenericsContext): Resource;
16
+ getParameterValue(configRoot: Resource, parameter: Resource, configElement: Resource, rawValue: boolean, genericsContext: GenericsContext): Resource | undefined;
16
17
  }
@@ -33,39 +33,38 @@ class ConfigPreprocessorComponentMapped extends ConfigPreprocessorComponent_1.Co
33
33
  }
34
34
  transformConstructorArguments(config, handleResponse) {
35
35
  const constructorArgs = handleResponse.component.property.constructorArguments;
36
- return this.applyConstructorArgumentsParameters(config, constructorArgs, config);
36
+ const genericsContext = this.createGenericsContext(handleResponse, config);
37
+ return this.applyConstructorArgumentsParameters(config, constructorArgs, config, genericsContext);
37
38
  }
38
- applyConstructorArgumentsParameters(configRoot, constructorArgs, configElement) {
39
+ applyConstructorArgumentsParameters(configRoot, constructorArgs, configElement, genericsContext) {
39
40
  // Check if this constructor args resource can be handled by one of the built-in handlers.
40
41
  for (const handler of this.mappingHandlers) {
41
- if (handler.canHandle(configRoot, constructorArgs, configElement, this)) {
42
- return handler.handle(configRoot, constructorArgs, configElement, this);
42
+ if (handler.canHandle(configRoot, constructorArgs, configElement, this, genericsContext)) {
43
+ return handler.handle(configRoot, constructorArgs, configElement, this, genericsContext);
43
44
  }
44
45
  }
45
46
  // Fallback to original constructor args
46
- return [constructorArgs];
47
+ return constructorArgs;
47
48
  }
48
- getParameterValue(configRoot, parameter, configElement, rawValue) {
49
- var _a;
49
+ getParameterValue(configRoot, parameter, configElement, rawValue, genericsContext) {
50
50
  let valueOut;
51
51
  if (parameter.type === 'NamedNode' && parameter.value === Iris_1.IRIS_RDF.subject) {
52
- valueOut = [this.objectLoader.createCompactedResource(`"${configElement.value}"`)];
53
- valueOut[0].property.unique = this.objectLoader.createCompactedResource('"true"');
52
+ valueOut = this.objectLoader.createCompactedResource(`"${configElement.value}"`);
54
53
  }
55
- else if (parameter.type === 'NamedNode') {
56
- valueOut = this.parameterHandler.applyParameterValues(configRoot, parameter, configElement);
54
+ else if (parameter.type === 'NamedNode' && !parameter.property.fields) {
55
+ valueOut = this.parameterHandler
56
+ .applyParameterValues(configRoot, parameter, configElement, genericsContext);
57
57
  }
58
58
  else {
59
- valueOut = this.applyConstructorArgumentsParameters(configRoot, parameter, configElement);
59
+ valueOut = this.applyConstructorArgumentsParameters(configRoot, parameter, configElement, genericsContext);
60
60
  }
61
61
  // If the referenced IRI should become a plain string
62
62
  if (rawValue) {
63
- const unique = ((_a = valueOut[0].property.unique) === null || _a === void 0 ? void 0 : _a.value) === 'true';
64
- valueOut = [this.objectLoader.createCompactedResource(`"${valueOut[0].value}"`)];
65
- // Make sure to inherit the original param's unique flag
66
- if (unique) {
67
- valueOut[0].property.unique = this.objectLoader.createCompactedResource('"true"');
68
- }
63
+ valueOut = (valueOut === null || valueOut === void 0 ? void 0 : valueOut.list) ?
64
+ this.objectLoader.createCompactedResource({
65
+ list: valueOut.list.map(valueOutSub => `"${valueOutSub.value}"`),
66
+ }) :
67
+ this.objectLoader.createCompactedResource(`"${valueOut ? valueOut.value : 'undefined'}"`);
69
68
  }
70
69
  return valueOut;
71
70
  }
@@ -0,0 +1,30 @@
1
+ import type { Resource, RdfObjectLoader } from 'rdf-object';
2
+ /**
3
+ * Context for binding generic types to a concrete range value.
4
+ */
5
+ export declare class GenericsContext {
6
+ private readonly objectLoader;
7
+ /**
8
+ * Set of generic type ids.
9
+ * @private
10
+ */
11
+ readonly genericTypeIds: Record<string, boolean>;
12
+ /**
13
+ * Mapping of generic type id to the resolved range.
14
+ * @private
15
+ */
16
+ readonly bindings: Record<string, Resource[]>;
17
+ constructor(objectLoader: RdfObjectLoader, genericTypeParameters: Resource[]);
18
+ /**
19
+ * Try to to bind the given value to the given generic.
20
+ * @param genericTypeId IRI of the generic to bind.
21
+ * @param value The value to bind to.
22
+ * @param typeValidator Callback for validating values against types.
23
+ */
24
+ bindGenericTypeToValue(genericTypeId: string, value: Resource | undefined, typeValidator: (subValue: Resource | undefined, subType: Resource) => boolean): boolean;
25
+ /**
26
+ * Infer the parameter range of the given value.
27
+ * @param value A value.
28
+ */
29
+ inferValueRange(value: Resource | undefined): Resource[];
30
+ }
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GenericsContext = void 0;
4
+ /**
5
+ * Context for binding generic types to a concrete range value.
6
+ */
7
+ class GenericsContext {
8
+ constructor(objectLoader, genericTypeParameters) {
9
+ this.objectLoader = objectLoader;
10
+ this.genericTypeIds = Object.fromEntries(genericTypeParameters
11
+ .map(genericTypeParameter => [genericTypeParameter.value, true]));
12
+ this.bindings = {};
13
+ for (const genericTypeParameter of genericTypeParameters) {
14
+ if (genericTypeParameter.property.range) {
15
+ this.bindings[genericTypeParameter.value] = genericTypeParameter.properties.range;
16
+ }
17
+ }
18
+ }
19
+ /**
20
+ * Try to to bind the given value to the given generic.
21
+ * @param genericTypeId IRI of the generic to bind.
22
+ * @param value The value to bind to.
23
+ * @param typeValidator Callback for validating values against types.
24
+ */
25
+ bindGenericTypeToValue(genericTypeId, value, typeValidator) {
26
+ // Fail if an unknown generic type is referenced
27
+ if (!(genericTypeId in this.genericTypeIds)) {
28
+ return false;
29
+ }
30
+ // If the generic was already bound to a range, validate it
31
+ const existingRange = this.bindings[genericTypeId];
32
+ if (existingRange && existingRange.some(existingRangeElement => !typeValidator(value, existingRangeElement))) {
33
+ return false;
34
+ }
35
+ // Infer type of value
36
+ const valueRange = this.inferValueRange(value);
37
+ if (valueRange.length > 0) {
38
+ // If we already had a range, try to align them
39
+ // TODO: this will be needed for resources with common inheritance hierarchies
40
+ // Save inferred type
41
+ this.bindings[genericTypeId] = valueRange;
42
+ }
43
+ return true;
44
+ }
45
+ /**
46
+ * Infer the parameter range of the given value.
47
+ * @param value A value.
48
+ */
49
+ inferValueRange(value) {
50
+ // Value is undefined
51
+ if (!value) {
52
+ return [this.objectLoader.createCompactedResource({ type: 'ParameterRangeUndefined' })];
53
+ }
54
+ // Value is a literal
55
+ if (value.term.termType === 'Literal') {
56
+ return [this.objectLoader.createCompactedResource(value.term.datatype)];
57
+ }
58
+ // Value is a named node
59
+ return value.properties.type;
60
+ }
61
+ }
62
+ exports.GenericsContext = GenericsContext;
63
+ //# sourceMappingURL=GenericsContext.js.map
@@ -1,4 +1,5 @@
1
1
  import type { RdfObjectLoader, Resource } from 'rdf-object';
2
+ import type { GenericsContext } from './GenericsContext';
2
3
  /**
3
4
  * Handles component parameters in the context of a config.
4
5
  */
@@ -11,9 +12,10 @@ export declare class ParameterHandler {
11
12
  * @param configRoot The root config resource that we are working in.
12
13
  * @param parameter The parameter resource to get the value for.
13
14
  * @param configElement Part of the config resource to look for parameter instantiations as predicates.
14
- * @return The parameter value(s)
15
+ * @param genericsContext Context for generic types.
16
+ * @return - The parameter value
15
17
  */
16
- applyParameterValues(configRoot: Resource, parameter: Resource, configElement: Resource): Resource[];
18
+ applyParameterValues(configRoot: Resource, parameter: Resource, configElement: Resource, genericsContext: GenericsContext): Resource | undefined;
17
19
  }
18
20
  export interface IParameterHandlerOptions {
19
21
  objectLoader: RdfObjectLoader;