-
Notifications
You must be signed in to change notification settings - Fork 23
/
metadataEvaluator.js
104 lines (91 loc) · 3.89 KB
/
metadataEvaluator.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// metadata filters
import defaultMetadataFilter from './filter/defaultMetadataFilter.js';
import entityMetadataFilter from './filter/entityMetadataFilter.js';
import arrayMetadataFilter from './filter/arrayMetadataFilter.js';
// property filters
import defaultPropertyMetadataFilter from './property-filter/defaultMetadataPropertyFilter.js';
class MetadataEvaluator {
constructor() {
// this array contains objects like: { property: 'invalid', filter: filter }
// fieldFilters that don't have a property associated will act on all properties
// in the order they were registered
this.fieldFilters = [];
// this array contains metadata filters
this.propertyFilters = [];
}
/**
* Evaluates the given metadata against the model
* @param propertyMetadata - Can be either an object or an array of objects
* @param model
* @param keyPrefix
* @param reduxFieldProps
* @param onChange
* @returns {{}}
*/
evaluate(propertyMetadata, model, keyPrefix, reduxFieldProps, onChange) {
if(!propertyMetadata) throw Error('Argument \'propertyMetadata\' should be truthy');
if (!model) throw Error('\'model\' should be truthy');
if (propertyMetadata.constructor === Array) return propertyMetadata.map(i => this.evaluate(i, model, keyPrefix, reduxFieldProps, onChange));
let result = {};
Object.keys(propertyMetadata).forEach((fieldName) => {
result[fieldName] = this.filterPropertyField(fieldName, propertyMetadata[fieldName], model);
});
let newPrefix = keyPrefix ? `${keyPrefix}.${propertyMetadata.name}` : propertyMetadata.name;
return this.filterProperty(result, model, newPrefix, reduxFieldProps, onChange);
}
/**
* Adds the given filter
*/
addPropertyFilter(filter) {
if (!filter) throw Error('\'filter\' should be truthy');
this.propertyFilters.push(filter);
}
/**
* Adds the given filter for the given metadata property name
* @param metadataProperty
* @param filter
*/
addPropertyFieldFilter(filter, metadataProperty) {
if (!filter) throw Error('\'filter\' should be truthy');
this.fieldFilters.push({property: metadataProperty, filter: filter});
}
/**
* Filters the given property against the model
* @param fieldName
* @param fieldValue
* @param model
*/
filterPropertyField(fieldName, fieldValue, model) {
let processedFieldValue = fieldValue;
for (let i = 0; i < this.fieldFilters.length; i++) {
if (!this.fieldFilters[i].property || this.fieldFilters[i].property === fieldName) {
processedFieldValue = this.fieldFilters[i].filter.filter(fieldName, processedFieldValue, model);
}
}
return processedFieldValue;
}
/**
* Filters the given metadata against the model
* @param metadata
* @param model
* @param keyPrefix
* @param metadataIndex
* @param reduxProps
* @returns {*}
*/
filterProperty(metadata, model, keyPrefix, metadataIndex, reduxProps) {
let processedMetadata = metadata;
for (let i = 0; i < this.propertyFilters.length; i++) {
processedMetadata = this.propertyFilters[i].filter(processedMetadata, model, keyPrefix, this, metadataIndex, reduxProps);
}
return processedMetadata;
}
}
let metadataEvaluator = new MetadataEvaluator();
// register metadata filters
metadataEvaluator.addPropertyFilter(defaultMetadataFilter); // sets redux props, key and id
metadataEvaluator.addPropertyFilter(entityMetadataFilter); // processes entities
metadataEvaluator.addPropertyFilter(arrayMetadataFilter); // processes arrays
// register property field filters
metadataEvaluator.addPropertyFieldFilter(defaultPropertyMetadataFilter); // evaluates functions to literals
export default metadataEvaluator;