[ 
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)

Reply via email to