[BUG]Order in collection is not preserved while using useImmutableCollections option
pawellabaj opened this issue · comments
When a record has a component of the type that is the Set
implementation keeping the order, the order is lost when using useImmutableCollections = true option.
Following test shows the problem:
import io.soabase.recordbuilder.core.RecordBuilder;
import java.util.Set;
@RecordBuilder
@RecordBuilder.Options(useImmutableCollections = true)
record OrderedSetRecord(Set<String> orderedSet) {}
import org.junit.jupiter.api.Test;
import java.util.LinkedHashSet;
import static org.assertj.core.api.Assertions.assertThat;
public class TestOrderedSetsBuilder {
@Test
void shouldKeepOrderInSetIfProvided() {
// given
var orderedSet = new LinkedHashSet<String>();
orderedSet.add("C");
orderedSet.add("B");
orderedSet.add("A");
// when
var record = OrderedSetRecordBuilder.builder().orderedSet(orderedSet).build();
// then
assertThat(record.orderedSet()).containsExactly("C", "B", "A");
}
}
Order is lost in java.util.Set#copyOf
method used in generated __set
method.
One of possible solution is te generate __set
method as follow:
private static <T> Set<T> __set(Collection<? extends T> o) {
return (o != null) ? Collections.unmodifiableSet((Set<T>) o) : Set.of();
}
unmodifiableSet
unfortunately only creates a view on the still modifiable original set. Meaning that from a reference to the underlying set the new "unmodifiable" set could change. This is ofc not desirable.
In most cases, reference to the original collection is not being kept and collection from the record is used.
Another possible solution would be to treat java.util.LinkedHashSet
or com.google.common.collect.ImmutableSet
in a special way.
Introducing the useUnmodifiableCollections option works for me. However, it didn't solve the issue reported here.
Possibly checking for specialized interfaces like SortedSet, etc. (see #151 ) is the solution.
@pawellabaj could you provide a PR?
@Randgalt , I'm thinking of it.
Do you consider introducing Guava as a dependency to your project?
Do you consider introducing Guava as a dependency to your project
No - we shouldn't do that. We could, however, do FQPN string comparisons if needed.
@Randgalt have you thought about introducing a plugins/extensions mechanism?
Extensions with the usage of any library could be implemented.
At this point I'd like to limit any new customizations. This library ran into a lot of problems with some of the recently added customizations.