⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 binding.java

📁 java属性邦定的(JSR-295)的一个实现
💻 JAVA
📖 第 1 页 / 共 5 页
字号:

    /**
     * Unsets the value of the {@code sourceUnreadableValue} property by clearing
     * the value and setting the value of the {@code sourceUnreadableValueSet}
     * property to {@code false}.
     * <p>
     * If the property was previously set, fires a property change notification
     * with property name {@code "sourceUnreadableValueSet"}, and a property
     * change notification with property name {@code "sourceUnreadableValue"}.
     * The event for the latter notification will have a new value of {@code null}.
     * <p>
     * See the documentation for {@link #setSourceUnreadableValue} for more
     * information on the {@code sourceUnreadableValue} property.
     * <p>
     * This method may not be called on a bound binding.
     *
     * @throws IllegalStateException if the {@code Binding} is bound
     * @see #isSourceUnreadableValueSet
     * @see #getSourceUnreadableValue
     */
    public final void unsetSourceUnreadableValue() {
        throwIfBound();

        if (isSourceUnreadableValueSet()) {
            TV old = this.sourceUnreadableValue;
            
            this.sourceUnreadableValue = null;
            this.sourceUnreadableValueSet = false;

            firePropertyChange("sourceUnreadableValueSet", true, false);
            firePropertyChange("sourceUnreadableValue", old, null);
        }

    }

    /**
     * Returns the value of the {@code sourceUnreadableValueSet} property,
     * which indicates whether or not the {@code sourceUnreadableValue} property
     * is set on the {@code Binding}.
     * <p>
     * See the documentation for {@link #setSourceUnreadableValue} for more
     * information on the {@code sourceUnreadableValue} property.
     *
     * @return whether or not the {@code sourceUnreadableValue} property
     *         is set on the {@code Binding}
     * @see #unsetSourceUnreadableValue
     * @see #getSourceUnreadableValue
     */
    public final boolean isSourceUnreadableValueSet() {
        return sourceUnreadableValueSet;
    }

    /**
     * If set, returns the value to be returned by {@link #getSourceValueForTarget}
     * when the source property is unreadable for the source object. Throws
     * {@code UnsupportedOperationException} if the property is not set,
     * as indicated by {@link #isSourceUnreadableValueSet}.
     * <p>
     * See the documentation for {@link #setSourceUnreadableValue} for more
     * information on this property.
     *
     * @return the value that replaces an unreadable source value, which may
     *         be {@code null}
     * @see #unsetSourceUnreadableValue
     * @throws UnsupportedOperationException if the property is not set,
     *         as indicated by {@code isSourceUnreadableValueSet}
     */
    public final TV getSourceUnreadableValue() {
        if (!isSourceUnreadableValueSet()) {
            throw new UnsupportedOperationException("not set");
        }

        return sourceUnreadableValue;
    }

    /**
     * Adds a {@code BindingListener} to be notified of changes to this {@code Binding}.
     * Does nothing if the listener is {@code null}. If a listener is added more than once,
     * notifications are sent to that listener once for every time that it has
     * been added. The ordering of listener notification is unspecified.
     *
     * @param listener the listener to add
     */
    public final void addBindingListener(BindingListener listener) {
        if (listener == null) {
            return;
        }

        if (listeners == null) {
            listeners = new ArrayList<BindingListener>();
        }

        listeners.add(listener);
    }

    /**
     * Removes a {@code BindingListener} from the {@code Binding}. Does
     * nothing if the listener is {@code null} or is not one of those registered.
     * If the listener being removed was registered more than once, only one
     * occurrence of the listener is removed from the list of listeners.
     * The ordering of listener notification is unspecified.
     *
     * @param listener the listener to remove
     * @see #addBindingListener
     */
    public final void removeBindingListener(BindingListener listener) {
        if (listener == null) {
            return;
        }

        if (listeners != null) {
            listeners.remove(listener);
        }
    }

    /**
     * Returns the list of {@code BindingListeners} registered on this
     * {@code Binding}. Order is undefined. Returns an empty array if there are
     * no listeners.
     *
     * @return the list of {@code BindingListeners} registered on this {@code Binding}
     * @see #addBindingListener
     */
    public final BindingListener[] getBindingListeners() {
        if (listeners == null) {
            return new BindingListener[0];
        }

        BindingListener[] ret = new BindingListener[listeners.size()];
        ret = listeners.toArray(ret);
        return ret;
    }

    /**
     * Fetches the value of the source property for the source object and
     * returns a {@code ValueResult} representing that value in terms that
     * can be set on the target property for the target object.
     * <p>
     * First, if the target property is not writeable for the target object,
     * a {@code ValueResult} is returned representing a failure
     * with failure type {@code SyncFailureType.TARGET_UNWRITEABLE}.
     * Then, if the source property is unreadable for the source object,
     * the value of {@link #isSourceUnreadableValueSet} is checked. If {@code true}
     * then a {@code ValueResult} is returned containing the value of the
     * {@code Binding's} {@link #getSourceUnreadableValue}. Otherwise a
     * {@code ValueResult} is returned representing a failure with failure
     * type {@code SyncFailureType.SOURCE_UNREADABLE}.
     * <p>
     * Next, the value of the source property is fetched for the source
     * object. If the value is {@code null}, a {@code ValueResult} is
     * returned containing the value of the {@code Binding's}
     * {@link #getSourceNullValue}. If the value is {@code non-null},
     * the {@code Binding's Converter}, if any, is run to convert
     * the value from source type to the target property's
     * {@code getWriteType}, by calling its {@code convertForward}
     * method with the value. If no {@code Converter} is registered,
     * a set of default converters is checked to see if one of them
     * can convert the value to the target type. Finally, the value
     * (converted or not) is cast to the target write type.
     * <p>
     * This final value is returned in a {@code ValueResult}.
     * <p>
     * Any {@code RuntimeException} or {@code ClassCastException} thrown by a
     * converter or the final cast is propogated up to the caller of this method.
     *
     * @return a {@code ValueResult} as described above
     * @throws RuntimeException if thrown by any of the converters
     * @throws ClassCastException if thrown by a converter or the final cast
     */
    public final ValueResult<TV> getSourceValueForTarget() {
        if (!targetProperty.isWriteable(targetObject)) {
            return new ValueResult<TV>(SyncFailure.TARGET_UNWRITEABLE);
        }

        if (!sourceProperty.isReadable(sourceObject)) {
            if (sourceUnreadableValueSet) {
                return new ValueResult<TV>(sourceUnreadableValue);
            } else {
                return new ValueResult<TV>(SyncFailure.SOURCE_UNREADABLE);
            }
        }

        TV value;

        SV rawValue = sourceProperty.getValue(sourceObject);

        if (rawValue == null) {
            value = sourceNullValue;
        } else {
            // may throw ClassCastException or other RuntimeException here;
            // allow it to be propogated back to the user of Binding
            value = convertForward(rawValue);
        }

        return new ValueResult<TV>(value);
    }

    /**
     * Fetches the value of the target property for the target object and
     * returns a {@code ValueResult} representing that value in terms that
     * can be set on the source property for the source object.
     * <p>
     * First, if the source property is not writeable for the source object,
     * a {@code ValueResult} is returned representing a failure
     * with failure type {@code SyncFailureType.SOURCE_UNWRITEABLE}.
     * Then, if the target property is not readable for the target object,
     * a {@code ValueResult} is returned representing a failure
     * with failure type {@code SyncFailureType.TARGET_UNREADABLE}.
     * <p>
     * Next, the value of the target property is fetched for the target
     * object. If the value is {@code null}, a {@code ValueResult} is
     * returned containing the value of the {@code Binding's}
     * {@link #getTargetNullValue}. If the value is {@code non-null},
     * the {@code Binding's Converter}, if any, is run to convert
     * the value from target type to the source property's
     * {@code getWriteType}, by calling its {@code convertReverse}
     * method with the value. If no {@code Converter} is registered,
     * a set of default converters is checked to see if one of them
     * can convert the value to the source type. Finally, the value
     * (converted or not) is cast to the source write type.
     * <p>
     * If a converter throws a {@code RuntimeException} other than
     * {@code ClassCastException}, this method returns a
     * {@code ValueResult} containing the failure, with failure type
     * {@code SyncFailureType.CONVERSION_FAILURE}.
     * <p>
     * As the last step, the {@code Binding's Validator}, if any, is called
     * upon to validate the final value. If the {@code Validator}
     * returns {@code non-null} from its {@code validate} method,
     * a {@code ValueResult} is returned containing the validation
     * result, with failure type {@code SyncFailureType.VALIDATION_FAILURE}.
     * Otherwise a {@code ValueResult} is returned containing the
     * final validated value.
     * <p>
     * Any {@code ClassCastException} thrown by a converter or the final
     * cast is propogated up to the caller of this method.
     *
     * @return a {@code ValueResult} as described above
     * @throws ClassCastException if thrown by a converter or the final cast
     */
    public final ValueResult<SV> getTargetValueForSource() {
        if (!sourceProperty.isWriteable(sourceObject)) {
            return new ValueResult<SV>(SyncFailure.SOURCE_UNWRITEABLE);
        }

        if (!targetProperty.isReadable(targetObject)) {
            return new ValueResult<SV>(SyncFailure.TARGET_UNREADABLE);
        }

        SV value = null;
        TV rawValue = targetProperty.getValue(targetObject);

        if (rawValue == null) {
            value = targetNullValue;
        } else {
            try {
                value = convertReverse(rawValue);
            } catch (ClassCastException cce) {
                throw cce;
            } catch (RuntimeException rte) {
                return new ValueResult<SV>(SyncFailure.conversionFailure(rte));
            }

            if (validator != null) {
                Validator.Result vr = validator.validate(value);
                if (vr != null) {
                    return new ValueResult<SV>(SyncFailure.validationFailure(vr));
                }
            }
        }

        return new ValueResult<SV>((SV)value);
    }

    /**
     * Binds this binding. Calls {@link #bindImpl} to allow subclasses
     * to initiate binding, adds a {@code PropertyStateListener} to the source
     * property for the source object and the target property for the target
     * object to start tracking changes, notifies all registered
     * {@code BindingListeners} that the binding has become bound, and
     * fires a property change notification to indicate a change to the
     * {@code "bound"} property.
     *
     * @throws UnsupportedOperationException if the {@code Binding} is managed
     * @throws IllegalStateException if the {@code Binding} is already bound
     * @see #isBound()
     * @see #isManaged()
     * @see #unbind
     */
    public final void bind() {
        throwIfManaged();
        bindUnmanaged();
    }

    /**
     * A protected version of {@link #bind} that allows managed
     * subclasses to bind without throwing an exception
     * for being managed.
     *
     * @throws IllegalStateException if the {@code Binding} is bound
     * @see #isManaged()
     * @see #isBound()
     */
    protected final void bindUnmanaged() {
        throwIfBound();

        bindImpl();

        psl = new PSL();
        sourceProperty.addPropertyStateListener(sourceObject, psl);
        targetProperty.addPropertyStateListener(targetObject, psl);

        isBound = true;

        if (listeners != null) {
            for (BindingListener listener : listeners) {
                listener.bindingBecameBound(this);
            }
        }
        
        firePropertyChange("bound", false, true);
    }

    /**
     * Called by {@link #bind} to allow subclasses to initiate binding.
     * Subclasses typically need not install {@code PropertyStateListeners}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -