Skip to content

Commit 0f28819

Browse files
author
Nicolai Parlog
committed
Implemented 'NestedBooleanProperty' including the builder and tests.
1 parent f9bd036 commit 0f28819

8 files changed

+344
-0
lines changed

src/org/codefx/libfx/nesting/AbstractNestingNestingBuilder.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.util.Objects;
44

5+
import javafx.beans.property.BooleanProperty;
56
import javafx.beans.property.DoubleProperty;
67
import javafx.beans.property.FloatProperty;
78
import javafx.beans.property.IntegerProperty;
@@ -83,6 +84,22 @@ public <N> ObjectPropertyNestingBuilder<N> nestProperty(NestingStep<T, Property<
8384
return new ObjectPropertyNestingBuilder<N>(this, nestingStep);
8485
}
8586

87+
/**
88+
* Returns a builder for nestings whose inner observable is a {@link BooleanProperty}. The created nestings depend
89+
* on this builder's outer observable and nesting steps and adds the specified step as the next one.
90+
*
91+
* @param nestingStep
92+
* the function which performs the nesting step from one observable to the next
93+
* @return a {@link BooleanPropertyNestingBuilder} which builds a nesting from this builder's settings and the
94+
* specified nesting steps
95+
* @throws NullPointerException
96+
* if the specified function is null
97+
*/
98+
public BooleanPropertyNestingBuilder nestBooleanProperty(NestingStep<T, BooleanProperty> nestingStep) {
99+
Objects.requireNonNull(nestingStep, "The argument 'nestingStep' must not be null.");
100+
return new BooleanPropertyNestingBuilder(this, nestingStep);
101+
}
102+
86103
/**
87104
* Returns a builder for nestings whose inner observable is an {@link IntegerProperty}. The created nestings depend
88105
* on this builder's outer observable and nesting steps and adds the specified step as the next one.
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package org.codefx.libfx.nesting;
2+
3+
import javafx.beans.property.BooleanProperty;
4+
5+
import org.codefx.libfx.nesting.property.NestedBooleanProperty;
6+
import org.codefx.libfx.nesting.property.NestedBooleanPropertyBuilder;
7+
8+
/**
9+
* A builder for all kinds of nested functionality whose innermost value is held by a {@link BooleanProperty}.
10+
*/
11+
public class BooleanPropertyNestingBuilder extends AbstractNestingBuilder<Boolean, BooleanProperty> {
12+
13+
// #region CONSTRUCTION
14+
15+
/**
16+
* Creates a new nesting builder which acts as a nested builder.
17+
*
18+
* @param <P>
19+
* the type the previous builder wraps
20+
* @param previousNestedBuilder
21+
* the previous builder
22+
* @param nestingStep
23+
* the function which performs the nesting step from one observable to the next
24+
*/
25+
<P> BooleanPropertyNestingBuilder(
26+
AbstractNestingBuilder<P, ?> previousNestedBuilder,
27+
NestingStep<P, BooleanProperty> nestingStep) {
28+
29+
super(previousNestedBuilder, nestingStep);
30+
}
31+
32+
//#end CONSTRUCTION
33+
34+
// #region BUILD
35+
36+
/**
37+
* Creates a nested property from this builder's settings. This method can be called arbitrarily often and each call
38+
* returns a new instance.
39+
*
40+
* @return a new {@link NestedBooleanProperty} instance with no owning bean and no name
41+
*/
42+
public NestedBooleanProperty buildProperty() {
43+
Nesting<BooleanProperty> nesting = buildNesting();
44+
return NestedBooleanPropertyBuilder.forNesting(nesting).build();
45+
}
46+
47+
/**
48+
* Returns a nested object property builder which can be used to define the new property's attributes before
49+
* building it.
50+
*
51+
* @return a new instance of {@link NestedBooleanPropertyBuilder}
52+
*/
53+
public NestedBooleanPropertyBuilder buildPropertyWithBuilder() {
54+
Nesting<BooleanProperty> nesting = buildNesting();
55+
return NestedBooleanPropertyBuilder.forNesting(nesting);
56+
}
57+
58+
//#end BUILD
59+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package org.codefx.libfx.nesting.property;
2+
3+
import java.util.Objects;
4+
5+
import javafx.beans.property.BooleanProperty;
6+
import javafx.beans.property.Property;
7+
import javafx.beans.property.ReadOnlyBooleanProperty;
8+
import javafx.beans.property.SimpleBooleanProperty;
9+
10+
import org.codefx.libfx.nesting.Nesting;
11+
12+
/**
13+
* A {@link BooleanProperty} which also implements {@link NestedProperty}.
14+
*/
15+
public class NestedBooleanProperty extends SimpleBooleanProperty implements NestedProperty<Boolean> {
16+
17+
// #region PROPERTIES
18+
19+
/**
20+
* The property indicating whether the nesting's inner observable is currently null.
21+
*/
22+
private final BooleanProperty innerObservableNull;
23+
24+
//#end PROPERTIES
25+
26+
// #region CONSTUCTION
27+
28+
/**
29+
* Creates a new property. Except {@code nesting} all arguments can be null.
30+
*
31+
* @param nesting
32+
* the nesting this property is based on
33+
* @param bean
34+
* the bean which owns this property; can be null
35+
* @param name
36+
* this property's name; can be null
37+
*/
38+
NestedBooleanProperty(Nesting<? extends Property<Boolean>> nesting, Object bean, String name) {
39+
super(bean, name);
40+
Objects.requireNonNull(nesting, "The argument 'nesting' must not be null.");
41+
this.innerObservableNull = new SimpleBooleanProperty(this, "innerObservableNull");
42+
43+
PropertyToNestingBinding.bind(this, isNull -> innerObservableNull.set(isNull), nesting);
44+
}
45+
46+
//#end CONSTUCTION
47+
48+
// #region IMPLEMENTATION OF 'NestedProperty'
49+
50+
@Override
51+
public ReadOnlyBooleanProperty innerObservableNull() {
52+
return innerObservableNull;
53+
}
54+
55+
@Override
56+
public boolean isInnerObservableNull() {
57+
return innerObservableNull.get();
58+
}
59+
60+
//#end IMPLEMENTATION OF 'NestedProperty'
61+
62+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package org.codefx.libfx.nesting.property;
2+
3+
import javafx.beans.property.BooleanProperty;
4+
5+
import org.codefx.libfx.nesting.Nesting;
6+
7+
/**
8+
* A builder for a {@link NestedBooleanProperty} which is bound to the {@link Nesting#innerObservable() innerObservable}
9+
* of a {@link Nesting}.
10+
*/
11+
public class NestedBooleanPropertyBuilder extends AbstractNestedPropertyBuilder<BooleanProperty, NestedBooleanProperty> {
12+
13+
// #region CONSTRUCTION
14+
15+
/**
16+
* Creates a new builder which uses the specified nesting.
17+
*
18+
* @param nesting
19+
* the nesting which will be used for all nested properties
20+
*/
21+
private NestedBooleanPropertyBuilder(Nesting<BooleanProperty> nesting) {
22+
super(nesting);
23+
}
24+
25+
/**
26+
* Creates a new builder which uses the specified nesting.
27+
*
28+
* @param nesting
29+
* the nesting which will be used for all nested properties
30+
* @return a new instance of {@link NestedBooleanPropertyBuilder}
31+
*/
32+
public static NestedBooleanPropertyBuilder forNesting(Nesting<BooleanProperty> nesting) {
33+
return new NestedBooleanPropertyBuilder(nesting);
34+
}
35+
36+
//#end CONSTRUCTION
37+
38+
// #region METHODS
39+
40+
@Override
41+
public NestedBooleanProperty build() {
42+
return new NestedBooleanProperty(getNesting(), getBean(), getName());
43+
}
44+
45+
//#end METHODS
46+
47+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package org.codefx.libfx.nesting.property;
2+
3+
import static org.codefx.libfx.nesting.testhelper.NestingAccess.getNestingObservable;
4+
import static org.codefx.libfx.nesting.testhelper.NestingAccess.getNestingValue;
5+
import static org.codefx.libfx.nesting.testhelper.NestingAccess.setNestingObservable;
6+
import static org.junit.Assert.assertEquals;
7+
import static org.junit.Assert.assertFalse;
8+
import static org.junit.Assert.assertNotSame;
9+
import static org.junit.Assert.assertTrue;
10+
import javafx.beans.property.BooleanProperty;
11+
import javafx.beans.property.SimpleBooleanProperty;
12+
13+
import org.codefx.libfx.nesting.Nesting;
14+
import org.junit.Test;
15+
16+
/**
17+
* Abstract superclass to tests for {@link NestedBooleanProperty NestedBooleanProperty} which only leaves the creation
18+
* of the tested properties (by {@link #createNestedPropertyFromNesting(Nesting)}) to the subclasses.
19+
*/
20+
public abstract class AbstractNestedBooleanPropertyTest extends AbstractNestedPropertyTest<Boolean, BooleanProperty> {
21+
22+
/*
23+
* Since Boolean has only two values, 'createNewValue' can not fulfill its contract. Instead it always returns
24+
* 'true' whereas 'createNewObservableWithSomeValue' uses false. All tests where this might come into play are
25+
* overridden below (for better readability or just to make them work).
26+
*/
27+
28+
@Override
29+
protected boolean allowsNullValues() {
30+
return false;
31+
}
32+
33+
@Override
34+
protected Boolean createNewValue() {
35+
return true;
36+
}
37+
38+
@Override
39+
protected BooleanProperty createNewObservableWithValue(Boolean value) {
40+
return new SimpleBooleanProperty(value);
41+
}
42+
43+
@Override
44+
protected BooleanProperty createNewObservableWithSomeValue() {
45+
return createNewObservableWithValue(false);
46+
}
47+
48+
// #region OVERRIDDEN TEST METHODS
49+
50+
@Override
51+
@Test
52+
public void testChangingNewObservablesValue() {
53+
// set a new observable whose value is 'false'...
54+
BooleanProperty newObservable = createNewObservableWithValue(false);
55+
setNestingObservable(getNesting(), newObservable);
56+
// (assert that setting the observable worked)
57+
assertEquals(newObservable, getNestingObservable(getNesting()));
58+
59+
// ... and change its value to 'true'
60+
newObservable.setValue(true);
61+
62+
// assert that nesting and property hold the new value
63+
assertTrue(getNestingValue(getNesting()));
64+
assertTrue(getPropertyValue());
65+
}
66+
67+
@Override
68+
@Test
69+
public void testChangingOldObservablesValue() {
70+
// store the old observable which has the value 'false' (see 'createNewObservableWithSomeValue') ...
71+
BooleanProperty oldObservable = getNestingObservable(getNesting());
72+
73+
// ... set a new observable with value 'false' ...
74+
BooleanProperty newObservableWithFalse = createNewObservableWithValue(false);
75+
setNestingObservable(getNesting(), newObservableWithFalse);
76+
// (assert that setting the observable worked)
77+
assertNotSame(oldObservable, getNestingObservable(getNesting()));
78+
79+
// ... and change the old observable's value
80+
oldObservable.setValue(true);
81+
82+
// assert that nesting and property hold the new observable's value (i.e. 'false') instead of the old observable's new value (i.e. 'true')
83+
assertFalse(getNestingValue(getNesting()));
84+
assertFalse(getPropertyValue());
85+
}
86+
87+
//#end OVERRIDDEN TEST METHODS
88+
89+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package org.codefx.libfx.nesting.property;
2+
3+
import javafx.beans.property.BooleanProperty;
4+
import javafx.beans.property.SimpleBooleanProperty;
5+
6+
import org.codefx.libfx.nesting.Nesting;
7+
import org.codefx.libfx.nesting.testhelper.NestingAccess.EditableNesting;
8+
import org.junit.runner.RunWith;
9+
import org.junit.runners.Suite;
10+
import org.junit.runners.Suite.SuiteClasses;
11+
12+
/**
13+
* Tests the class {@link NestedBooleanPropertyBuilder}.
14+
*/
15+
@RunWith(Suite.class)
16+
@SuiteClasses({
17+
NestedBooleanPropertyBuilderTest.AbstractBuilderContract.class,
18+
NestedBooleanPropertyBuilderTest.CreatedProperties.class,
19+
})
20+
public class NestedBooleanPropertyBuilderTest {
21+
22+
/**
23+
* Tests whether the builder fulfills the contract defined by {@link AbstractNestedPropertyBuilder}.
24+
*/
25+
public static class AbstractBuilderContract
26+
extends AbstractNestedPropertyBuilderTest<BooleanProperty, NestedBooleanProperty> {
27+
28+
@Override
29+
protected AbstractNestedPropertyBuilder<BooleanProperty, NestedBooleanProperty> createBuilder() {
30+
BooleanProperty innerObservable = new SimpleBooleanProperty(false);
31+
EditableNesting<BooleanProperty> nesting = EditableNesting.createWithInnerObservable(innerObservable);
32+
return NestedBooleanPropertyBuilder.forNesting(nesting);
33+
}
34+
35+
}
36+
37+
/**
38+
* Uses the builder to create properties which are then tested.
39+
*/
40+
public static class CreatedProperties extends AbstractNestedBooleanPropertyTest {
41+
42+
@Override
43+
protected NestedProperty<Boolean> createNestedPropertyFromNesting(Nesting<BooleanProperty> nesting) {
44+
// use the builder to create the property
45+
NestedBooleanPropertyBuilder builder = NestedBooleanPropertyBuilder.forNesting(nesting);
46+
return builder.build();
47+
}
48+
49+
}
50+
51+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package org.codefx.libfx.nesting.property;
2+
3+
import javafx.beans.property.BooleanProperty;
4+
5+
import org.codefx.libfx.nesting.Nesting;
6+
7+
/**
8+
* Tests the class {@link NestedBooleanProperty}.
9+
*/
10+
public class NestedBooleanPropertyTest extends AbstractNestedBooleanPropertyTest {
11+
12+
@Override
13+
protected NestedProperty<Boolean> createNestedPropertyFromNesting(Nesting<BooleanProperty> nesting) {
14+
return new NestedBooleanProperty(nesting, null, null);
15+
}
16+
17+
}

test/org/codefx/libfx/nesting/property/_AllNestedPropertyTests.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
*/
1010
@RunWith(Suite.class)
1111
@SuiteClasses({
12+
NestedBooleanPropertyBuilderTest.class,
13+
NestedBooleanPropertyTest.class,
1214
NestedDoublePropertyBuilderTest.class,
1315
NestedDoublePropertyTest.class,
1416
NestedFloatPropertyBuilderTest.class,

0 commit comments

Comments
 (0)