[
https://issues.apache.org/jira/browse/CONFIGURATION-857?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18095834#comment-18095834
]
Maria Galbis commented on CONFIGURATION-857:
--------------------------------------------
Thanks, [~ggregory] . I did some more digging into this.
The current {{'dejaVu'}} set prevents infinite recursion by ensuring that the
same object is not processed more than once during the flattening operation.
Because scalar values are also added to it, duplicate non-{{{}String{}}} scalar
values are removed by the same visited-object check used for cycle detection.
I changed the code so scalars are not added to {{{}'dejaVu'{}}}. This preserves
their duplicates, but makes
{{TestPropertiesConfiguration.testCompress840ArrayListCycle()}} fail. For
example, with {{{}size = 2{}}}, the test expects:
{code:java}
[0, 1]{code}
but the result becomes:
{code:java}
[0, 0, 1, 0, 1]{code}
The extra values come from the nested list copies, which are now processed
instead of being skipped as already visited.
I think duplicate scalar values should always be preserved, since they cannot
create cycles. The remaining question is how containers should be handled:
whether every previously visited container should be skipped, or only
containers already present in the current recursion path.
My proposed approach would be to track containers only and use {{'dejaVu'}} as
a recursion-path set. A container would be added when entering it and removed
when leaving it. This would prevent infinite recursion without deduplicating
scalar values or unrelated repeated containers.
With that behavior, the {{size = 2}} result would be:
{code:java}
[0, 0, 1, 0, 0, 1]{code}
since only the actual back-references would be skipped.
> Clarify flatten() behavior for duplicate scalar values and descendant
> branches with back-references
> ---------------------------------------------------------------------------------------------------
>
> Key: CONFIGURATION-857
> URL: https://issues.apache.org/jira/browse/CONFIGURATION-857
> Project: Commons Configuration
> Issue Type: Bug
> Affects Versions: 2.15.1
> Reporter: Maria Galbis
> Priority: Major
>
> This issue is related to:
> - CONFIGURATION-841 (cyclical container handling)
> - CONFIGURATION-849 (preserving required duplicate values)
> The common problem is that {{flatten()}} has to handle both:
> - recursive container graphs
> - legitimate duplicate scalar values
> These two concerns are currently difficult to separate, and I am not sure
> what the expected behavior should be.
>
> *1. Duplicate scalar values for non-String simple types*
> At the moment, duplicate String values are preserved, but it is not clear
> whether the same behavior is expected for other simple scalar types.
> *Examples:*
> {code:java}
> - ["a", "b", "a"] -> ["a", "b", "a"]
> - [1, 2, 1] -> [1, 2, 1]
> - [true, false, true] -> [true, false, true]
> - [1.5, 2.5, 1.5] -> [1.5, 2.5, 1.5]{code}
> *Question:*
> Should duplicate scalar values be preserved for all simple types, not only
> String?
>
> *2. Descendant containers with a back-reference to an ancestor*
> If duplicate scalar values are preserved, there is still an open question
> about descendant containers that are distinct by identity, but contain a
> back-reference to an ancestor.
> Consider the following structure:
> {code:java}
> root = [0]
> root.add(root)
> root.add(new ArrayList<>(root))
> root.add(1)
> root.add(new ArrayList<>(root)){code}
> Conceptually, this produces a graph where descendant containers are distinct
> by identity, but some of them still contain a back-reference to an ancestor.
> {code:java}
> - [0, self, copy1, 1, copy2]
> - copy1 = [0, self]
> - copy2 = [0, self, copy1, 1]{code}
> If only cyclic container references are removed, the remaining scalar leaves
> would be:
> {code:java}
> [0, 0, 1, 0, 1]{code}
> If instead any descendant branch containing a back-reference is treated as
> invalid, the result would be:
> {code:java}
> [0, 1]{code}
> *Question:*
> Which behavior is expected for {{{}flatten(){}}}?
> - keep scalar leaves from descendant branches and only prune cyclic ontainer
> references
> - or discard the whole descendant branch once it points back to an ancestor
>
> The important point is that the implementation cannot reliably distinguish a
> copied container from a legitimate distinct container with similar or
> overlapping content, so the expected semantics need to be clarified before
> changing the implementation.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)