< prev index next >

modules/javafx.base/src/main/java/javafx/beans/binding/When.java

Print this page

        

@@ -24,10 +24,13 @@
  */
 
 package javafx.beans.binding;
 
 import java.lang.ref.WeakReference;
+import java.util.Objects;
+import java.util.function.BiFunction;
+import java.util.function.Function;
 
 import javafx.beans.InvalidationListener;
 import javafx.beans.NamedArg;
 import javafx.beans.Observable;
 import javafx.beans.value.ObservableBooleanValue;

@@ -39,53 +42,57 @@
 import javafx.beans.value.ObservableStringValue;
 import javafx.beans.value.ObservableValue;
 import javafx.collections.FXCollections;
 import javafx.collections.ObservableList;
 
+import com.sun.javafx.binding.BooleanConstant;
 import com.sun.javafx.binding.DoubleConstant;
 import com.sun.javafx.binding.FloatConstant;
 import com.sun.javafx.binding.IntegerConstant;
 import com.sun.javafx.binding.Logging;
 import com.sun.javafx.binding.LongConstant;
+import com.sun.javafx.binding.ObjectConstant;
+import com.sun.javafx.binding.StringConstant;
 
 /**
  * Starting point for a binding that calculates a ternary expression.
  * <p>
  * A ternary expression has the basic form
  * {@code new When(cond).then(value1).otherwise(value2);}. The expression
- * {@code cond} needs to be a {@link javafx.beans.value.ObservableBooleanValue}.
+ * {@code cond} needs to be an {@link javafx.beans.value.ObservableBooleanValue}.
  * Based on the value of {@code cond}, the binding contains the value of
  * {@code value1} (if {@code cond.getValue() == true}) or {@code value2} (if
  * {@code cond.getValue() == false}). The values {@code value1} and
  * {@code value2} have to be of the same type. They can be constant values or
  * implementations of {@link javafx.beans.value.ObservableValue}.
  * @since JavaFX 2.0
  */
 public class When {
+
+    private static final String VALUE_MUST_BE_SPECIFIED = "Value must be specified";
+
     private final ObservableBooleanValue condition;
 
     /**
      * The constructor of {@code When}.
      *
      * @param condition
      *            the condition of the ternary expression
      */
     public When(final @NamedArg("condition") ObservableBooleanValue condition) {
-        if (condition == null) {
-            throw new NullPointerException("Condition must be specified.");
-        }
-        this.condition = condition;
+        this.condition = Objects.requireNonNull(condition, "Condition must be specified.");
     }
 
     private static class WhenListener implements InvalidationListener {
 
         private final ObservableBooleanValue condition;
         private final ObservableValue<?> thenValue;
         private final ObservableValue<?> otherwiseValue;
         private final WeakReference<Binding<?>> ref;
 
-        private WhenListener(Binding<?> binding, ObservableBooleanValue condition, ObservableValue<?> thenValue, ObservableValue<?> otherwiseValue) {
+        private WhenListener(Binding<?> binding, ObservableBooleanValue condition, ObservableValue<?> thenValue,
+                             ObservableValue<?> otherwiseValue) {
             this.ref = new WeakReference<Binding<?>>(binding);
             this.condition = condition;
             this.thenValue = thenValue;
             this.otherwiseValue = otherwiseValue;
         }

@@ -108,133 +115,72 @@
                 if (condition.equals(observable) || (binding.isValid() && (condition.get() == observable.equals(thenValue)))) {
                     binding.invalidate();
                 }
             }
         }
-
     }
 
-    private static NumberBinding createNumberCondition(
-            final ObservableBooleanValue condition,
-            final ObservableNumberValue thenValue,
-            final ObservableNumberValue otherwiseValue) {
-        if ((thenValue instanceof ObservableDoubleValue) || (otherwiseValue instanceof ObservableDoubleValue)) {
-            return new DoubleBinding() {
-                final InvalidationListener observer = new WhenListener(this, condition, thenValue, otherwiseValue);
-                {
-                    condition.addListener(observer);
-                    thenValue.addListener(observer);
-                    otherwiseValue.addListener(observer);
-                }
+    private abstract class ConditionHolder<V, B extends Binding<V>> {
 
-                @Override
-                public void dispose() {
-                    condition.removeListener(observer);
-                    thenValue.removeListener(observer);
-                    otherwiseValue.removeListener(observer);
-                }
+        protected B binding;
+        private ObservableValue<V> thenValue;
+        private ObservableValue<V> otherwiseValue;
+        private InvalidationListener observer;
+
+        protected void registerListeners(final ObservableValue<V> then, final ObservableValue<V> otherwise) {
+            thenValue = then;
+            otherwiseValue = otherwise;
+            observer = new WhenListener(binding, condition, thenValue, otherwiseValue);
+            condition.addListener(observer);
+            thenValue.addListener(observer);
+            otherwiseValue.addListener(observer);
+        }
 
-                @Override
-                protected double computeValue() {
-                    final boolean conditionValue = condition.get();
-                    Logging.getLogger().finest("Condition of ternary binding expression was evaluated: {0}", conditionValue);
-                    return conditionValue ? thenValue.doubleValue() : otherwiseValue.doubleValue();
-                }
+        // TODO: unnecessary - can access field directly
+        protected B getBinding() {
+            return binding;
+        }
 
-                @Override
-                public ObservableList<ObservableValue<?>> getDependencies() {
-                    return FXCollections.unmodifiableObservableList(
-                            FXCollections.<ObservableValue<?>> observableArrayList(condition, thenValue, otherwiseValue));
-                }
-            };
-        } else if ((thenValue instanceof ObservableFloatValue) || (otherwiseValue instanceof ObservableFloatValue)) {
-            return new FloatBinding() {
-                final InvalidationListener observer = new WhenListener(this, condition, thenValue, otherwiseValue);
-                {
-                    condition.addListener(observer);
-                    thenValue.addListener(observer);
-                    otherwiseValue.addListener(observer);
-                }
+        protected ObservableList<ObservableValue<?>> getDependencies() {
+            return FXCollections.unmodifiableObservableList(
+                    FXCollections.observableArrayList(condition, thenValue, otherwiseValue));
+        }
 
-                @Override
-                public void dispose() {
-                    condition.removeListener(observer);
-                    thenValue.removeListener(observer);
-                    otherwiseValue.removeListener(observer);
-                }
+        protected V computeValue() {
+            final boolean conditionValue = condition.get();
+            Logging.getLogger().finest("Condition of ternary binding expression was evaluated: {0}", conditionValue);
+            return conditionValue ? thenValue.getValue() : otherwiseValue.getValue();
+        }
 
-                @Override
-                protected float computeValue() {
-                    final boolean conditionValue = condition.get();
-                    Logging.getLogger().finest("Condition of ternary binding expression was evaluated: {0}", conditionValue);
-                    return conditionValue ? thenValue.floatValue() : otherwiseValue.floatValue();
-                }
+        protected void dispose() {
+            condition.removeListener(observer);
+            thenValue.removeListener(observer);
+            otherwiseValue.removeListener(observer);
+        }
+    }
 
-                @Override
-                public ObservableList<ObservableValue<?>> getDependencies() {
-                    return FXCollections.unmodifiableObservableList(
-                            FXCollections.<ObservableValue<?>> observableArrayList(condition, thenValue, otherwiseValue));
-                }
-            };
-        } else if ((thenValue instanceof ObservableLongValue) || (otherwiseValue instanceof ObservableLongValue)) {
-            return new LongBinding() {
-                final InvalidationListener observer = new WhenListener(this, condition, thenValue, otherwiseValue);
-                {
-                    condition.addListener(observer);
-                    thenValue.addListener(observer);
-                    otherwiseValue.addListener(observer);
-                }
+    private class DoubleConditionHolder extends ConditionHolder<Number, DoubleBinding> {
 
-                @Override
-                public void dispose() {
-                    condition.removeListener(observer);
-                    thenValue.removeListener(observer);
-                    otherwiseValue.removeListener(observer);
-                }
+        protected DoubleConditionHolder(ObservableNumberValue then, ObservableNumberValue otherwise) {
+            binding = new DoubleBinding() {
 
                 @Override
-                protected long computeValue() {
-                    final boolean conditionValue = condition.get();
-                    Logging.getLogger().finest("Condition of ternary binding expression was evaluated: {0}", conditionValue);
-                    return conditionValue ? thenValue.longValue() : otherwiseValue.longValue();
+                protected double computeValue() {
+                    return DoubleConditionHolder.super.computeValue().doubleValue();
                 }
 
                 @Override
-                public ObservableList<ObservableValue<?>> getDependencies() {
-                    return FXCollections.unmodifiableObservableList(
-                            FXCollections.<ObservableValue<?>> observableArrayList(condition, thenValue, otherwiseValue));
-                }
-            };
-        } else {
-            return new IntegerBinding() {
-                final InvalidationListener observer = new WhenListener(this, condition, thenValue, otherwiseValue);
-                {
-                    condition.addListener(observer);
-                    thenValue.addListener(observer);
-                    otherwiseValue.addListener(observer);
+                public ObservableList<?> getDependencies() {
+                    return DoubleConditionHolder.super.getDependencies();
                 }
 
                 @Override
                 public void dispose() {
-                    condition.removeListener(observer);
-                    thenValue.removeListener(observer);
-                    otherwiseValue.removeListener(observer);
-                }
-
-                @Override
-                protected int computeValue() {
-                    final boolean conditionValue = condition.get();
-                    Logging.getLogger().finest("Condition of ternary binding expression was evaluated: {0}", conditionValue);
-                    return conditionValue ? thenValue.intValue(): otherwiseValue.intValue();
-                }
-
-                @Override
-                public ObservableList<ObservableValue<?>> getDependencies() {
-                    return FXCollections.unmodifiableObservableList(
-                            FXCollections.<ObservableValue<?>> observableArrayList(condition, thenValue, otherwiseValue));
+                    DoubleConditionHolder.super.dispose();
                 }
             };
+            registerListeners(then, otherwise);
         }
     }
 
     /**
      * If-then-else expression returning a number.

@@ -247,27 +193,34 @@
         private NumberConditionBuilder(final ObservableNumberValue thenValue) {
             this.thenValue = thenValue;
         }
 
         /**
-         * Defines the {@link javafx.beans.value.ObservableNumberValue} which
+         * Defines the {@link javafx.beans.value.ObservableNumberValue} whose
          * value is returned by the ternary expression if the condition is
          * {@code false}.
          *
          * @param otherwiseValue
          *            the value
          * @return the complete {@link DoubleBinding}
          */
         public NumberBinding otherwise(ObservableNumberValue otherwiseValue) {
-            if (otherwiseValue == null) {
-                throw new NullPointerException("Value needs to be specified");
+            Objects.requireNonNull(otherwiseValue, VALUE_MUST_BE_SPECIFIED);
+            // Arranged by widening conventions
+            if ((thenValue instanceof ObservableDoubleValue) || (otherwiseValue instanceof ObservableDoubleValue)) {
+                return new DoubleConditionHolder(thenValue, otherwiseValue).getBinding();
+            } else if ((thenValue instanceof ObservableFloatValue) || (otherwiseValue instanceof ObservableFloatValue)) {
+                return new DoubleConditionHolder(thenValue, otherwiseValue).getBinding();
+            } else if ((thenValue instanceof ObservableLongValue) || (otherwiseValue instanceof ObservableLongValue)) {
+                return new DoubleConditionHolder(thenValue, otherwiseValue).getBinding();
+            } else {
+                return new DoubleConditionHolder(thenValue, otherwiseValue).getBinding();
             }
-            return When.createNumberCondition(condition, thenValue, otherwiseValue);
         }
 
         /**
-         * Defines a constant value of the ternary expression, that is returned
+         * Defines a constant value of the ternary expression that is returned
          * if the condition is {@code false}.
          *
          * @param otherwiseValue
          *            the value
          * @return the complete {@link DoubleBinding}

@@ -275,23 +228,23 @@
         public DoubleBinding otherwise(double otherwiseValue) {
             return (DoubleBinding) otherwise(DoubleConstant.valueOf(otherwiseValue));
         }
 
         /**
-         * Defines a constant value of the ternary expression, that is returned
+         * Defines a constant value of the ternary expression that is returned
          * if the condition is {@code false}.
          *
          * @param otherwiseValue
          *            the value
          * @return the complete {@link NumberBinding}
          */
         public NumberBinding otherwise(float otherwiseValue) {
-            return otherwise(FloatConstant.valueOf(otherwiseValue));
+            return otherwise(FloatConstant.valueOf(otherwiseValue));             // TODO: add note about runtime type of binding?
         }
 
         /**
-         * Defines a constant value of the ternary expression, that is returned
+         * Defines a constant value of the ternary expression that is returned
          * if the condition is {@code false}.
          *
          * @param otherwiseValue
          *            the value
          * @return the complete {@link NumberBinding}

@@ -299,11 +252,11 @@
         public NumberBinding otherwise(long otherwiseValue) {
             return otherwise(LongConstant.valueOf(otherwiseValue));
         }
 
         /**
-         * Defines a constant value of the ternary expression, that is returned
+         * Defines a constant value of the ternary expression that is returned
          * if the condition is {@code false}.
          *
          * @param otherwiseValue
          *            the value
          * @return the complete {@link NumberBinding}

@@ -320,203 +273,182 @@
      * @param thenValue
      *            the value
      * @return the intermediate result which still requires the otherwise-branch
      */
     public NumberConditionBuilder then(final ObservableNumberValue thenValue) {
-        if (thenValue == null) {
-            throw new NullPointerException("Value needs to be specified");
-        }
+        Objects.requireNonNull(thenValue, VALUE_MUST_BE_SPECIFIED);
         return new NumberConditionBuilder(thenValue);
     }
 
     /**
-     * Defines a constant value of the ternary expression, that is returned if
+     * Defines a constant value of the ternary expression that is returned if
      * the condition is {@code true}.
      *
      * @param thenValue
      *            the value
      * @return the intermediate result which still requires the otherwise-branch
      */
     public NumberConditionBuilder then(double thenValue) {
-        return new NumberConditionBuilder(DoubleConstant.valueOf(thenValue));
+        return then(DoubleConstant.valueOf(thenValue));
     }
 
     /**
-     * Defines a constant value of the ternary expression, that is returned if
+     * Defines a constant value of the ternary expression that is returned if
      * the condition is {@code true}.
      *
      * @param thenValue
      *            the value
      * @return the intermediate result which still requires the otherwise-branch
      */
     public NumberConditionBuilder then(float thenValue) {
-        return new NumberConditionBuilder(FloatConstant.valueOf(thenValue));
+        return then(FloatConstant.valueOf(thenValue));
     }
 
     /**
-     * Defines a constant value of the ternary expression, that is returned if
+     * Defines a constant value of the ternary expression that is returned if
      * the condition is {@code true}.
      *
      * @param thenValue
      *            the value
      * @return the intermediate result which still requires the otherwise-branch
      */
     public NumberConditionBuilder then(long thenValue) {
-        return new NumberConditionBuilder(LongConstant.valueOf(thenValue));
+        return then(LongConstant.valueOf(thenValue));
     }
 
     /**
-     * Defines a constant value of the ternary expression, that is returned if
+     * Defines a constant value of the ternary expression that is returned if
      * the condition is {@code true}.
      *
      * @param thenValue
      *            the value
      * @return the intermediate result which still requires the otherwise-branch
      */
     public NumberConditionBuilder then(int thenValue) {
-        return new NumberConditionBuilder(IntegerConstant.valueOf(thenValue));
+        return then(IntegerConstant.valueOf(thenValue));
     }
 
-    /**
-     * If-then-else expression returning Boolean.
-     */
-    private class BooleanCondition extends BooleanBinding {
-        private final ObservableBooleanValue trueResult;
-        private final boolean trueResultValue;
+    private class BooleanConditionHolder extends ConditionHolder<Boolean, BooleanBinding> {
+
+        private BooleanConditionHolder(ObservableValue<Boolean> then, ObservableValue<Boolean> otherwise) {
+            binding = new BooleanBinding() {
 
-        private final ObservableBooleanValue falseResult;
-        private final boolean falseResultValue;
+                @Override
+                protected boolean computeValue() {
+                    return BooleanConditionHolder.super.computeValue();
+                }
 
-        private final InvalidationListener observer;
+                @Override
+                public void dispose() {
+                    BooleanConditionHolder.super.dispose();
+                }
 
-        private BooleanCondition(final ObservableBooleanValue then, final ObservableBooleanValue otherwise) {
-            this.trueResult = then;
-            this.trueResultValue = false;
-            this.falseResult = otherwise;
-            this.falseResultValue = false;
-            this.observer = new WhenListener(this, condition, then, otherwise);
-            condition.addListener(observer);
-            then.addListener(observer);
-            otherwise.addListener(observer);
+                @Override
+                public ObservableList<ObservableValue<?>> getDependencies() {
+                    return BooleanConditionHolder.super.getDependencies();
+                }
+            };
+            registerListeners(then, otherwise);
         }
+    }
 
-        private BooleanCondition(final boolean then, final ObservableBooleanValue otherwise) {
-            this.trueResult = null;
-            this.trueResultValue = then;
-            this.falseResult = otherwise;
-            this.falseResultValue = false;
-            this.observer = new WhenListener(this, condition, null, otherwise);
-            condition.addListener(observer);
-            otherwise.addListener(observer);
+    private abstract class ConditionBuilder<V, B extends Binding<V>> {
+
+        private ObservableValue<V> thenValue;
+        protected BiFunction<ObservableValue<V>, ObservableValue<V>, ? extends ConditionHolder<V, B>> conditionHolderGenerator;
+        protected Function<V, ObservableValue<V>> primitiveWrapper;
+
+        protected ConditionBuilder(final ObservableValue<V> thenValue) {
+            this.thenValue = thenValue;
         }
 
-        private BooleanCondition(final ObservableBooleanValue then, final boolean otherwise) {
-            this.trueResult = then;
-            this.trueResultValue = false;
-            this.falseResult = null;
-            this.falseResultValue = otherwise;
-            this.observer = new WhenListener(this, condition, then, null);
-            condition.addListener(observer);
-            then.addListener(observer);
+        public B otherwise(final ObservableValue<V> otherwiseValue) {
+            Objects.requireNonNull(otherwiseValue, VALUE_MUST_BE_SPECIFIED);
+            return conditionHolderGenerator.apply(thenValue, otherwiseValue).getBinding();
         }
 
-        private BooleanCondition(final boolean then, final boolean otherwise) {
-            this.trueResult = null;
-            this.trueResultValue = then;
-            this.falseResult = null;
-            this.falseResultValue = otherwise;
-            this.observer = null;
-            super.bind(condition);
+        public B otherwise(final V otherwiseValue) {
+            return otherwise(primitiveWrapper.apply(otherwiseValue));
         }
+    }
 
-        @Override
-        protected boolean computeValue() {
-            final boolean conditionValue = condition.get();
-            Logging.getLogger().finest("Condition of ternary binding expression was evaluated: {0}", conditionValue);
-            return conditionValue ? (trueResult != null ? trueResult.get() : trueResultValue)
-                    : (falseResult != null ? falseResult.get() : falseResultValue);
+    /**
+     * An intermediate class needed while assembling the ternary expression. It
+     * should not be used in another context.
+     * @since JavaFX 2.0
+     */
+    public class BooleanConditionBuilder2 extends ConditionBuilder<Boolean, BooleanBinding> {
+
+        private BooleanConditionBuilder2(ObservableBooleanValue then) {
+            super(then);
+            conditionHolderGenerator = (thenValue, otherwiseValue) -> new BooleanConditionHolder(thenValue, otherwiseValue);
+            primitiveWrapper = otherwiseValue -> BooleanConstant.valueOf(otherwiseValue);
         }
 
-        @Override
-        public void dispose() {
-            if (observer == null) {
-                super.unbind(condition);
-            } else {
-                condition.removeListener(observer);
-                if (trueResult != null) {
-                    trueResult.removeListener(observer);
-                }
-                if (falseResult != null) {
-                    falseResult.removeListener(observer);
-                }
-            }
+        /**
+         * Defines the {@link javafx.beans.value.ObservableBooleanValue} whose
+         * value is returned by the ternary expression if the condition is
+         * {@code false}.
+         *
+         * @param otherwiseValue
+         *            the value
+         * @return the complete {@link BooleanBinding}
+         */
+        public BooleanBinding otherwise(final ObservableBooleanValue otherwiseValue) {
+            return super.otherwise(otherwiseValue);
         }
 
-        @Override
-        public ObservableList<ObservableValue<?>> getDependencies() {
-            assert condition != null;
-            final ObservableList<ObservableValue<?>> seq = FXCollections.<ObservableValue<?>> observableArrayList(condition);
-            if (trueResult != null) {
-                seq.add(trueResult);
-            }
-            if (falseResult != null) {
-                seq.add(falseResult);
-            }
-            return FXCollections.unmodifiableObservableList(seq);
+        /**
+         * Defines a constant value of the ternary expression that is returned
+         * if the condition is {@code false}.
+         *
+         * @param otherwiseValue
+         *            the value
+         * @return the complete {@link BooleanBinding}
+         */
+        public BooleanBinding otherwise(final boolean otherwiseValue) {
+            return super.otherwise(otherwiseValue);
         }
     }
 
     /**
      * An intermediate class needed while assembling the ternary expression. It
      * should not be used in another context.
      * @since JavaFX 2.0
      */
     public class BooleanConditionBuilder {
 
-        private ObservableBooleanValue trueResult;
-        private boolean trueResultValue;
+        private ObservableValue<Boolean> thenValue;
 
         private BooleanConditionBuilder(final ObservableBooleanValue thenValue) {
-            this.trueResult = thenValue;
-        }
-
-        private BooleanConditionBuilder(final boolean thenValue) {
-            this.trueResultValue = thenValue;
+            this.thenValue = thenValue;
         }
 
         /**
-         * Defines the {@link javafx.beans.value.ObservableBooleanValue} which
+         * Defines the {@link javafx.beans.value.ObservableBooleanValue} whose
          * value is returned by the ternary expression if the condition is
          * {@code false}.
          *
          * @param otherwiseValue
          *            the value
          * @return the complete {@link BooleanBinding}
          */
         public BooleanBinding otherwise(final ObservableBooleanValue otherwiseValue) {
-            if (otherwiseValue == null) {
-                throw new NullPointerException("Value needs to be specified");
-            }
-            if (trueResult != null)
-                return new BooleanCondition(trueResult, otherwiseValue);
-            else
-                return new BooleanCondition(trueResultValue, otherwiseValue);
+            Objects.requireNonNull(otherwiseValue, VALUE_MUST_BE_SPECIFIED);
+            return new BooleanConditionHolder(thenValue, otherwiseValue).getBinding();
         }
 
         /**
-         * Defines a constant value of the ternary expression, that is returned
+         * Defines a constant value of the ternary expression that is returned
          * if the condition is {@code false}.
          *
          * @param otherwiseValue
          *            the value
          * @return the complete {@link BooleanBinding}
          */
         public BooleanBinding otherwise(final boolean otherwiseValue) {
-            if (trueResult != null)
-                return new BooleanCondition(trueResult, otherwiseValue);
-            else
-                return new BooleanCondition(trueResultValue, otherwiseValue);
+            return otherwise(BooleanConstant.valueOf(otherwiseValue));
         }
     }
 
     /**
      * Defines the {@link javafx.beans.value.ObservableBooleanValue} which value

@@ -525,166 +457,87 @@
      * @param thenValue
      *            the value
      * @return the intermediate result which still requires the otherwise-branch
      */
     public BooleanConditionBuilder then(final ObservableBooleanValue thenValue) {
-        if (thenValue == null) {
-            throw new NullPointerException("Value needs to be specified");
-        }
+        Objects.requireNonNull(thenValue, VALUE_MUST_BE_SPECIFIED);
         return new BooleanConditionBuilder(thenValue);
     }
 
     /**
-     * Defines a constant value of the ternary expression, that is returned if
+     * Defines a constant value of the ternary expression that is returned if
      * the condition is {@code true}.
      *
      * @param thenValue
      *            the value
      * @return the intermediate result which still requires the otherwise-branch
      */
     public BooleanConditionBuilder then(final boolean thenValue) {
-        return new BooleanConditionBuilder(thenValue);
+        return then(BooleanConstant.valueOf(thenValue));
     }
 
-    /**
-     * If-then-else expression returning String.
-     */
-    private class StringCondition extends StringBinding {
-
-        private final ObservableStringValue trueResult;
-        private final String trueResultValue;
-
-        private final ObservableStringValue falseResult;
-        private final String falseResultValue;
-
-        private final InvalidationListener observer;
+    private class StringConditionHolder extends ConditionHolder<String, StringBinding> {
 
-        private StringCondition(final ObservableStringValue then, final ObservableStringValue otherwise) {
-            this.trueResult = then;
-            this.trueResultValue = "";
-            this.falseResult = otherwise;
-            this.falseResultValue = "";
-            this.observer = new WhenListener(this, condition, then, otherwise);
-            condition.addListener(observer);
-            then.addListener(observer);
-            otherwise.addListener(observer);
-        }
-
-        private StringCondition(final String then, final ObservableStringValue otherwise) {
-            this.trueResult = null;
-            this.trueResultValue = then;
-            this.falseResult = otherwise;
-            this.falseResultValue = "";
-            this.observer = new WhenListener(this, condition, null, otherwise);
-            condition.addListener(observer);
-            otherwise.addListener(observer);
-        }
+        protected StringConditionHolder(ObservableStringValue then, ObservableStringValue otherwise) {
+            binding = new StringBinding() {
 
-        private StringCondition(final ObservableStringValue then, final String otherwise) {
-            this.trueResult = then;
-            this.trueResultValue = "";
-            this.falseResult = null;
-            this.falseResultValue = otherwise;
-            this.observer = new WhenListener(this, condition, then, null);
-            condition.addListener(observer);
-            then.addListener(observer);
-        }
-
-        private StringCondition(final String then, final String otherwise) {
-            this.trueResult = null;
-            this.trueResultValue = then;
-            this.falseResult = null;
-            this.falseResultValue = otherwise;
-            this.observer = null;
-            super.bind(condition);
-        }
-
-        @Override
-        protected String computeValue() {
-            final boolean conditionValue = condition.get();
-            Logging.getLogger().finest("Condition of ternary binding expression was evaluated: {0}", conditionValue);
-            return conditionValue ? (trueResult != null ? trueResult.get() : trueResultValue)
-                    : (falseResult != null ? falseResult.get() : falseResultValue);
-        }
-
-        @Override
-        public void dispose() {
-            if (observer == null) {
-                super.unbind(condition);
-            } else {
-                condition.removeListener(observer);
-                if (trueResult != null) {
-                    trueResult.removeListener(observer);
-                }
-                if (falseResult != null) {
-                    falseResult.removeListener(observer);
+                @Override
+                protected String computeValue() {
+                    return StringConditionHolder.super.computeValue();
                 }
-            }
-        }
 
+                @Override
+                public void dispose() {
+                    StringConditionHolder.super.dispose();
+                }
 
-        @Override
-        public ObservableList<ObservableValue<?>> getDependencies() {
-            assert condition != null;
-            final ObservableList<ObservableValue<?>> seq = FXCollections.<ObservableValue<?>> observableArrayList(condition);
-            if (trueResult != null) {
-                seq.add(trueResult);
-            }
-            if (falseResult != null) {
-                seq.add(falseResult);
-            }
-            return FXCollections.unmodifiableObservableList(seq);
+                @Override
+                public ObservableList<ObservableValue<?>> getDependencies() {
+                    return StringConditionHolder.super.getDependencies();
+                }
+            };
+            registerListeners(then, otherwise);
         }
     }
 
     /**
      * An intermediate class needed while assembling the ternary expression. It
      * should not be used in another context.
      * @since JavaFX 2.0
      */
     public class StringConditionBuilder {
 
-        private ObservableStringValue trueResult;
-        private String trueResultValue;
+        private ObservableStringValue thenValue;
 
         private StringConditionBuilder(final ObservableStringValue thenValue) {
-            this.trueResult = thenValue;
-        }
-
-        private StringConditionBuilder(final String thenValue) {
-            this.trueResultValue = thenValue;
+            this.thenValue = thenValue;
         }
 
         /**
-         * Defines the {@link javafx.beans.value.ObservableStringValue} which
+         * Defines the {@link javafx.beans.value.ObservableStringValue} whose
          * value is returned by the ternary expression if the condition is
          * {@code false}.
          *
          * @param otherwiseValue
          *            the value
          * @return the complete {@link StringBinding}
          */
         public StringBinding otherwise(final ObservableStringValue otherwiseValue) {
-            if (trueResult != null)
-                return new StringCondition(trueResult, otherwiseValue);
-            else
-                return new StringCondition(trueResultValue, otherwiseValue);
+            Objects.requireNonNull(otherwiseValue, VALUE_MUST_BE_SPECIFIED);
+            return new StringConditionHolder(thenValue, otherwiseValue).getBinding();
         }
 
         /**
-         * Defines a constant value of the ternary expression, that is returned
+         * Defines a constant value of the ternary expression that is returned
          * if the condition is {@code false}.
          *
          * @param otherwiseValue
          *            the value
          * @return the complete {@link StringBinding}
          */
         public StringBinding otherwise(final String otherwiseValue) {
-            if (trueResult != null)
-                return new StringCondition(trueResult, otherwiseValue);
-            else
-                return new StringCondition(trueResultValue, otherwiseValue);
+            return otherwise(StringConstant.valueOf(otherwiseValue));
         }
     }
 
     /**
      * Defines the {@link javafx.beans.value.ObservableStringValue} which value

@@ -693,135 +546,61 @@
      * @param thenValue
      *            the value
      * @return the intermediate result which still requires the otherwise-branch
      */
     public StringConditionBuilder then(final ObservableStringValue thenValue) {
-        if (thenValue == null) {
-            throw new NullPointerException("Value needs to be specified");
-        }
+        Objects.requireNonNull(thenValue, VALUE_MUST_BE_SPECIFIED);
         return new StringConditionBuilder(thenValue);
     }
 
     /**
-     * Defines a constant value of the ternary expression, that is returned if
+     * Defines a constant value of the ternary expression that is returned if
      * the condition is {@code true}.
      *
      * @param thenValue
      *            the value
      * @return the intermediate result which still requires the otherwise-branch
      */
     public StringConditionBuilder then(final String thenValue) {
-        return new StringConditionBuilder(thenValue);
+        return then(StringConstant.valueOf(thenValue));
     }
 
-    /**
-     * If-then-else expression returning general objects.
-     */
-    private class ObjectCondition<T> extends ObjectBinding<T> {
-
-        private final ObservableObjectValue<T> trueResult;
-        private final T trueResultValue;
-
-        private final ObservableObjectValue<T> falseResult;
-        private final T falseResultValue;
-
-        private final InvalidationListener observer;
-
-        private ObjectCondition(final ObservableObjectValue<T> then, final ObservableObjectValue<T> otherwise) {
-            this.trueResult = then;
-            this.trueResultValue = null;
-            this.falseResult = otherwise;
-            this.falseResultValue = null;
-            this.observer = new WhenListener(this, condition, then, otherwise);
-            condition.addListener(observer);
-            then.addListener(observer);
-            otherwise.addListener(observer);
-        }
-
-        private ObjectCondition(final T then, final ObservableObjectValue<T> otherwise) {
-            this.trueResult = null;
-            this.trueResultValue = then;
-            this.falseResult = otherwise;
-            this.falseResultValue = null;
-            this.observer = new WhenListener(this, condition, null, otherwise);
-            condition.addListener(observer);
-            otherwise.addListener(observer);
-        }
-
-        private ObjectCondition(final ObservableObjectValue<T> then, final T otherwise) {
-            this.trueResult = then;
-            this.trueResultValue = null;
-            this.falseResult = null;
-            this.falseResultValue = otherwise;
-            this.observer = new WhenListener(this, condition, then, null);
-            condition.addListener(observer);
-            then.addListener(observer);
-        }
-
-        private ObjectCondition(final T then, final T otherwise) {
-            this.trueResult = null;
-            this.trueResultValue = then;
-            this.falseResult = null;
-            this.falseResultValue = otherwise;
-            this.observer = null;
-            super.bind(condition);
-        }
+    private class ObjectConditionHolder<T> extends ConditionHolder<T, ObjectBinding<T>> {
 
-        @Override
-        protected T computeValue() {
-            final boolean conditionValue = condition.get();
-            Logging.getLogger().finest("Condition of ternary binding expression was evaluated: {0}", conditionValue);
-            return conditionValue ? (trueResult != null ? trueResult.get() : trueResultValue)
-                    : (falseResult != null ? falseResult.get() : falseResultValue);
-        }
+        protected ObjectConditionHolder(ObservableObjectValue<T> then, ObservableObjectValue<T> otherwise) {
+            binding = new ObjectBinding<T>() {
 
-        @Override
-        public void dispose() {
-            if (observer == null) {
-                super.unbind(condition);
-            } else {
-                condition.removeListener(observer);
-                if (trueResult != null) {
-                    trueResult.removeListener(observer);
-                }
-                if (falseResult != null) {
-                    falseResult.removeListener(observer);
+                @Override
+                protected T computeValue() {
+                    return ObjectConditionHolder.super.computeValue();
                 }
-            }
-        }
 
+                @Override
+                public void dispose() {
+                    ObjectConditionHolder.super.dispose();
+                }
 
-        @Override
-        public ObservableList<ObservableValue<?>> getDependencies() {
-            assert condition != null;
-            final ObservableList<ObservableValue<?>> seq = FXCollections.<ObservableValue<?>> observableArrayList(condition);
-            if (trueResult != null) {
-                seq.add(trueResult);
-            }
-            if (falseResult != null) {
-                seq.add(falseResult);
-            }
-            return FXCollections.unmodifiableObservableList(seq);
+                @Override
+                public ObservableList<ObservableValue<?>> getDependencies() {
+                    return ObjectConditionHolder.super.getDependencies();
+                }
+            };
+            registerListeners(then, otherwise);
         }
     }
 
     /**
      * An intermediate class needed while assembling the ternary expression. It
      * should not be used in another context.
      * @since JavaFX 2.0
      */
     public class ObjectConditionBuilder<T> {
 
-        private ObservableObjectValue<T> trueResult;
-        private T trueResultValue;
+        private ObservableObjectValue<T> thenValue;
 
         private ObjectConditionBuilder(final ObservableObjectValue<T> thenValue) {
-            this.trueResult = thenValue;
-        }
-
-        private ObjectConditionBuilder(final T thenValue) {
-            this.trueResultValue = thenValue;
+            this.thenValue = thenValue;
         }
 
         /**
          * Defines the {@link javafx.beans.value.ObservableObjectValue} which
          * value is returned by the ternary expression if the condition is

@@ -830,32 +609,24 @@
          * @param otherwiseValue
          *            the value
          * @return the complete {@link ObjectBinding}
          */
         public ObjectBinding<T> otherwise(final ObservableObjectValue<T> otherwiseValue) {
-            if (otherwiseValue == null) {
-                throw new NullPointerException("Value needs to be specified");
-            }
-            if (trueResult != null)
-                return new ObjectCondition<T>(trueResult, otherwiseValue);
-            else
-                return new ObjectCondition<T>(trueResultValue, otherwiseValue);
+            Objects.requireNonNull(otherwiseValue, VALUE_MUST_BE_SPECIFIED);
+            return new ObjectConditionHolder<>(thenValue, otherwiseValue).getBinding();
         }
 
         /**
-         * Defines a constant value of the ternary expression, that is returned
+         * Defines a constant value of the ternary expression that is returned
          * if the condition is {@code false}.
          *
          * @param otherwiseValue
          *            the value
          * @return the complete {@link ObjectBinding}
          */
         public ObjectBinding<T> otherwise(final T otherwiseValue) {
-            if (trueResult != null)
-                return new ObjectCondition<T>(trueResult, otherwiseValue);
-            else
-                return new ObjectCondition<T>(trueResultValue, otherwiseValue);
+            return otherwise(ObjectConstant.valueOf(otherwiseValue));
         }
     }
 
     /**
      * Defines the {@link javafx.beans.value.ObservableObjectValue} which value

@@ -865,25 +636,23 @@
      * @param thenValue
      *            the value
      * @return the intermediate result which still requires the otherwise-branch
      */
     public <T> ObjectConditionBuilder<T> then(final ObservableObjectValue<T> thenValue) {
-        if (thenValue == null) {
-            throw new NullPointerException("Value needs to be specified");
-        }
+        Objects.requireNonNull(thenValue, VALUE_MUST_BE_SPECIFIED);
         return new ObjectConditionBuilder<T>(thenValue);
     }
 
     /**
-     * Defines a constant value of the ternary expression, that is returned if
+     * Defines a constant value of the ternary expression that is returned if
      * the condition is {@code true}.
      *
      * @param <T> the type of the intermediate result
      * @param thenValue
      *            the value
      * @return the intermediate result which still requires the otherwise-branch
      */
     public <T> ObjectConditionBuilder<T> then(final T thenValue) {
-        return new ObjectConditionBuilder<T>(thenValue);
+        return then(ObjectConstant.valueOf(thenValue));
     }
 
 }
< prev index next >