1 /*
   2  * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javafx.beans.binding;
  27 
  28 import com.sun.javafx.binding.StringFormatter;
  29 import javafx.beans.value.ObservableObjectValue;
  30 import javafx.collections.FXCollections;
  31 import javafx.collections.ObservableList;
  32 
  33 import java.util.Locale;
  34 
  35 /**
  36  * {@code ObjectExpression} is an
  37  * {@link javafx.beans.value.ObservableObjectValue} plus additional convenience
  38  * methods to generate bindings in a fluent style.
  39  * <p>
  40  * A concrete sub-class of {@code ObjectExpression} has to implement the method
  41  * {@link javafx.beans.value.ObservableObjectValue#get()}, which provides the
  42  * actual value of this expression.
  43  * @since JavaFX 2.0
  44  */
  45 public abstract class ObjectExpression<T> implements ObservableObjectValue<T> {
  46 
  47     @Override
  48     public T getValue() {
  49         return get();
  50     }
  51 
  52     /**
  53      * Returns an {@code ObjectExpression} that wraps an
  54      * {@link javafx.beans.value.ObservableObjectValue}. If the
  55      * {@code ObservableObjectValue} is already an {@code ObjectExpression}, it
  56      * will be returned. Otherwise a new
  57      * {@link javafx.beans.binding.ObjectBinding} is created that is bound to
  58      * the {@code ObservableObjectValue}.
  59      *
  60      * @param <T> the type of the wrapped {@code Object}
  61      * @param value
  62      *            The source {@code ObservableObjectValue}
  63      * @return A {@code ObjectExpression} that wraps the
  64      *         {@code ObservableObjectValue} if necessary
  65      * @throws NullPointerException
  66      *             if {@code value} is {@code null}
  67      */
  68     public static <T> ObjectExpression<T> objectExpression(
  69             final ObservableObjectValue<T> value) {
  70         if (value == null) {
  71             throw new NullPointerException("Value must be specified.");
  72         }
  73         return value instanceof ObjectExpression ? (ObjectExpression<T>) value
  74                 : new ObjectBinding<T>() {
  75                     {
  76                         super.bind(value);
  77                     }
  78 
  79                     @Override
  80                     public void dispose() {
  81                         super.unbind(value);
  82                     }
  83 
  84                     @Override
  85                     protected T computeValue() {
  86                         return value.get();
  87                     }
  88 
  89                     @Override
  90                     public ObservableList<ObservableObjectValue<T>> getDependencies() {
  91                         return FXCollections.singletonObservableList(value);
  92                     }
  93                 };
  94     }
  95 
  96     /**
  97      * Creates a new {@code BooleanExpression} that holds {@code true} if this and
  98      * another {@link javafx.beans.value.ObservableObjectValue} are equal.
  99      *
 100      * @param other
 101      *            the other {@code ObservableObjectValue}
 102      * @return the new {@code BooleanExpression}
 103      * @throws NullPointerException
 104      *             if {@code other} is {@code null}
 105      */
 106     public BooleanBinding isEqualTo(final ObservableObjectValue<?> other) {
 107         return Bindings.equal(this, other);
 108     }
 109 
 110     /**
 111      * Creates a new {@code BooleanExpression} that holds {@code true} if this
 112      * {@code ObjectExpression} is equal to a constant value.
 113      *
 114      * @param other
 115      *            the constant value
 116      * @return the new {@code BooleanExpression}
 117      */
 118     public BooleanBinding isEqualTo(final Object other) {
 119         return Bindings.equal(this, other);
 120     }
 121 
 122     /**
 123      * Creates a new {@code BooleanExpression} that holds {@code true} if this and
 124      * another {@link javafx.beans.value.ObservableObjectValue} are not equal.
 125      *
 126      * @param other
 127      *            the other {@code ObservableObjectValue}
 128      * @return the new {@code BooleanExpression}
 129      * @throws NullPointerException
 130      *             if {@code other} is {@code null}
 131      */
 132     public BooleanBinding isNotEqualTo(final ObservableObjectValue<?> other) {
 133         return Bindings.notEqual(this, other);
 134     }
 135 
 136     /**
 137      * Creates a new {@code BooleanExpression} that holds {@code true} if this
 138      * {@code ObjectExpression} is not equal to a constant value.
 139      *
 140      * @param other
 141      *            the constant value
 142      * @return the new {@code BooleanExpression}
 143      */
 144     public BooleanBinding isNotEqualTo(final Object other) {
 145         return Bindings.notEqual(this, other);
 146     }
 147 
 148     /**
 149      * Creates a new {@link BooleanBinding} that holds {@code true} if this
 150      * {@code ObjectExpression} is {@code null}.
 151      *
 152      * @return the new {@code BooleanBinding}
 153      */
 154     public BooleanBinding isNull() {
 155         return Bindings.isNull(this);
 156     }
 157 
 158     /**
 159      * Creates a new {@link BooleanBinding} that holds {@code true} if this
 160      * {@code ObjectExpression} is not {@code null}.
 161      *
 162      * @return the new {@code BooleanBinding}
 163      */
 164     public BooleanBinding isNotNull() {
 165         return Bindings.isNotNull(this);
 166     }
 167 
 168     /**
 169      * Creates a {@link javafx.beans.binding.StringBinding} that holds the value
 170      * of this {@code ObjectExpression} turned into a {@code String}. If the
 171      * value of this {@code ObjectExpression} changes, the value of the
 172      * {@code StringBinding} will be updated automatically.
 173      *
 174      * @return the new {@code StringBinding}
 175      * @since JavaFX 8.0
 176      */
 177     public StringBinding asString() {
 178         return (StringBinding) StringFormatter.convert(this);
 179     }
 180 
 181     /**
 182      * Creates a {@link javafx.beans.binding.StringBinding} that holds the value
 183      * of the {@code ObjectExpression} turned into a {@code String}. If the
 184      * value of this {@code ObjectExpression} changes, the value of the
 185      * {@code StringBinding} will be updated automatically.
 186      * <p>
 187      * The result is formatted according to the formatting {@code String}. See
 188      * {@code java.util.Formatter} for formatting rules.
 189      *
 190      * @param format
 191      *            the formatting {@code String}
 192      * @return the new {@code StringBinding}
 193      * @since JavaFX 8.0
 194      */
 195     public StringBinding asString(String format) {
 196         return (StringBinding) Bindings.format(format, this);
 197     }
 198 
 199     /**
 200      * Creates a {@link javafx.beans.binding.StringBinding} that holds the value
 201      * of the {@code NumberExpression} turned into a {@code String}. If the
 202      * value of this {@code NumberExpression} changes, the value of the
 203      * {@code StringBinding} will be updated automatically.
 204      * <p>
 205      * The result is formatted according to the formatting {@code String} and
 206      * the passed in {@code Locale}. See {@code java.util.Formatter} for
 207      * formatting rules. See {@code java.util.Locale} for details on
 208      * {@code Locale}.
 209      *
 210      * @param locale the Locale to be used
 211      * @param format
 212      *            the formatting {@code String}
 213      * @return the new {@code StringBinding}
 214      * @since JavaFX 8.0
 215      */
 216     public StringBinding asString(Locale locale, String format) {
 217         return (StringBinding) Bindings.format(locale, format, this);
 218     }
 219 }