codeconsole commented on code in PR #16732:
URL: https://github.com/apache/grails-core/pull/16732#discussion_r4368880392
##########
grails-bootstrap/src/main/groovy/org/grails/config/NavigableMap.groovy:
##########
@@ -199,30 +246,160 @@ class NavigableMap implements Map<String, Object>,
Cloneable {
mergeMaps(rootMap, newPath , subMap, (Map) sourceValue,
parseFlatKeys)
newValue = subMap
} else {
- newValue = sourceValue
+ newValue = mergedValue(sourceValue)
}
if (isNestedSet && newValue == null) {
- if (path) {
-
- def subMap = rootMap.get(path)
- if (subMap instanceof Map) {
- subMap.remove(sourceKey)
- }
- def keysToRemove = rootMap.keySet().findAll() { String key
->
- key.startsWith("${path}.")
- }
- for (key in keysToRemove) {
- rootMap.remove(key)
- }
- }
+ // the flat key of the removed property, those below it and
its indexed aliases go with it;
+ // the flat keys of its siblings stay
+ String removedKey = path ? "${path}.${sourceKey}".toString() :
sourceKey
+ removeKeysBelow(rootMap, removedKey, ['.', '['])
+ rootMap.remove(removedKey)
targetMap.remove(sourceKey)
} else {
+ String flatKey = path ? "${path}.${sourceKey}".toString() :
sourceKey
if (path) {
- rootMap.put("${path}.${sourceKey}".toString(), newValue)
+ mergeMapEntry(rootMap, flatKey, newValue)
}
mergeMapEntry(targetMap, sourceKey, newValue)
+ if (replacedBy(currentValue, newValue)) {
+ // the element keys of the container the value replaces go
with it; the flat keys of the
+ // entries of a block stay, as they always have
+ removeKeysBelow(rootMap, flatKey, ['['])
+ }
+ writeElements(rootMap, flatKey, newValue)
+ }
+ }
+ }
+
+ /**
+ * Writes the element keys of a list, {@code a.rows[0]} and, for an
element that is a map, {@code a.rows[0].name},
+ * as the indexed keys of a configuration file write them, so that a list
is read alike however it was written.
+ * A map that is not a block of this configuration, an element of a list
or a value an indexed key wrote, has
+ * its entries written the same way; a block writes its own flat keys as
it is merged.
+ */
+ private void writeElements(NavigableMap rootMap, String flatKey, Object
value) {
+ if (value instanceof List) {
+ int index = 0
+ for (Object element in (List) value) {
Review Comment:
Fixed in 7e9b4c22d0. The key `app.names[0]` held the element as it was when
the list was written, so a `set`, `add` or `remove` on the list left it behind,
and `other.merge(map, true)` wrote the old element back into the list through
`mergeIndexedEntry`; the same for an entry of an element map set in place, and
for a list written by indexed keys. Nothing is held per element now: an indexed
key is read through the container held under the name before its first
subscript and the elements the subscripts and names after it step through, so
`get`, `containsKey` and `getProperty` answer from the list as it is,
`toProperties()` and `toFlatConfig()` write the elements from the list, and a
map merged into another carries its lists and no element keys, so it writes
nothing into them. `NavigableMapPropertySource` reads an element the same way,
so `environment.getProperty('app.names[0]')` follows the list too; its property
names are still those of the elements the lists held when it was made.
The code that wrote and removed element keys goes. `keySet()` no longer lists
a key per element, and the bracket spelling of a map-subscript key,
`a.mappings[/api/**]`, is no longer in `toProperties()`, which writes
`a.mappings./api/**` as before.
Pinned in `NavigableMapSpec` with your sequence, `map.app.names = ['one']`
then `map.app.names[0] = 'two'`, read by the key, by `toProperties()` for the
list and for the element, and after `other.merge(map, true)` by the other map
with the list still `['two']`; and over an element set, added and removed and
an entry of an element map set, added and removed, each read by `get`,
`containsKey` and `toProperties()` and after a merge into another map.
`PropertySourcesConfigSpec` reads the same through a config,
`NavigableMapPropertySourceSpec` through the property source, and
`GrailsAppGroovyConfigSpec` sets an element of an `application.groovy` list
through the config of a started `GrailsApp` and reads it back through the
config and the environment. The probe over the seventeen write paths reports no
stale or missing element key any more; what remains is the dotted flat key of a
block's entry that a value replaced, the block rule, and the re-merge of a
map-subscript container as a blo
ck with `parseFlatKeys` off, both older than this PR.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]