On Tue, 30 Jun 2026 20:29:44 GMT, Marius Hanl <[email protected]> wrote:

>> Mostly wondering the same - why do we have `ArrayListWrapper` but no wrapper 
>> classes for the other collections? Maybe we can unify / simplify it more.
>> 
>> I did some tests with `@NamedArg` and it really seems to be buggy with more 
>> advanced usecases like this one
>
> @stechy1 do you have an idea about this?
> Since you are most likely the person that knows the most about this logic. 
> Will help us a lot to review the change

I'm not an expert on this. I just start digging into this because `@NamedArg` 
was not working as expected. The author of this piece of code must had a reason 
to write it in this way.

`getReadOnlyProperty(propName)` - inspects the getter's return type and creates 
a temporary container of the appropriate type (`ObservableList` , 
`ObservableSet` , `Map` , `Set` , or `ArrayListWrapper` for a plain  
`Collection` ). Returns `null`  if the property is not a read-only 
collection/map.

This method is called here:


    /**
     * This is used to support read-only collection property. This method must
     * return a Collection of the appropriate type if 1. the property is
     * read-only, and 2. the property is a collection. It must return null
     * otherwise.
     *
     */
    private Object getTemporaryContainer(String propName) {
        Object o = containers.get(propName);
        if (o == null) {
            o = getReadOnlyProperty(propName);
            if (o != null) {
                containers.put(propName, o);
            }
        }
        return o;
    }


---

Methods `getTemporaryContainer()` and `getUserValue()` are in some kind of 
relationship. We can look on this as two phases:

# Phase 1 - Parsing / accumulation
 
ProxyBuilder  extends  Map<String, Object> . While the FXML loader is parsing 
child elements, it calls the standard  Map  methods  containsKey(key)  and  
get(key)  on the builder. Both of those override methods delegate directly to  
getTemporaryContainer :


@Override
public boolean containsKey(Object key) {
    return (getTemporaryContainer(key.toString()) != null);
}

@Override
public Object get(Object key) {
    return getTemporaryContainer(key.toString());   // ← returns the temp 
container
}


The FXML loader gets back the temporary container (e.g.  `ArrayListWrapper` ,  
`ObservableList` …), and populates it with the child elements.

# Phase 2 - Build / resolution

When FXML parsing is done, the loader calls `build()`. At that point:

1. All accumulated _containers_ are flushed into `userValues`.
2. The builder tries to find the best matching constructor / setters.
3. `getUserValue` is called for each parameter/property to retrieve the final, 
correctly-typed value - including the  `ArrayListWrapper` → scalar unwrapping 
logic.

-------------

PR Review Comment: https://git.openjdk.org/jfx/pull/2167#discussion_r3518783450

Reply via email to