diff options
author | Brian Vosburgh | 2016-07-01 22:05:47 +0000 |
---|---|---|
committer | Brian Vosburgh | 2017-05-18 22:37:40 +0000 |
commit | e1845e115f0e6541a1c2d56ddd6a23ea8d53bd0f (patch) | |
tree | ed694d03c7ea6da3972d5960206ecab5aa87e65f /common | |
parent | b325d65b4b7f6b319db20b3af5b58626cc9c6799 (diff) | |
download | webtools.dali-e1845e115f0e6541a1c2d56ddd6a23ea8d53bd0f.tar.gz webtools.dali-e1845e115f0e6541a1c2d56ddd6a23ea8d53bd0f.tar.xz webtools.dali-e1845e115f0e6541a1c2d56ddd6a23ea8d53bd0f.zip |
refactor double PVMs
Diffstat (limited to 'common')
13 files changed, 546 insertions, 607 deletions
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/AbstractDoublePropertyValueModel.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/AbstractDoublePropertyValueModel.java deleted file mode 100644 index 1e60ffe17c..0000000000 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/AbstractDoublePropertyValueModel.java +++ /dev/null @@ -1,189 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2012, 2016 Oracle. All rights reserved. - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0, which accompanies this distribution - * and is available at http://www.eclipse.org/legal/epl-v10.html. - * - * Contributors: - * Oracle - initial API and implementation - ******************************************************************************/ -package org.eclipse.jpt.common.utility.internal.model.value; - -import org.eclipse.jpt.common.utility.model.event.PropertyChangeEvent; -import org.eclipse.jpt.common.utility.model.listener.PropertyChangeAdapter; -import org.eclipse.jpt.common.utility.model.listener.PropertyChangeListener; -import org.eclipse.jpt.common.utility.model.value.PropertyValueModel; - -/** - * This [<em>outer</em>] property value model wraps another [<em>middle</em>] - * property value model that wraps yet another [<em>inner</em>] property value model - * and treats the <em>inner</em> model's value as the <em>outer</em>'s value. - * Any change events fired by the <em>inner</em> model are simply forwarded by - * the <em>outer</em> model as its own. - * Similarly, changing the <em>middle</em> model's <em>inner</em> model - * can also trigger a change event - * (see {@link #wrappedValueChanged(PropertyValueModel)}). - * <p> - * <ul> - * <li>Double (<em>outer</em>) property value model - a client can listen to - * this model and receive the same change notification whether the - * <em>middle</em> model's value changes or the <em>inner</em> model's - * value changes; - * much like an {@link PropertyAspectAdapter aspect adapter} whose subject - * model is <em>not</em> another property value model - * <ul> - * <li>Wrapped (<em>middle</em>) property value model - this model is built - * and maintained by the server that also builds the <em>inner</em> model - * (i.e. the server will monitor some other model that determines when - * the <em>inner</em> model is changed) - * <ul> - * <li>Original (<em>inner</em>) property value model - this model is - * the "original" model that contains the value of interest - * </ul> - * </ul> - * </ul> - * <p> - * This wrapper is useful when a change in the <em>middle</em> model's value is - * signaled by a non-value event and a third-party would like to change it. - * - * @param <V> the type of the both the <em>inner</em> and <em>outer</em> - * models' values - * @param <VMV> the type of the <em>middle</em> model's value (i.e. the type - * of the <em>inner</em> model itself) - */ -public abstract class AbstractDoublePropertyValueModel<V, VMV extends PropertyValueModel<? extends V>> - extends PropertyValueModelWrapper<VMV> - implements PropertyValueModel<V> -{ - /** - * The optionally present <em>inner</em> model; held by the <em>middle</em> - * model {@link #valueModel}. This may be <code>null</code>. - */ - protected volatile VMV valueModelValue; - - /** - * A listener that allows us to sync with changes to the - * {@link #valueModelValue <em>inner</em> model}. - */ - protected final PropertyChangeListener valueModelValueListener; - - /** - * The <em>inner</em> model's value. - */ - private volatile V value; - - - /** - * Construct a double property value model for the specified - * <em>middle</em> property value model. - */ - protected AbstractDoublePropertyValueModel(PropertyValueModel<? extends VMV> valueModel) { - super(valueModel); - this.valueModelValueListener = this.buildValueModelValueListener(); - } - - protected PropertyChangeListener buildValueModelValueListener() { - return new ValueModelValueListener(); - } - - /* CU private */ class ValueModelValueListener - extends PropertyChangeAdapter - { - @Override - public void propertyChanged(PropertyChangeEvent event) { - AbstractDoublePropertyValueModel.this.wrappedValueModelValueChanged(event); - } - } - - - // ********** PropertyValueModel implementation ********** - - public V getValue() { - return this.value; - } - - @Override - public void toString(StringBuilder sb) { - sb.append(this.value); - } - - - // ********** middle model ********** - - /** - * The <em>middle</em> model has changed. - * Move our <em>inner</em> model listener and - * notify listeners the <em>outer</em> model's value has changed. - */ - @Override - protected void wrappedValueChanged(VMV newValueModelValue) { - V oldValue = null; - V newValue = null; - synchronized (this) { - if (this.hasListeners()) { // it's possible listeners were removed before event gets here... - oldValue = this.value; - this.disengageValueModelValue(); - this.valueModelValue = newValueModelValue; - if (newValueModelValue != null) { - newValueModelValue.addPropertyChangeListener(VALUE, this.valueModelValueListener); - newValue = newValueModelValue.getValue(); - this.value = newValue; - } - } - } - this.firePropertyChanged(VALUE, oldValue, newValue); - } - - - // ********** inner model ********** - - /** - * The <em>inner</em> model has changed. - * Cache the new value and - * notify listeners the <em>outer</em> model's value has changed. - */ - @SuppressWarnings("unchecked") - protected void wrappedValueModelValueChanged(PropertyChangeEvent event) { - V oldValue = null; - V newValue = (V) event.getNewValue(); - synchronized (this) { - oldValue = this.value; - this.value = newValue; - } - this.firePropertyChanged(VALUE, oldValue, newValue); - } - - /** - * Begin listening to the <em>inner</em> model. - */ - @Override - protected void engageModel() { - super.engageModel(); - this.engageValueModelValue(); - } - - protected void engageValueModelValue() { - this.valueModelValue = this.valueModel.getValue(); - if (this.valueModelValue != null) { - this.valueModelValue.addPropertyChangeListener(VALUE, this.valueModelValueListener); - this.value = this.valueModelValue.getValue(); - } - } - - /** - * Stop listening to the <em>inner</em> model. - */ - @Override - protected void disengageModel() { - this.disengageValueModelValue(); - super.disengageModel(); - } - - protected void disengageValueModelValue() { - if (this.valueModelValue != null) { - this.value = null; - this.valueModelValue.removePropertyChangeListener(VALUE, this.valueModelValueListener); - this.valueModelValue = null; - } - } -} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/BaseDoublePropertyValueModelAdapter.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/BaseDoublePropertyValueModelAdapter.java new file mode 100644 index 0000000000..ea814dfa46 --- /dev/null +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/BaseDoublePropertyValueModelAdapter.java @@ -0,0 +1,185 @@ +/******************************************************************************* + * Copyright (c) 2012, 2016 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.common.utility.internal.model.value; + +import org.eclipse.jpt.common.utility.internal.ObjectTools; +import org.eclipse.jpt.common.utility.model.event.PropertyChangeEvent; +import org.eclipse.jpt.common.utility.model.listener.PropertyChangeAdapter; +import org.eclipse.jpt.common.utility.model.listener.PropertyChangeListener; +import org.eclipse.jpt.common.utility.model.value.PropertyValueModel; + +/** + * This adapter adapts an (<em>outer</em>) property value model whose + * value is yet another (<em>inner</em>) property value model + * and treats the <em>inner</em> model's value as this adapter's models's value. + * As a result, this adapter listens for changes to either model + * (<em>inner</em> or <em>outer</em>). + * <p> + * A typical usage:<br>A (simple) model <code>A</code> is wrapped by + * a transformation model <code>B</code> that transforms model <code>A</code>'s + * value to yet another model <code>C</code>. This adapter is + * then constructed with model <code>B</code>.<ul> + * <li>If model <code>A</code>'s value changes + * (e.g. as the result of an Eclipse-generated event), model <code>B</code> + * will recalculate its value, a new model <code>C</code>, and this adapter's value will + * be recalculated etc.</li> + * <li>If model <code>C</code>'s value changes + * (e.g. its value is deleted from the Eclipse workspace), this adapter's value will + * be recalculated etc.</li> + * </ul> + * This is an adapter that can be used by a {@link BasePluggablePropertyValueModel}. + * + * @param <V> the type of both the adapter's and the <em>inner</em> model's values + * @param <IM> the type of the <em>inner</em> model (and the <em>outer</em> model's value) + * @param <OM> the type of the <em>outer</em> model + * @param <A> the type of the adapter itself + * @param <F> the type of the adapter factory + * + * @see BasePluggablePropertyValueModel + */ +public abstract class BaseDoublePropertyValueModelAdapter<V, IM extends PropertyValueModel<? extends V>, OM extends PropertyValueModel<? extends IM>, A extends BasePluggablePropertyValueModel.Adapter<V>, F extends BaseDoublePropertyValueModelAdapter.Factory<V, IM, OM, A>> + implements BasePluggablePropertyValueModel.Adapter<V> +{ + /** The <em>outer</em> model; whose value is cached as {@link #innerModel}. */ + protected final OM outerModel; + + /** Listens to {@link #outerModel}. */ + protected final PropertyChangeListener outerValueListener; + + /** The <em>inner</em> model; which is the value of {@link #outerModel}. Can be <code>null</code>. */ + protected volatile IM innerModel; + + /** Listens to {@link #innerModel}, if present. */ + protected final PropertyChangeListener innerValueListener; + + /** The derived value. */ + private volatile V value; + + /** The <em>real</em> adapter. */ + private final BasePluggablePropertyValueModel.Adapter.Listener<V> listener; + + + public BaseDoublePropertyValueModelAdapter(OM outerModel, BasePluggablePropertyValueModel.Adapter.Listener<V> listener) { + super(); + if (outerModel == null) { + throw new NullPointerException(); + } + this.outerModel = outerModel; + this.outerValueListener = new OuterValueListener(); + + this.innerValueListener = new InnerValueListener(); + + if (listener == null) { + throw new NullPointerException(); + } + this.listener = listener; + } + + /* CU private */ class OuterValueListener + extends PropertyChangeAdapter + { + @Override + public void propertyChanged(PropertyChangeEvent event) { + @SuppressWarnings("unchecked") + IM newInnerModel = (IM) event.getNewValue(); + BaseDoublePropertyValueModelAdapter.this.outerValueChanged(newInnerModel); + } + } + + /* CU private */ class InnerValueListener + extends PropertyChangeAdapter + { + @Override + public void propertyChanged(PropertyChangeEvent event) { + @SuppressWarnings("unchecked") + V newValue = (V) event.getNewValue(); + BaseDoublePropertyValueModelAdapter.this.innerValueChanged(newValue); + } + } + + + // ********** BasePluggablePropertyValueModel.Adapter ********** + + public V getValue() { + return this.value; + } + + public void engageModel() { + this.outerModel.addPropertyChangeListener(PropertyValueModel.VALUE, this.outerValueListener); + this.innerModel = this.outerModel.getValue(); + this.engageInnerModel(); + } + + private void engageInnerModel() { + if (this.innerModel != null) { + this.innerModel.addPropertyChangeListener(PropertyValueModel.VALUE, this.innerValueListener); + this.value = this.innerModel.getValue(); + } + } + + public void disengageModel() { + this.disengageInnerModel(); + this.outerModel.removePropertyChangeListener(PropertyValueModel.VALUE, this.outerValueListener); + } + + private void disengageInnerModel() { + if (this.innerModel != null) { + this.value = null; + this.innerModel.removePropertyChangeListener(PropertyValueModel.VALUE, this.innerValueListener); + this.innerModel = null; + } + } + + + // ********** change events ********** + + /** + * Move our <em>inner</em> value listener to the new inner model. + */ + protected void outerValueChanged(IM newInnerModel) { + this.disengageInnerModel(); + this.innerModel = newInnerModel; + this.engageInnerModel(); + this.listener.valueChanged(this.value); + } + + protected void innerValueChanged(V newValue) { + this.listener.valueChanged(this.value = newValue); + } + + @Override + public String toString() { + return ObjectTools.toString(this, this.value); + } + + + // ********** Factory ********** + + public abstract static class Factory<V, IM extends PropertyValueModel<? extends V>, OM extends PropertyValueModel<? extends IM>, A extends BasePluggablePropertyValueModel.Adapter<V>> + implements BasePluggablePropertyValueModel.Adapter.Factory<V, A> + { + /* CU private */ final OM outerModel; + + public Factory(OM outerModel) { + super(); + if (outerModel == null) { + throw new NullPointerException(); + } + this.outerModel = outerModel; + } + + public abstract A buildAdapter(BasePluggablePropertyValueModel.Adapter.Listener<V> listener); + + @Override + public String toString() { + return ObjectTools.toString(this); + } + } +} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/BasePropertyPluggablePropertyValueModelAdapter.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/BasePropertyPluggablePropertyValueModelAdapter.java index eeb658b65c..32a36fb358 100644 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/BasePropertyPluggablePropertyValueModelAdapter.java +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/BasePropertyPluggablePropertyValueModelAdapter.java @@ -112,7 +112,7 @@ public abstract class BasePropertyPluggablePropertyValueModelAdapter<V1, V2, M e } - // ********** BasePluggablePropertyValueModel.Adapter.Factory ********** + // ********** Factory ********** public abstract static class Factory<V1, V2, M extends PropertyValueModel<? extends V1>, A extends BasePluggablePropertyValueModel.Adapter<V2>> implements BasePluggablePropertyValueModel.Adapter.Factory<V2, A> diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/DoubleModifiablePropertyValueModel.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/DoubleModifiablePropertyValueModel.java deleted file mode 100644 index 8b1e39be37..0000000000 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/DoubleModifiablePropertyValueModel.java +++ /dev/null @@ -1,47 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2012, 2016 Oracle. All rights reserved. - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0, which accompanies this distribution - * and is available at http://www.eclipse.org/legal/epl-v10.html. - * - * Contributors: - * Oracle - initial API and implementation - ******************************************************************************/ -package org.eclipse.jpt.common.utility.internal.model.value; - -import org.eclipse.jpt.common.utility.model.value.ModifiablePropertyValueModel; -import org.eclipse.jpt.common.utility.model.value.PropertyValueModel; - -/** - * Add support for changing the double property value model's value. - * This also constrains the value's type, since it is read <em>and</em> written. - * <p> - * <strong>NB:</strong> If the <em>outer</em> model has no listeners, - * {@link #setValue(Object) changes} will <em>not</em> be forwarded to the - * <em>inner</em> model. - * - * @param <V> the type of the both the <em>inner</em> and <em>outer</em> - * models' values - */ -public final class DoubleModifiablePropertyValueModel<V> - extends AbstractDoublePropertyValueModel<V, ModifiablePropertyValueModel<V>> - implements ModifiablePropertyValueModel<V> -{ - /** - * Construct a double property value model for the specified - * <em>middle</em> property value model. - */ - public DoubleModifiablePropertyValueModel(PropertyValueModel<? extends ModifiablePropertyValueModel<V>> valueModel) { - super(valueModel); - } - - /** - * Forward the specified value to the <em>inner</em> model. - */ - public void setValue(V value) { - if (this.valueModelValue == null) { - throw new IllegalStateException(); - } - this.valueModelValue.setValue(value); - } -} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/DoubleModifiablePropertyValueModelAdapter.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/DoubleModifiablePropertyValueModelAdapter.java new file mode 100644 index 0000000000..46bf044407 --- /dev/null +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/DoubleModifiablePropertyValueModelAdapter.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright (c) 2012, 2016 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.common.utility.internal.model.value; + +import org.eclipse.jpt.common.utility.model.value.ModifiablePropertyValueModel; +import org.eclipse.jpt.common.utility.model.value.PropertyValueModel; + +/** + * Add support for changing the model's value. + * This also constrains the value's type, since it is read <em>and</em> written. + * <p> + * <strong>NB:</strong> If the model has no listeners, + * {@link #setValue(Object) changes} will <em>not</em> be forwarded to the + * <em>inner</em> model. + * + * @param <V> the type of both the adapter's and the <em>inner</em> model's values + * @param <IM> the type of the <em>inner</em> model (and the <em>outer</em> model's value) + * @param <OM> the type of the <em>outer</em> model + */ +public final class DoubleModifiablePropertyValueModelAdapter<V, IM extends ModifiablePropertyValueModel<V>, OM extends PropertyValueModel<IM>> + extends BaseDoublePropertyValueModelAdapter<V, IM, OM, PluggableModifiablePropertyValueModel.Adapter<V>, DoubleModifiablePropertyValueModelAdapter.Factory<V, IM, OM>> + implements PluggableModifiablePropertyValueModel.Adapter<V> +{ + + public DoubleModifiablePropertyValueModelAdapter(OM outerModel, BasePluggablePropertyValueModel.Adapter.Listener<V> listener) { + super(outerModel, listener); + } + + /** + * Forward the specified value to the <em>inner</em> model. + * Client's should be aware of a <code>null</code> <em>inner</em> model + * (typically the <em>inner</em> will never be <code>null</code>). + */ + public void setValue(V value) { + if (this.innerModel == null) { + throw new IllegalStateException(); + } + this.innerModel.setValue(value); + } + + + // ********** Factory ********** + + public static class Factory<V, IM extends ModifiablePropertyValueModel<V>, OM extends PropertyValueModel<IM>> + extends BaseDoublePropertyValueModelAdapter.Factory<V,IM, OM, PluggableModifiablePropertyValueModel.Adapter<V>> + implements PluggableModifiablePropertyValueModel.Adapter.Factory<V> + { + public Factory(OM outerModel) { + super(outerModel); + } + + @Override + public PluggableModifiablePropertyValueModel.Adapter<V> buildAdapter(BasePluggablePropertyValueModel.Adapter.Listener<V> listener) { + return new DoubleModifiablePropertyValueModelAdapter<>(this.outerModel, listener); + } + } +} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/DoublePropertyValueModel.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/DoublePropertyValueModel.java deleted file mode 100644 index 522906e88d..0000000000 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/DoublePropertyValueModel.java +++ /dev/null @@ -1,32 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2012, 2013 Oracle. All rights reserved. - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0, which accompanies this distribution - * and is available at http://www.eclipse.org/legal/epl-v10.html. - * - * Contributors: - * Oracle - initial API and implementation - ******************************************************************************/ -package org.eclipse.jpt.common.utility.internal.model.value; - -import org.eclipse.jpt.common.utility.model.value.PropertyValueModel; - -/** - * This [<em>outer</em>] property value model wraps another [<em>middle</em>] - * property value model that wraps yet another [<em>inner</em>] property value model - * and treats the <em>inner</em> model's value as the <em>outer</em>'s value. - * - * @param <V> the type of the both the <em>inner</em> and <em>outer</em> - * models' values - */ -public final class DoublePropertyValueModel<V> - extends AbstractDoublePropertyValueModel<V, PropertyValueModel<? extends V>> -{ - /** - * Construct a double property value model for the specified - * <em>middle</em> property value model. - */ - public DoublePropertyValueModel(PropertyValueModel<? extends PropertyValueModel<? extends V>> valueModel) { - super(valueModel); - } -} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/DoublePropertyValueModelAdapter.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/DoublePropertyValueModelAdapter.java new file mode 100644 index 0000000000..b32e1daf8e --- /dev/null +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/DoublePropertyValueModelAdapter.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2012, 2016 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.common.utility.internal.model.value; + +import org.eclipse.jpt.common.utility.model.value.PropertyValueModel; + +/** + * This adapter adapts an (<em>outer</em>) property value model whose + * value is yet another (<em>inner</em>) property value model + * and treats the <em>inner</em> model's value as this adapter's models's value. + * As a result, this adapter listens for changes to either model + * (<em>inner</em> or <em>outer</em>). + * <p> + * This is an adapter that can be used by a {@link BasePluggablePropertyValueModel}. + * + * @param <V> the type of both the adapter's and the <em>inner</em> model's values + * @param <IM> the type of the <em>inner</em> model (and the <em>outer</em> model's value) + * @param <OM> the type of the <em>outer</em> model + * + * @see BasePluggablePropertyValueModel + */ +public final class DoublePropertyValueModelAdapter<V, IM extends PropertyValueModel<? extends V>, OM extends PropertyValueModel<IM>> + extends BaseDoublePropertyValueModelAdapter<V, IM, OM, PluggablePropertyValueModel.Adapter<V>, DoublePropertyValueModelAdapter.Factory<V, IM, OM>> + implements PluggablePropertyValueModel.Adapter<V> +{ + + public DoublePropertyValueModelAdapter(OM outerModel, BasePluggablePropertyValueModel.Adapter.Listener<V> listener) { + super(outerModel, listener); + } + + + // ********** Factory ********** + + public static class Factory<V, IM extends PropertyValueModel<? extends V>, OM extends PropertyValueModel<IM>> + extends BaseDoublePropertyValueModelAdapter.Factory<V, IM, OM, PluggablePropertyValueModel.Adapter<V>> + implements PluggablePropertyValueModel.Adapter.Factory<V> + { + public Factory(OM outerModel) { + super(outerModel); + } + + @Override + public PluggablePropertyValueModel.Adapter<V> buildAdapter(BasePluggablePropertyValueModel.Adapter.Listener<V> listener) { + return new DoublePropertyValueModelAdapter<>(this.outerModel, listener); + } + } +} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/PluggableModifiablePropertyValueModelAdapter.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/PluggableModifiablePropertyValueModelAdapter.java index 105f8234c6..98436a995a 100644 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/PluggableModifiablePropertyValueModelAdapter.java +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/PluggableModifiablePropertyValueModelAdapter.java @@ -29,10 +29,10 @@ public class PluggableModifiablePropertyValueModelAdapter<V> private final BasePluggablePropertyValueModel.Adapter<V> adapter; /** Write the adapted model with this. */ - private final Closure<V> closure; + private final Closure<? super V> closure; - public PluggableModifiablePropertyValueModelAdapter(BasePluggablePropertyValueModel.Adapter<V> adapter, Closure<V> closure) { + public PluggableModifiablePropertyValueModelAdapter(BasePluggablePropertyValueModel.Adapter<V> adapter, Closure<? super V> closure) { super(); if (adapter == null) { throw new NullPointerException(); @@ -67,9 +67,9 @@ public class PluggableModifiablePropertyValueModelAdapter<V> implements PluggableModifiablePropertyValueModel.Adapter.Factory<V> { /* CU private */ final BasePluggablePropertyValueModel.Adapter.Factory<V, ? extends BasePluggablePropertyValueModel.Adapter<V>> factory; - /* CU private */ final Closure<V> closure; + /* CU private */ final Closure<? super V> closure; - public Factory(BasePluggablePropertyValueModel.Adapter.Factory<V, ? extends BasePluggablePropertyValueModel.Adapter<V>> factory, Closure<V> closure) { + public Factory(BasePluggablePropertyValueModel.Adapter.Factory<V, ? extends BasePluggablePropertyValueModel.Adapter<V>> factory, Closure<? super V> closure) { super(); if (factory == null) { throw new NullPointerException(); diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/PropertyPluggableModifiablePropertyValueModelAdapter.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/PropertyPluggableModifiablePropertyValueModelAdapter.java index 6e2073a942..a0ac51af62 100644 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/PropertyPluggableModifiablePropertyValueModelAdapter.java +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/PropertyPluggableModifiablePropertyValueModelAdapter.java @@ -27,7 +27,7 @@ import org.eclipse.jpt.common.utility.transformer.Transformer; * * @see PluggableModifiablePropertyValueModel */ -public class PropertyPluggableModifiablePropertyValueModelAdapter<V1, V2> +public final class PropertyPluggableModifiablePropertyValueModelAdapter<V1, V2> extends BasePropertyPluggablePropertyValueModelAdapter<V1, V2, ModifiablePropertyValueModel<V1>, PluggableModifiablePropertyValueModel.Adapter<V2>, PropertyPluggableModifiablePropertyValueModelAdapter.Factory<V1, V2>> implements PluggableModifiablePropertyValueModel.Adapter<V2> { @@ -43,7 +43,7 @@ public class PropertyPluggableModifiablePropertyValueModelAdapter<V1, V2> } - // ********** PluggableModifiablePropertyValueModel.Adapter.Factory ********** + // ********** Factory ********** public static class Factory<V1, V2> extends BasePropertyPluggablePropertyValueModelAdapter.Factory<V1, V2, ModifiablePropertyValueModel<V1>, PluggableModifiablePropertyValueModel.Adapter<V2>> diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/PropertyPluggablePropertyValueModelAdapter.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/PropertyPluggablePropertyValueModelAdapter.java index 6030de521b..adbb3d04f1 100644 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/PropertyPluggablePropertyValueModelAdapter.java +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/PropertyPluggablePropertyValueModelAdapter.java @@ -27,7 +27,7 @@ import org.eclipse.jpt.common.utility.transformer.Transformer; * * @see PluggablePropertyValueModel */ -public class PropertyPluggablePropertyValueModelAdapter<V1, V2> +public final class PropertyPluggablePropertyValueModelAdapter<V1, V2> extends BasePropertyPluggablePropertyValueModelAdapter<V1, V2, PropertyValueModel<? extends V1>, PluggablePropertyValueModel.Adapter<V2>, PropertyPluggablePropertyValueModelAdapter.Factory<V1, V2>> implements PluggablePropertyValueModel.Adapter<V2> { @@ -37,8 +37,7 @@ public class PropertyPluggablePropertyValueModelAdapter<V1, V2> } - - // ********** PluggablePropertyValueModel.Adapter.Factory ********** + // ********** Factory ********** public static class Factory<V1, V2> extends BasePropertyPluggablePropertyValueModelAdapter.Factory<V1, V2, PropertyValueModel<? extends V1>, PluggablePropertyValueModel.Adapter<V2>> diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/PropertyValueModelTools.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/PropertyValueModelTools.java index 245b864615..877af5f51a 100644 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/PropertyValueModelTools.java +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/PropertyValueModelTools.java @@ -172,6 +172,16 @@ public final class PropertyValueModelTools { } /** + * Construct a modifiable property value model that wraps the specified + * property value model and transforms its value with the specified + * transformer. The specified closure is invoked when the model's value is set. + * @see PluggablePropertyValueModel + */ + public static <V1, V2> ModifiablePropertyValueModel<V2> transform(PropertyValueModel<? extends V1> propertyModel, Transformer<? super V1, ? extends V2> transformer, Closure<? super V2> setValueClosure) { + return pluggableModifiablePropertyValueModel(pluggablePropertyValueModelAdapterFactory(propertyModel, transformer), setValueClosure); + } + + /** * Construct a pluggable property value model adapter factory for the specified * property value model and transformer. * @see PluggablePropertyValueModel @@ -203,21 +213,33 @@ public final class PropertyValueModelTools { // ********** double PVMs ********** /** - * Construct a double property value model for the specified - * <em>middle</em> property value model. - * @see AbstractDoublePropertyValueModel + * Construct a double property value model for the specified <em>outer</em> property value model. + */ + public static <V> PropertyValueModel<V> doubleWrap(PropertyValueModel<? extends PropertyValueModel<? extends V>> outerModel) { + return propertyValueModel(doublePropertyValueModelAdapterFactory(outerModel)); + } + + /** + * Construct a double property value model adapter factory for the specified <em>outer</em> property value model. + */ + public static <V> PluggablePropertyValueModel.Adapter.Factory<V> doublePropertyValueModelAdapterFactory(PropertyValueModel<? extends PropertyValueModel<? extends V>> outerModel) { + return new DoublePropertyValueModelAdapter.Factory<>(outerModel); + } + + /** + * Construct a modifiable double property value model + * for the specified <em>outer</em> property value model. */ - public static <V> PropertyValueModel<V> doubleWrap(PropertyValueModel<? extends PropertyValueModel<? extends V>> propertyModel) { - return new DoublePropertyValueModel<>(propertyModel); + public static <V> ModifiablePropertyValueModel<V> doubleWrapModifiable(PropertyValueModel<? extends ModifiablePropertyValueModel<V>> outerModel) { + return modifiablePropertyValueModel(doubleModifiablePropertyValueModelAdapterFactory(outerModel)); } /** - * Construct a modifiable double property value model for the specified - * <em>middle</em> property value model. - * @see AbstractDoublePropertyValueModel + * Construct a modifiable double property value model adapter factory + * for the specified <em>outer</em> property value model. */ - public static <V> ModifiablePropertyValueModel<V> doubleWrapModifiable(PropertyValueModel<? extends ModifiablePropertyValueModel<V>> propertyModel) { - return new DoubleModifiablePropertyValueModel<>(propertyModel); + public static <V> PluggableModifiablePropertyValueModel.Adapter.Factory<V> doubleModifiablePropertyValueModelAdapterFactory(PropertyValueModel<? extends ModifiablePropertyValueModel<V>> outerModel) { + return new DoubleModifiablePropertyValueModelAdapter.Factory<>(outerModel); } @@ -244,11 +266,45 @@ public final class PropertyValueModelTools { * property value model adapter adapter factory and closure. * The specified closure is invoked when the model's value is set. */ - public static <V> ModifiablePropertyValueModel<V> pluggableModifiablePropertyValueModel(BasePluggablePropertyValueModel.Adapter.Factory<V, ? extends BasePluggablePropertyValueModel.Adapter<V>> factory, Closure<V> setValueClosure) { + public static <V> ModifiablePropertyValueModel<V> pluggableModifiablePropertyValueModel(BasePluggablePropertyValueModel.Adapter.Factory<V, ? extends BasePluggablePropertyValueModel.Adapter<V>> factory, Closure<? super V> setValueClosure) { return new PluggableModifiablePropertyValueModel<>(new PluggableModifiablePropertyValueModelAdapter.Factory<>(factory, setValueClosure)); } + // ********** value transformers ********** + + /** + * Return a transformer that converts a property value model to its value + * but first checks whether the property value model passed to it is <code>null</code>. + * If the property value model is <code>null</code>, the transformer returns + * <code>null</code>. + * @see PropertyValueModel#VALUE_TRANSFORMER + */ + public static <V, PVM extends PropertyValueModel<? extends V>> Transformer<PVM, V> nullCheckValueTransformer() { + return nullCheckValueTransformer(null); + } + + /** + * Return a transformer that converts a property value model to its value + * but first checks whether the property value model passed to it is <code>null</code>. + * If the property value model is <code>null</code>, the transformer returns + * the specified null value. + * @see PropertyValueModel#VALUE_TRANSFORMER + */ + public static <V, PVM extends PropertyValueModel<? extends V>> Transformer<PVM, V> nullCheckValueTransformer(V nullValue) { + return TransformerTools.nullCheck(valueTransformer(), nullValue); + } + + /** + * Return a transformer that converts a property value model to its value. + * @see PropertyValueModel#VALUE_TRANSFORMER + */ + @SuppressWarnings("unchecked") + public static <V, PVM extends PropertyValueModel<? extends V>> Transformer<PVM, V> valueTransformer() { + return PropertyValueModel.VALUE_TRANSFORMER; + } + + // ********** suppressed constructor ********** /** diff --git a/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/model/value/DoubleModifiablePropertyValueModelTests.java b/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/model/value/DoubleModifiablePropertyValueModelTests.java index 73a410eec3..a61fc26776 100644 --- a/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/model/value/DoubleModifiablePropertyValueModelTests.java +++ b/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/model/value/DoubleModifiablePropertyValueModelTests.java @@ -9,8 +9,9 @@ ******************************************************************************/ package org.eclipse.jpt.common.utility.tests.internal.model.value; -import org.eclipse.jpt.common.utility.internal.model.value.SimplePropertyValueModel; +import org.eclipse.jpt.common.utility.internal.closure.ClosureAdapter; import org.eclipse.jpt.common.utility.internal.model.value.PropertyValueModelTools; +import org.eclipse.jpt.common.utility.internal.model.value.SimplePropertyValueModel; import org.eclipse.jpt.common.utility.model.value.ModifiablePropertyValueModel; import org.eclipse.jpt.common.utility.model.value.PropertyValueModel; @@ -23,102 +24,67 @@ public class DoubleModifiablePropertyValueModelTests } @Override - protected PropertyValueModel<String> buildDoubleModel(ModifiablePropertyValueModel<ModifiablePropertyValueModel<String>> modelModel) { + protected ModifiablePropertyValueModel<String> buildTestModel(PropertyValueModel<SimplePropertyValueModel<String>> modelModel) { return PropertyValueModelTools.doubleWrapModifiable(modelModel); } - protected ModifiablePropertyValueModel<String> getDoubleModel() { - return (ModifiablePropertyValueModel<String>) this.doubleModel; - } - - public void testSetValue() { - assertEquals("foo", this.stringModel.getValue()); - assertEquals(this.stringModel, this.stringModelModel.getValue()); - assertNull(this.doubleModel.getValue()); - this.doubleModel.addPropertyChangeListener(PropertyValueModel.VALUE, this.doubleModelListener); - assertEquals("foo", this.doubleModel.getValue()); - - this.getDoubleModel().setValue("bar"); - assertEquals("bar", this.stringModel.getValue()); - assertEquals("bar", this.doubleModel.getValue()); - - this.stringModelModel.setValue(null); - assertNull(this.doubleModel.getValue()); - boolean exCaught = false; - try { - this.getDoubleModel().setValue("TTT"); // unsupported? - } catch (IllegalStateException ex) { - exCaught = true; + public class SetClosure + extends ClosureAdapter<String> + { + @Override + public void execute(String argument) { + String key = DoubleModifiablePropertyValueModelTests.this.keyModel.getValue(); + DoubleModifiablePropertyValueModelTests.this.getValueModel(key).setValue(argument); } - assertTrue(exCaught); - assertEquals("bar", this.stringModel.getValue()); - assertNull(this.doubleModel.getValue()); } - public void testPropertyChange3() { - this.stringModel.addChangeListener(this.stringModelListener); - this.stringModelModel.addChangeListener(this.stringModelModelListener); - this.doubleModel.addChangeListener(this.doubleModelListener); - this.verifyPropertyChanges2(); + protected ModifiablePropertyValueModel<String> getTestModel() { + return (ModifiablePropertyValueModel<String>) this.testModel; } - public void testPropertyChange4() { - this.stringModel.addPropertyChangeListener(PropertyValueModel.VALUE, this.stringModelListener); - this.stringModelModel.addPropertyChangeListener(PropertyValueModel.VALUE, this.stringModelModelListener); - this.doubleModel.addPropertyChangeListener(PropertyValueModel.VALUE, this.doubleModelListener); - this.verifyPropertyChanges2(); + public void testSetValue() { + assertNull(this.keyModel.getValue()); + assertNull(this.valueModelModel.getValue()); + assertNull(this.testModel.getValue()); + + this.testModel.addPropertyChangeListener(PropertyValueModel.VALUE, this.testModelListener); + + assertNull(this.keyModel.getValue()); + assertNull(this.valueModelModel.getValue()); + assertNull(this.testModel.getValue()); + + this.keyModel.setValue("foo"); + assertEquals("foo", this.keyModel.getValue()); + assertEquals(this.valueModels.get("foo"), this.valueModelModel.getValue()); + assertEquals("foofoo", this.testModel.getValue()); + + this.getTestModel().setValue("bar"); + assertEquals("foo", this.keyModel.getValue()); + assertEquals(this.valueModels.get("foo"), this.valueModelModel.getValue()); + assertEquals("bar", this.testModel.getValue()); + + this.getTestModel().setValue(null); + assertEquals("foo", this.keyModel.getValue()); + assertEquals(this.valueModels.get("foo"), this.valueModelModel.getValue()); + assertNull(this.testModel.getValue()); } - protected void verifyPropertyChanges2() { - this.stringModelEvent = null; - this.stringModelModelEvent = null; - this.doubleModelEvent = null; - this.getDoubleModel().setValue("bar"); - this.verifyEvent(this.stringModelEvent, this.stringModel, "foo", "bar"); - assertNull(this.stringModelModelEvent); - this.verifyEvent(this.doubleModelEvent, this.doubleModel, "foo", "bar"); - - this.stringModelEvent = null; - this.stringModelModelEvent = null; - this.doubleModelEvent = null; - this.getDoubleModel().setValue(null); - this.verifyEvent(this.stringModelEvent, this.stringModel, "bar", null); - assertNull(this.stringModelModelEvent); - this.verifyEvent(this.doubleModelEvent, this.doubleModel, "bar", null); - - this.stringModelEvent = null; - this.stringModelModelEvent = null; - this.doubleModelEvent = null; - this.getDoubleModel().setValue("foo"); - this.verifyEvent(this.stringModelEvent, this.stringModel, null, "foo"); - assertNull(this.stringModelModelEvent); - this.verifyEvent(this.doubleModelEvent, this.doubleModel, null, "foo"); - - this.stringModelEvent = null; - this.stringModelModelEvent = null; - this.doubleModelEvent = null; - ModifiablePropertyValueModel<String> stringModel2 = new SimplePropertyValueModel<>("TTT"); - this.stringModelModel.setValue(stringModel2); - assertNull(this.stringModelEvent); - this.verifyEvent(this.stringModelModelEvent, this.stringModelModel, this.stringModel, stringModel2); - this.verifyEvent(this.doubleModelEvent, this.doubleModel, "foo", "TTT"); - - this.stringModelEvent = null; - this.stringModelModelEvent = null; - this.doubleModelEvent = null; - this.getDoubleModel().setValue("XXX"); - assertNull(this.stringModelEvent); - assertNull(this.stringModelModelEvent); - this.verifyEvent(this.doubleModelEvent, this.doubleModel, "TTT", "XXX"); - assertEquals("foo", this.stringModel.getValue()); - assertEquals("XXX", stringModel2.getValue()); - - this.stringModelEvent = null; - this.stringModelModelEvent = null; - this.doubleModelEvent = null; - this.stringModelModel.setValue(this.stringModel); - assertNull(this.stringModelEvent); - this.verifyEvent(this.stringModelModelEvent, this.stringModelModel, stringModel2, this.stringModel); - this.verifyEvent(this.doubleModelEvent, this.doubleModel, "XXX", "foo"); + public void testPropertyChange_directSet() { + this.testModel.addPropertyChangeListener(PropertyValueModel.VALUE, this.testModelListener); + + this.keyModel.setValue("foo"); + this.verifyEvent(this.testModelEvent, this.testModel, null, "foofoo"); + + this.testModelEvent = null; + this.getTestModel().setValue("bar"); + this.verifyEvent(this.testModelEvent, this.testModel, "foofoo", "bar"); + + this.testModelEvent = null; + this.getTestModel().setValue(null); + this.verifyEvent(this.testModelEvent, this.testModel, "bar", null); + + this.testModelEvent = null; + this.getTestModel().setValue("foo"); + this.verifyEvent(this.testModelEvent, this.testModel, null, "foo"); } } diff --git a/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/model/value/DoublePropertyValueModelTests.java b/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/model/value/DoublePropertyValueModelTests.java index ce392ccc24..d896e6c6c9 100644 --- a/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/model/value/DoublePropertyValueModelTests.java +++ b/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/model/value/DoublePropertyValueModelTests.java @@ -9,14 +9,14 @@ ******************************************************************************/ package org.eclipse.jpt.common.utility.tests.internal.model.value; +import java.util.HashMap; import org.eclipse.jpt.common.utility.internal.model.AbstractModel; -import org.eclipse.jpt.common.utility.internal.model.value.SimplePropertyValueModel; import org.eclipse.jpt.common.utility.internal.model.value.PropertyValueModelTools; +import org.eclipse.jpt.common.utility.internal.model.value.SimplePropertyValueModel; +import org.eclipse.jpt.common.utility.internal.transformer.TransformerAdapter; import org.eclipse.jpt.common.utility.model.event.PropertyChangeEvent; import org.eclipse.jpt.common.utility.model.listener.ChangeAdapter; import org.eclipse.jpt.common.utility.model.listener.ChangeListener; -import org.eclipse.jpt.common.utility.model.listener.PropertyChangeListener; -import org.eclipse.jpt.common.utility.model.value.ModifiablePropertyValueModel; import org.eclipse.jpt.common.utility.model.value.PropertyValueModel; import org.eclipse.jpt.common.utility.tests.internal.TestTools; import junit.framework.TestCase; @@ -25,17 +25,13 @@ import junit.framework.TestCase; public class DoublePropertyValueModelTests extends TestCase { - protected ModifiablePropertyValueModel<String> stringModel; - protected ChangeListener stringModelListener; - protected PropertyChangeEvent stringModelEvent; - - protected ModifiablePropertyValueModel<ModifiablePropertyValueModel<String>> stringModelModel; - protected ChangeListener stringModelModelListener; - protected PropertyChangeEvent stringModelModelEvent; + protected SimplePropertyValueModel<String> keyModel; + protected HashMap<String, SimplePropertyValueModel<String>> valueModels; + protected PropertyValueModel<SimplePropertyValueModel<String>> valueModelModel; - protected PropertyValueModel<String> doubleModel; - protected ChangeListener doubleModelListener; - protected PropertyChangeEvent doubleModelEvent; + protected PropertyValueModel<String> testModel; + protected ChangeListener testModelListener; + protected PropertyChangeEvent testModelEvent; public DoublePropertyValueModelTests(String name) { super(name); @@ -44,17 +40,40 @@ public class DoublePropertyValueModelTests @Override protected void setUp() throws Exception { super.setUp(); - this.stringModel = new SimplePropertyValueModel<>("foo"); - this.stringModelListener = new StringModelListener(); + this.keyModel = new SimplePropertyValueModel<>(null); + this.valueModels = new HashMap<>(); + this.valueModelModel = this.buildValueModelModel(); + + this.testModel = this.buildTestModel(this.valueModelModel); + this.testModelListener = new TestModelListener(); + } - this.stringModelModel = new SimplePropertyValueModel<>(this.stringModel); - this.stringModelModelListener = new StringModelModelListener(); + protected PropertyValueModel<SimplePropertyValueModel<String>> buildValueModelModel() { + return PropertyValueModelTools.transform(this.keyModel, new KeyTransformer()); + } + + public class KeyTransformer + extends TransformerAdapter<String, SimplePropertyValueModel<String>> + { + @Override + public SimplePropertyValueModel<String> transform(String key) { + return DoublePropertyValueModelTests.this.getValueModel(key); + } + } - this.doubleModel = this.buildDoubleModel(this.stringModelModel); - this.doubleModelListener = new DoubleModelListener(); + protected SimplePropertyValueModel<String> getValueModel(String key) { + if (key == null) { + return null; + } + SimplePropertyValueModel<String> valueModel = this.valueModels.get(key); + if (valueModel == null) { + valueModel = new SimplePropertyValueModel<>(key + key); + this.valueModels.put(key, valueModel); + } + return valueModel; } - protected PropertyValueModel<String> buildDoubleModel(ModifiablePropertyValueModel<ModifiablePropertyValueModel<String>> modelModel) { + protected PropertyValueModel<String> buildTestModel(PropertyValueModel<SimplePropertyValueModel<String>> modelModel) { return PropertyValueModelTools.doubleWrap(modelModel); } @@ -64,259 +83,123 @@ public class DoublePropertyValueModelTests super.tearDown(); } - public void testGetValue1() { - assertEquals("foo", this.stringModel.getValue()); - assertEquals(this.stringModel, this.stringModelModel.getValue()); - assertNull(this.doubleModel.getValue()); - this.doubleModel.addPropertyChangeListener(PropertyValueModel.VALUE, this.doubleModelListener); - assertEquals("foo", this.doubleModel.getValue()); + public void testGetValue() { + assertNull(this.keyModel.getValue()); + assertNull(this.valueModelModel.getValue()); + assertNull(this.testModel.getValue()); - this.stringModel.setValue("bar"); - assertEquals("bar", this.stringModel.getValue()); - assertEquals("bar", this.doubleModel.getValue()); + this.testModel.addPropertyChangeListener(PropertyValueModel.VALUE, this.testModelListener); - this.stringModel.setValue("baz"); - assertEquals("baz", this.stringModel.getValue()); - assertEquals("baz", this.doubleModel.getValue()); + assertNull(this.keyModel.getValue()); + assertNull(this.valueModelModel.getValue()); + assertNull(this.testModel.getValue()); - this.stringModel.setValue(null); - assertNull(this.stringModel.getValue()); - assertNull(this.doubleModel.getValue()); + this.keyModel.setValue("foo"); + assertEquals("foo", this.keyModel.getValue()); + assertEquals(this.valueModels.get("foo"), this.valueModelModel.getValue()); + assertEquals("foofoo", this.testModel.getValue()); - this.stringModel.setValue("foo"); - assertEquals("foo", this.stringModel.getValue()); - assertEquals("foo", this.doubleModel.getValue()); - } + this.keyModel.setValue("bar"); + assertEquals("bar", this.keyModel.getValue()); + assertEquals(this.valueModels.get("bar"), this.valueModelModel.getValue()); + assertEquals("barbar", this.testModel.getValue()); - public void testGetValue2() { - assertNull(this.doubleModel.getValue()); - this.doubleModel.addPropertyChangeListener(PropertyValueModel.VALUE, this.doubleModelListener); - assertEquals("foo", this.doubleModel.getValue()); + this.keyModel.setValue("baz"); + assertEquals("baz", this.keyModel.getValue()); + assertEquals(this.valueModels.get("baz"), this.valueModelModel.getValue()); + assertEquals("bazbaz", this.testModel.getValue()); - this.stringModelModel.setValue(null); - assertNull(this.doubleModel.getValue()); + this.keyModel.setValue(null); + assertNull(this.keyModel.getValue()); + assertNull(this.valueModelModel.getValue()); + assertNull(this.testModel.getValue()); - ModifiablePropertyValueModel<String> stringModel2 = new SimplePropertyValueModel<>("TTT"); - this.stringModelModel.setValue(stringModel2); - assertEquals("TTT", this.doubleModel.getValue()); + this.keyModel.setValue("foo"); + assertEquals("foo", this.keyModel.getValue()); + assertEquals(this.valueModels.get("foo"), this.valueModelModel.getValue()); + assertEquals("foofoo", this.testModel.getValue()); - this.stringModelModel.setValue(this.stringModel); - assertEquals("foo", this.doubleModel.getValue()); - } + this.valueModels.get("foo").setValue("XXX"); + assertEquals("foo", this.keyModel.getValue()); + assertEquals(this.valueModels.get("foo"), this.valueModelModel.getValue()); + assertEquals("XXX", this.testModel.getValue()); - public void testLazyListening1() { - assertTrue(((AbstractModel) this.stringModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) this.stringModelModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - this.doubleModel.addChangeListener(this.doubleModelListener); - assertTrue(((AbstractModel) this.stringModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) this.stringModelModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); - this.doubleModel.removeChangeListener(this.doubleModelListener); - assertTrue(((AbstractModel) this.stringModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) this.stringModelModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - - this.doubleModel.addPropertyChangeListener(PropertyValueModel.VALUE, this.doubleModelListener); - assertTrue(((AbstractModel) this.stringModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); - this.doubleModel.removePropertyChangeListener(PropertyValueModel.VALUE, this.doubleModelListener); - assertTrue(((AbstractModel) this.stringModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - - this.doubleModel.addPropertyChangeListener(PropertyValueModel.VALUE, this.doubleModelListener); - ModifiablePropertyValueModel<String> stringModel2 = new SimplePropertyValueModel<>("TTT"); - assertTrue(((AbstractModel) this.stringModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) stringModel2).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - this.stringModelModel.setValue(stringModel2); - assertTrue(((AbstractModel) this.stringModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) stringModel2).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); - this.stringModelModel.setValue(this.stringModel); - assertTrue(((AbstractModel) this.stringModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) stringModel2).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - } + this.testModel.removePropertyChangeListener(PropertyValueModel.VALUE, this.testModelListener); - public void testLazyListening2() { - ChangeListener doubleModelListener2 = new ChangeAdapter(); - PropertyChangeListener doubleModelListener3 = new ChangeAdapter(); - - assertTrue(((AbstractModel) this.stringModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) this.stringModelModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - this.doubleModel.addChangeListener(this.doubleModelListener); - assertTrue(((AbstractModel) this.stringModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) this.stringModelModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); - this.doubleModel.addChangeListener(doubleModelListener2); - assertTrue(((AbstractModel) this.stringModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) this.stringModelModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); - this.doubleModel.addPropertyChangeListener(PropertyValueModel.VALUE, doubleModelListener3); - assertTrue(((AbstractModel) this.stringModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) this.stringModelModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); - this.doubleModel.removeChangeListener(doubleModelListener2); - assertTrue(((AbstractModel) this.stringModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) this.stringModelModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); - this.doubleModel.removePropertyChangeListener(PropertyValueModel.VALUE, doubleModelListener3); - assertTrue(((AbstractModel) this.stringModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) this.stringModelModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); - this.doubleModel.removeChangeListener(this.doubleModelListener); - assertTrue(((AbstractModel) this.stringModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) this.stringModelModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - - this.doubleModel.addPropertyChangeListener(PropertyValueModel.VALUE, this.doubleModelListener); - assertTrue(((AbstractModel) this.stringModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); - this.doubleModel.removePropertyChangeListener(PropertyValueModel.VALUE, this.doubleModelListener); - assertTrue(((AbstractModel) this.stringModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - - this.doubleModel.addPropertyChangeListener(PropertyValueModel.VALUE, this.doubleModelListener); - ModifiablePropertyValueModel<String> stringModel2 = new SimplePropertyValueModel<>("TTT"); - assertTrue(((AbstractModel) this.stringModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) stringModel2).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - this.stringModelModel.setValue(stringModel2); - assertTrue(((AbstractModel) this.stringModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) stringModel2).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); - this.stringModelModel.setValue(this.stringModel); - assertTrue(((AbstractModel) this.stringModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) stringModel2).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); + assertEquals("foo", this.keyModel.getValue()); // simple PVM + assertNull(this.valueModelModel.getValue()); + assertNull(this.testModel.getValue()); } - public void testLazyListening3() { - assertTrue(((AbstractModel) this.stringModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) this.stringModelModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); + public void testLazyListening() { + assertTrue(((AbstractModel) this.keyModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); + assertTrue(((AbstractModel) this.valueModelModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); + assertTrue(((AbstractModel) this.testModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - this.stringModelModel.setValue(null); - this.doubleModel.addChangeListener(this.doubleModelListener); - assertTrue(((AbstractModel) this.stringModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) this.stringModelModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); + this.testModel.addChangeListener(this.testModelListener); - this.stringModelModel.setValue(this.stringModel); - assertTrue(((AbstractModel) this.stringModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) this.stringModelModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); + assertTrue(((AbstractModel) this.keyModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); + assertTrue(((AbstractModel) this.valueModelModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); + assertTrue(((AbstractModel) this.testModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); + this.testModel.removeChangeListener(this.testModelListener); + assertTrue(((AbstractModel) this.keyModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); + assertTrue(((AbstractModel) this.valueModelModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); + assertTrue(((AbstractModel) this.testModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - this.stringModelModel.setValue(null); - assertTrue(((AbstractModel) this.stringModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) this.stringModelModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); + this.testModel.addPropertyChangeListener(PropertyValueModel.VALUE, this.testModelListener); + assertTrue(((AbstractModel) this.keyModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); + this.testModel.removePropertyChangeListener(PropertyValueModel.VALUE, this.testModelListener); + assertTrue(((AbstractModel) this.keyModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); + } - this.doubleModel.removeChangeListener(this.doubleModelListener); - assertTrue(((AbstractModel) this.stringModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) this.stringModelModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); + public void testPropertyChange() { + this.testModel.addPropertyChangeListener(PropertyValueModel.VALUE, this.testModelListener); + this.testModelEvent = null; + this.keyModel.setValue("foo"); + this.verifyEvent(this.testModelEvent, this.testModel, null, "foofoo"); - this.doubleModel.addPropertyChangeListener(PropertyValueModel.VALUE, this.doubleModelListener); - assertTrue(((AbstractModel) this.stringModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) this.stringModelModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); + this.testModelEvent = null; + this.keyModel.setValue("bar"); + this.verifyEvent(this.testModelEvent, this.testModel, "foofoo", "barbar"); - this.stringModelModel.setValue(this.stringModel); - assertTrue(((AbstractModel) this.stringModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) this.stringModelModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); + this.testModelEvent = null; + this.keyModel.setValue(null); + this.verifyEvent(this.testModelEvent, this.testModel, "barbar", null); - this.stringModelModel.setValue(null); - assertTrue(((AbstractModel) this.stringModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) this.stringModelModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); + this.testModelEvent = null; + this.keyModel.setValue("foo"); + this.verifyEvent(this.testModelEvent, this.testModel, null, "foofoo"); - this.doubleModel.removePropertyChangeListener(PropertyValueModel.VALUE, this.doubleModelListener); - assertTrue(((AbstractModel) this.stringModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) this.stringModelModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - } - - public void testPropertyChange1() { - this.stringModel.addChangeListener(this.stringModelListener); - this.stringModelModel.addChangeListener(this.stringModelModelListener); - this.doubleModel.addChangeListener(this.doubleModelListener); - this.verifyPropertyChanges1(); - } - - public void testPropertyChange2() { - this.stringModel.addPropertyChangeListener(PropertyValueModel.VALUE, this.stringModelListener); - this.stringModelModel.addPropertyChangeListener(PropertyValueModel.VALUE, this.stringModelModelListener); - this.doubleModel.addPropertyChangeListener(PropertyValueModel.VALUE, this.doubleModelListener); - this.verifyPropertyChanges1(); - } - - public void testToString() { - this.stringModel.addChangeListener(this.stringModelListener); - this.stringModelModel.addChangeListener(this.stringModelModelListener); - this.doubleModel.addChangeListener(this.doubleModelListener); - assertFalse(this.doubleModel.toString().indexOf("foo") == -1); + this.testModelEvent = null; + this.valueModels.get("foo").setValue("XXX"); + this.verifyEvent(this.testModelEvent, this.testModel, "foofoo", "XXX"); } public void testConstructor_NPE() { boolean exCaught = false; try { - this.doubleModel = this.buildDoubleModel(null); + this.testModel = this.buildTestModel(null); } catch (NullPointerException ex) { exCaught = true; } assertTrue(exCaught); } - protected void verifyPropertyChanges1() { - this.stringModelEvent = null; - this.stringModelModelEvent = null; - this.doubleModelEvent = null; - this.stringModel.setValue("bar"); - this.verifyEvent(this.stringModelEvent, this.stringModel, "foo", "bar"); - assertNull(this.stringModelModelEvent); - this.verifyEvent(this.doubleModelEvent, this.doubleModel, "foo", "bar"); - - this.stringModelEvent = null; - this.stringModelModelEvent = null; - this.doubleModelEvent = null; - this.stringModel.setValue(null); - this.verifyEvent(this.stringModelEvent, this.stringModel, "bar", null); - assertNull(this.stringModelModelEvent); - this.verifyEvent(this.doubleModelEvent, this.doubleModel, "bar", null); - - this.stringModelEvent = null; - this.stringModelModelEvent = null; - this.doubleModelEvent = null; - this.stringModel.setValue("foo"); - this.verifyEvent(this.stringModelEvent, this.stringModel, null, "foo"); - assertNull(this.stringModelModelEvent); - this.verifyEvent(this.doubleModelEvent, this.doubleModel, null, "foo"); - - this.stringModelEvent = null; - this.stringModelModelEvent = null; - this.doubleModelEvent = null; - ModifiablePropertyValueModel<String> stringModel2 = new SimplePropertyValueModel<>("TTT"); - this.stringModelModel.setValue(stringModel2); - assertNull(this.stringModelEvent); - this.verifyEvent(this.stringModelModelEvent, this.stringModelModel, this.stringModel, stringModel2); - this.verifyEvent(this.doubleModelEvent, this.doubleModel, "foo", "TTT"); - - this.stringModelEvent = null; - this.stringModelModelEvent = null; - this.doubleModelEvent = null; - this.stringModelModel.setValue(this.stringModel); - assertNull(this.stringModelEvent); - this.verifyEvent(this.stringModelModelEvent, this.stringModelModel, stringModel2, this.stringModel); - this.verifyEvent(this.doubleModelEvent, this.doubleModel, "TTT", "foo"); - } - protected void verifyEvent(PropertyChangeEvent event, Object source, Object oldValue, Object newValue) { + assertNotNull(event); assertEquals(source, event.getSource()); assertEquals(PropertyValueModel.VALUE, event.getPropertyName()); assertEquals(oldValue, event.getOldValue()); assertEquals(newValue, event.getNewValue()); } - protected class StringModelListener - extends ChangeAdapter - { - @Override - public void propertyChanged(PropertyChangeEvent event) { - DoublePropertyValueModelTests.this.stringModelEvent = event; - } - } - - protected class StringModelModelListener - extends ChangeAdapter - { - @Override - public void propertyChanged(PropertyChangeEvent event) { - DoublePropertyValueModelTests.this.stringModelModelEvent = event; - } - } - - protected class DoubleModelListener + protected class TestModelListener extends ChangeAdapter { @Override public void propertyChanged(PropertyChangeEvent event) { - DoublePropertyValueModelTests.this.doubleModelEvent = event; + DoublePropertyValueModelTests.this.testModelEvent = event; } } } |