I am trying to bind two ListProperties
bidirectional. The problem is, they have different types (A and B).
Test4#test01()
illustrates what I would like to do.
Test4#test02()
is my naive approach to do so, but this results in a StackOverflowError
How can I bind List<A>
bidirectional to List<B>
using given AB transformer and BA transformer?
Here is a MWE:
public class Test4 {
public Test4() {
}
@BeforeClass
public static void setUpBeforeClass() throws Exception {
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
}
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
class A {
@Override
public boolean equals(final Object obj) {
return obj instanceof A;
}
}
class B {
@Override
public boolean equals(final Object obj) {
return obj instanceof B;
}
}
ListProperty<A> listA = new SimpleListProperty<>(FXCollections.observableArrayList());
ListProperty<B> listB = new SimpleListProperty<>(FXCollections.observableArrayList());
Function<A, B> trivialTransformerAB = a -> new B();
Function<B, A> trivialTransformerBA = b -> new A();
ListChangeListener<A> listAListener;
ListChangeListener<B> listBListener;
@Test
public void test01() {
// Bindings.bindContentBidirectional(listA, listB,
// trivialTransformerAB, trivialTransformerBA);
}
@Test
public void test02() {
listAListener = c -> {
while (c.next()) {
if (c.wasRemoved() || c.wasUpdated()) {
c.getList().subList(c.getFrom(), c.getTo())
.forEach(a -> listB.remove(trivialTransformerAB.apply(a)));
}
if (c.wasAdded() || c.wasUpdated()) {
c.getList().subList(c.getFrom(), c.getTo()).forEach(a -> {
final B b = trivialTransformerAB.apply(a);
if (!listB.contains(b)) {
listB.add(trivialTransformerAB.apply(a));
}
});
}
}
};
listBListener = c -> {
while (c.next()) {
if (c.wasRemoved() || c.wasUpdated()) {
c.getList().subList(c.getFrom(), c.getTo())
.forEach(b -> listA.remove(trivialTransformerBA.apply(b)));
}
if (c.wasAdded() || c.wasUpdated()) {
c.getList().subList(c.getFrom(), c.getTo()).forEach(b -> {
final A a = trivialTransformerBA.apply(b);
if (!listA.contains(a)) {
listA.add(trivialTransformerBA.apply(b));
}
});
}
}
};
listA.addListener(listAListener);
listB.addListener(listBListener);
listA.add(new A());
assertThat(listB.size(), is(1));
}
}
Error:
java.lang.StackOverflowError
at java.util.Collections$UnmodifiableCollection.isEmpty(Collections.java:1031)
at java.util.Collections$UnmodifiableCollection.isEmpty(Collections.java:1031)
[..]
The way you set up the listeners created an endless loop.
I would suggest setting a breakpoint each in these two lines and step through with a debugger:
listB.add(trivialTransformerAB.apply(a));
listA.add(trivialTransformerBA.apply(b));