1
1
package net .finmath .util .config ;
2
2
3
+ import java .util .Arrays ;
3
4
import java .util .List ;
4
5
import java .util .Map ;
5
6
import java .util .stream .Collectors ;
23
24
public class ConfigTree {
24
25
25
26
private final Node root ;
26
-
27
+
27
28
/**
28
29
* Construct the tree.
29
30
*
@@ -37,13 +38,18 @@ public ConfigTree(List<String> keyOrder, List<Map<String, Object>> configs) {
37
38
/**
38
39
* Get the configuration for a given specification of the properties (selector).
39
40
*
41
+ * The configutation tree is traversed by selecting each route though the value of a specific key in the selector,
42
+ * until the lead node is reached.
43
+ * If keys are missing in the selector of if values do not match a predefined route, a default route is used.
44
+ *
40
45
* @param selector Maps the name (String) of a property to its value (Object).
41
46
* @return The configuration value for the given selector.
42
47
*/
43
48
public Object getConfig (Map <String , Object > selector ) {
44
-
49
+
45
50
Node node = this .root ;
46
-
51
+
52
+ // Traverse the tree where each route is selected though the value of a specific key in the selector.
47
53
while (node instanceof ConfigNode ) {
48
54
ConfigNode configNode = (ConfigNode )node ;
49
55
if (selector .containsKey (configNode .getKey ()) && configNode .getValueToConfig ().keySet ().contains (selector .get (configNode .getKey ()))) {
@@ -53,7 +59,8 @@ public Object getConfig(Map<String, Object> selector) {
53
59
node = configNode .getValueToConfig ().get (SpecialNodes .DEFAULT_VALUE );
54
60
}
55
61
}
56
-
62
+
63
+ // Having reached the value node, return it.
57
64
if (node instanceof ValueNode ) {
58
65
ValueNode valueNode = (ValueNode )node ;
59
66
return valueNode .getValue ();
@@ -62,7 +69,7 @@ public Object getConfig(Map<String, Object> selector) {
62
69
throw new IllegalArgumentException ("Unable to resolve configuration from the given properties." );
63
70
}
64
71
}
65
-
72
+
66
73
/**
67
74
* Helper for the constructor. Recursive contruction of the tree.
68
75
*
@@ -71,27 +78,29 @@ public Object getConfig(Map<String, Object> selector) {
71
78
* @return Node of the (sub-)tree for the given config key.
72
79
*/
73
80
private Node group (List <String > keyOrder , List <Map <String , Object >> configs ) {
74
- if (keyOrder .size () == 0 ) {
81
+ if (keyOrder .size () > 0 ) {
82
+ // Group all elements by the first key in keyOrder....
83
+ String key = keyOrder .get (0 );
84
+ Map <Object , List <Map <String , Object >>> grouped = configs .stream ().collect (Collectors .groupingBy (map -> map .get (key )));
85
+
86
+ // ...call group (recursive) for all values below this key taking the remainder of keyOrder...
87
+ List <String > keyOrderRemain = keyOrder .subList (1 , keyOrder .size ());
88
+ Map <Object , Node > valueToConfig = grouped .entrySet ().stream ().collect (Collectors .toMap (
89
+ Map .Entry ::getKey , entry -> group (keyOrderRemain , entry .getValue ())));
90
+
91
+ // ...create a ConfigNode for this key.
92
+ return new ConfigNode (key , valueToConfig );
93
+ }
94
+ else {
95
+ // If no keys are left in key order, create the leaf node
75
96
if (configs .size () == 1 ) {
76
97
Map <String , Object > config = configs .get (0 );
77
98
Object value = config .get ("value" );
78
99
return new ValueNode ( value );
79
100
}
80
101
else {
81
- throw new IllegalArgumentException ("Multiple configs for same values." );
102
+ throw new IllegalArgumentException ("Multiple configs for the same selector values. " + Arrays . deepToString ( configs . toArray ()) );
82
103
}
83
104
}
84
-
85
- // Group all elements by the first key....
86
- String key = keyOrder .get (0 );
87
- Map <Object , List <Map <String , Object >>> grouped = configs .stream ().collect (Collectors .groupingBy (map -> map .get (key )));
88
-
89
- // ...call group (recursive) for all values below this key...
90
- List <String > keyOrderRemain = keyOrder .subList (1 , keyOrder .size ());
91
- Map <Object , Node > valueToConfig = grouped .entrySet ().stream ().collect (Collectors .toMap (
92
- Map .Entry ::getKey , entry -> group (keyOrderRemain , entry .getValue ())));
93
-
94
- // ...create a ConfigNode for this key.
95
- return new ConfigNode (key , valueToConfig );
96
105
}
97
106
}
0 commit comments