|
18 | 18 |
|
19 | 19 | import java.io.IOException;
|
20 | 20 | import java.io.Reader;
|
| 21 | +import java.util.ArrayList; |
21 | 22 | import java.util.Arrays;
|
22 | 23 | import java.util.Collection;
|
23 | 24 | import java.util.Collections;
|
@@ -69,6 +70,8 @@ public abstract class YamlProcessor {
|
69 | 70 |
|
70 | 71 | private Set<String> supportedTypes = Collections.emptySet();
|
71 | 72 |
|
| 73 | + private boolean isIncludeSimpleLists = false; |
| 74 | + |
72 | 75 |
|
73 | 76 | /**
|
74 | 77 | * A map of document matchers allowing callers to selectively use only
|
@@ -150,6 +153,73 @@ public void setSupportedTypes(Class<?>... supportedTypes) {
|
150 | 153 | }
|
151 | 154 | }
|
152 | 155 |
|
| 156 | + /** |
| 157 | + * Set the {@code isIncludeSimpleLists} flag, which enables adding the string |
| 158 | + * representation of simple lists/arrays to the {@code Properties} in addition |
| 159 | + * to the flattened indexed keys. When set to {@code false}, the default behavior |
| 160 | + * of just adding flattened keys is restored. |
| 161 | + * <p> For example, considering the following YAML snippet: |
| 162 | + * <pre><code> |
| 163 | + * animals: |
| 164 | + * mammals: |
| 165 | + * - cat |
| 166 | + * - dog |
| 167 | + * - horse |
| 168 | + * unicorns: [] |
| 169 | + * </code></pre> |
| 170 | + * By default ({@code isAddFulllists == false}) the following entries are |
| 171 | + * added to the properties: |
| 172 | + * <pre><code> |
| 173 | + * animals.mammals[0]="cat" |
| 174 | + * animals.mammals[1]="dog" |
| 175 | + * animals.mammals[2]="horse" |
| 176 | + * animals.unicorns="" //an empty String |
| 177 | + * </code></pre> |
| 178 | + * With the flag set to {@code true}, an additional {@code animals.mammals} |
| 179 | + * key is added with the {@code List} representation of all elements. |
| 180 | + * The properties become: |
| 181 | + * <pre><code> |
| 182 | + * animals.mammals[0]="cat" |
| 183 | + * animals.mammals[1]="dog" |
| 184 | + * animals.mammals[2]="horse" |
| 185 | + * animals.mammals="[cat,dog,horse]" // can be parsed as a List |
| 186 | + * animals.unicorns="[]" // String representation of an empty List |
| 187 | + * </code></pre> |
| 188 | + * <p>This flag is ignored at levels where a list is detected to |
| 189 | + * contain a nested list, array or map: |
| 190 | + * <code><pre> |
| 191 | + * all: |
| 192 | + * animals: |
| 193 | + * - name: cat |
| 194 | + * type: mammal |
| 195 | + * - name: dragon |
| 196 | + * type: imaginary |
| 197 | + * </pre></code> |
| 198 | + * The above YAML results in the following properties even if this flag is |
| 199 | + * set to {@code true}: |
| 200 | + * <code><pre> |
| 201 | + * all.animals[0].name=cat |
| 202 | + * all.animals[0].type=mammal |
| 203 | + * all.animals[1].name=dragon |
| 204 | + * all.animals[1].type=imaginary |
| 205 | + * </pre></code> |
| 206 | + * |
| 207 | + * @param isIncludeSimpleLists {@code true} to enabling adding full lists during |
| 208 | + * flattening, {@code false} to disable it (the default) |
| 209 | + * @since 6.0.7 |
| 210 | + */ |
| 211 | + public void setIncludeSimpleLists(boolean isIncludeSimpleLists) { |
| 212 | + this.isIncludeSimpleLists = isIncludeSimpleLists; |
| 213 | + } |
| 214 | + |
| 215 | + /** |
| 216 | + * @return the value of the {{@link #setIncludeSimpleLists(boolean) isAddFullLists flag} |
| 217 | + * @since 6.0.7 |
| 218 | + */ |
| 219 | + protected boolean isIncludeSimpleLists() { |
| 220 | + return this.isIncludeSimpleLists; |
| 221 | + } |
| 222 | + |
153 | 223 | /**
|
154 | 224 | * Provide an opportunity for subclasses to process the Yaml parsed from the supplied
|
155 | 225 | * resources. Each resource is parsed in turn and the documents inside checked against
|
@@ -326,13 +396,32 @@ else if (value instanceof Map map) {
|
326 | 396 | else if (value instanceof Collection collection) {
|
327 | 397 | // Need a compound key
|
328 | 398 | if (collection.isEmpty()) {
|
329 |
| - result.put(key, ""); |
| 399 | + result.put(key, isIncludeSimpleLists() ? Collections.emptyList() : ""); |
330 | 400 | }
|
331 | 401 | else {
|
332 | 402 | int count = 0;
|
| 403 | + List<String> subCollectionKeys = new ArrayList<>(); |
333 | 404 | for (Object object : collection) {
|
334 |
| - buildFlattenedMap(result, Collections.singletonMap( |
335 |
| - "[" + (count++) + "]", object), key); |
| 405 | + String indexKeyPart = "[" + (count++) + "]"; |
| 406 | + if (object instanceof Collection || object instanceof Map) { |
| 407 | + subCollectionKeys.add(indexKeyPart); |
| 408 | + } |
| 409 | + buildFlattenedMap(result, Collections.singletonMap(indexKeyPart, object), key); |
| 410 | + } |
| 411 | + if (isIncludeSimpleLists()) { |
| 412 | + if (!subCollectionKeys.isEmpty()) { |
| 413 | + if (this.logger.isDebugEnabled()) { |
| 414 | + this.logger.debug(key + " not added as a full list because it contains " |
| 415 | + + "nested lists/maps at indexes " + subCollectionKeys.stream().collect(Collectors.joining(","))); |
| 416 | + } |
| 417 | + else { |
| 418 | + this.logger.warn(key + " not added as a full list because it contains " |
| 419 | + + subCollectionKeys.size() + " nested lists/maps"); |
| 420 | + } |
| 421 | + } |
| 422 | + else { |
| 423 | + result.put(key, collection); |
| 424 | + } |
336 | 425 | }
|
337 | 426 | }
|
338 | 427 | }
|
|
0 commit comments