diff options
author | Brian Vosburgh | 2016-07-15 15:25:29 +0000 |
---|---|---|
committer | Brian Vosburgh | 2017-05-18 22:37:56 +0000 |
commit | 8ff9fb95c56ff9fdc5bc534e0a78e3933e090241 (patch) | |
tree | ba23e1ccee991d07faf2103c04da68b88570dcc1 | |
parent | 595e54e3513c560f3ece0e4a47049334a8a5fee3 (diff) | |
download | webtools.dali-8ff9fb95c56ff9fdc5bc534e0a78e3933e090241.tar.gz webtools.dali-8ff9fb95c56ff9fdc5bc534e0a78e3933e090241.tar.xz webtools.dali-8ff9fb95c56ff9fdc5bc534e0a78e3933e090241.zip |
refactor BufferedPVM
13 files changed, 1134 insertions, 1296 deletions
diff --git a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/properties/JptProjectPropertiesPage.java b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/properties/JptProjectPropertiesPage.java index df59dc5316..78fc9c36d1 100644 --- a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/properties/JptProjectPropertiesPage.java +++ b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/properties/JptProjectPropertiesPage.java @@ -28,7 +28,8 @@ import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jpt.common.ui.internal.plugin.JptCommonUiPlugin; import org.eclipse.jpt.common.utility.internal.ArrayTools; import org.eclipse.jpt.common.utility.internal.ObjectTools; -import org.eclipse.jpt.common.utility.internal.model.value.BufferedModifiablePropertyValueModel; +import org.eclipse.jpt.common.utility.internal.model.value.BufferedPropertyValueModelAdapter; +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.Model; import org.eclipse.jpt.common.utility.model.listener.AbstractChangeListener; @@ -65,7 +66,7 @@ public abstract class JptProjectPropertiesPage protected volatile boolean engaged = false; protected final ModifiablePropertyValueModel<IProject> projectModel; - protected final BufferedModifiablePropertyValueModel.Trigger trigger; + protected final BufferedPropertyValueModelAdapter.Trigger trigger; protected final ChangeListener validationListener; @@ -74,7 +75,7 @@ public abstract class JptProjectPropertiesPage super(); this.projectModel = new SimplePropertyValueModel<>(); - this.trigger = new BufferedModifiablePropertyValueModel.Trigger(); + this.trigger = PropertyValueModelTools.bufferedPropertyValueModelAdapterTrigger(); this.buildModels(); @@ -350,15 +351,15 @@ public abstract class JptProjectPropertiesPage * Return whether any of the models are buffering a change. */ private boolean isBuffering() { - for (BufferedModifiablePropertyValueModel<?> model : this.buildBufferedModels()) { - if (model.isBuffering()) { + for (PropertyValueModel<Boolean> flag : this.buildBufferingFlags()) { + if (flag.getValue().booleanValue()) { return true; } } return false; } - protected abstract BufferedModifiablePropertyValueModel<?>[] buildBufferedModels(); + protected abstract PropertyValueModel<Boolean>[] buildBufferingFlags(); @Override protected void performDefaults() { diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/AbstractPropertyValueModel.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/AbstractPropertyValueModel.java deleted file mode 100644 index aeb34de889..0000000000 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/AbstractPropertyValueModel.java +++ /dev/null @@ -1,125 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009, 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.model.AbstractModel; -import org.eclipse.jpt.common.utility.internal.model.ChangeSupport; -import org.eclipse.jpt.common.utility.internal.model.SingleAspectChangeSupport; -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.PropertyValueModel; - -/** - * This abstract class provides the infrastructure for "lazily" adding/removing - * listeners to/from an underlying model as <em>property</em> change - * listeners are added to/removed from itself. - * Subclasses will need to engage and disengage the underlying model - * appropriately and fire the appropriate <em>property</em> - * change events. - * <p> - * Subclasses must implement the appropriate {@link PropertyValueModel}. - * <p> - * Subclasses must implement the following methods:<ul> - * <li>{@link #engageModel()}<p> - * implement this method to add the appropriate listener(s) to the - * underlying model - * <li>{@link #disengageModel()}<p> - * implement this method to remove the appropriate listener(s) from the - * underlying model - * </ul> - */ -public abstract class AbstractPropertyValueModel - extends AbstractModel -{ - // ********** constructor/initialization ********** - - protected AbstractPropertyValueModel() { - super(); - } - - @Override - protected ChangeSupport buildChangeSupport() { - return new SingleAspectChangeSupport(this, PropertyChangeListener.class, PropertyValueModel.VALUE); - } - - - // ********** listeners ********** - - /** - * Extend to start listening to the underlying model if necessary. - */ - @Override - public synchronized void addChangeListener(ChangeListener listener) { - if (this.hasNoListeners()) { - this.engageModel(); - } - super.addChangeListener(listener); - } - - /** - * Extend to stop listening to the underlying model if necessary. - */ - @Override - public synchronized void removeChangeListener(ChangeListener listener) { - super.removeChangeListener(listener); - if (this.hasNoListeners()) { - this.disengageModel(); - } - } - - /** - * Extend to start listening to the underlying model if necessary. - */ - @Override - public synchronized void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { - if (propertyName.equals(PropertyValueModel.VALUE) && this.hasNoListeners()) { - this.engageModel(); - } - super.addPropertyChangeListener(propertyName, listener); - } - - /** - * Extend to stop listening to the underlying model if necessary. - */ - @Override - public synchronized void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { - super.removePropertyChangeListener(propertyName, listener); - if (propertyName.equals(PropertyValueModel.VALUE) && this.hasNoListeners()) { - this.disengageModel(); - } - } - - /** - * Return whether the model has no property value listeners. - */ - public boolean hasNoListeners() { - return ! this.hasListeners(); - } - - /** - * Return whether the model has any property value listeners. - */ - public boolean hasListeners() { - return this.hasAnyPropertyChangeListeners(PropertyValueModel.VALUE); - } - - - // ********** subclass implementation ********** - - /** - * Engage the underlying model. - */ - protected abstract void engageModel(); - - /** - * Stop listening to the underlying model. - */ - protected abstract void disengageModel(); -} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/BasePluggablePropertyValueModel.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/BasePluggablePropertyValueModel.java index 69538412e0..6b94a430d8 100644 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/BasePluggablePropertyValueModel.java +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/BasePluggablePropertyValueModel.java @@ -174,7 +174,7 @@ public abstract class BasePluggablePropertyValueModel<V, A extends BasePluggable // ********** Adapter Listener ********** /** - * Simple callback. + * Simple callback. Allows us to keep the callback method internal. */ /* CU private */ class AdapterListener implements Adapter.Listener<V> diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/BufferedModifiablePropertyValueModel.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/BufferedModifiablePropertyValueModel.java deleted file mode 100644 index 8dbd7b2f56..0000000000 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/BufferedModifiablePropertyValueModel.java +++ /dev/null @@ -1,398 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007, 2012 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; -import org.eclipse.jpt.common.utility.model.value.ModifiablePropertyValueModel; - -/** - * A <code>BufferedModifiablePropertyValueModel</code> is used to hold a temporary - * copy of the value - * in another property value model (the "wrapped" value model). The application - * can modify this temporary copy, ad nauseam; but the temporary copy is only - * passed through to the "wrapped" value model when the trigger "accepts" the - * buffered value. Alternatively, the application can "reset" the buffered value - * to the original, "wrapped" value. - * <p> - * The trigger is another {@link PropertyValueModel} that holds a - * {@link Boolean} and the application changes the trigger's value to - * <code>true</code> on "accept", <code>false</code> on "reset". - * <p> - * Typically, in a dialog:<ul> - * <li>pressing the "OK" button will trigger an "accept" and close the dialog - * <li>pressing the "Cancel" button will simply close the dialog, - * dropping the "buffered" values into the bit bucket - * <li>pressing the "Apply" button will trigger an "accept" and leave the - * dialog open - * <li>pressing the "Restore" button will trigger a "reset" and leave the - * dialog open - * </ul> - * A number of buffered property value models can wrap another set of - * property aspect adapters that adapt the various aspects of a single - * domain model. All the buffered property value models can be hooked to the - * same trigger, and that trigger is controlled by the application, typically - * via the "OK" button in a dialog. - * - * @param <V> the type of the model's value - * @see PropertyAspectAdapter - */ -public class BufferedModifiablePropertyValueModel<V> - extends PropertyValueModelWrapper<V> - implements ModifiablePropertyValueModel<V> -{ - /** - * We cache the value here until it is accepted and passed - * through to the wrapped value model. - */ - protected volatile V bufferedValue; - - /** - * This is set to true when we are "accepting" the buffered value - * and passing it through to the wrapped value model. This allows - * us to ignore the property change event fired by the wrapped - * value model. - * (We can't stop listening to the wrapped value model, because - * if we are the only listener that could "deactivate" the wrapped - * value model.) - */ - protected volatile boolean accepting; - - /** - * This is the trigger that indicates whether the buffered value - * should be accepted or reset. - */ - protected final PropertyValueModel<Boolean> triggerModel; - - /** This listens to the trigger model. */ - protected final PropertyChangeListener triggerListener; - - /** - * This flag indicates whether our buffered value has been assigned - * a value and is possibly out of sync with the wrapped value. - */ - protected volatile boolean buffering; - - - // ********** constructor/initialization ********** - - /** - * Construct a buffered property value model with the specified wrapped - * property value model and trigger model. - */ - // TODO wrap the value model in a CachingPVMWrapper and get rid of accepting flag - public BufferedModifiablePropertyValueModel(ModifiablePropertyValueModel<V> valueModel, PropertyValueModel<Boolean> triggerModel) { - super(valueModel); - if (triggerModel == null) { - throw new NullPointerException(); - } - this.triggerModel = triggerModel; - this.bufferedValue = null; - this.buffering = false; - this.accepting = false; - this.triggerListener = this.buildTriggerListener(); - } - - protected PropertyChangeListener buildTriggerListener() { - return new TriggerListener(); - } - - protected class TriggerListener - extends PropertyChangeAdapter - { - @Override - public void propertyChanged(PropertyChangeEvent event) { - BufferedModifiablePropertyValueModel.this.triggerChanged(event); - } - } - - - // ********** value ********** - - /** - * If we are currently "buffering" a value, return that; - * otherwise, return the wrapped value. - */ - public V getValue() { - return this.buffering ? this.bufferedValue : this.valueModel.getValue(); - } - - /** - * Assign the new value to our "buffered" value. - * It will be pushed to the wrapped value model - * when the trigger is "accepted". - */ - public void setValue(V value) { - if (this.buffering) { - if (ObjectTools.equals(value, this.valueModel.getValue())) { - // the buffered value is being set back to the original value - this.reset(); - } else { - // the buffered value is being changed - Object old = this.bufferedValue; - this.bufferedValue = value; - this.firePropertyChanged(VALUE, old, value); - } - } else { - if (ObjectTools.equals(value, this.valueModel.getValue())) { - // the buffered value is being set to the same value as the original value - ignore - } else { - // the buffered value is being set for the first time - Object old = this.valueModel.getValue(); - this.bufferedValue = value; - this.buffering = true; - this.firePropertyChanged(VALUE, old, value); - } - } - } - - - // ********** PropertyValueModelWrapper extensions ********** - - /** - * Extend to engage the trigger model also. - */ - @Override - protected void engageModel() { - super.engageModel(); - this.triggerModel.addPropertyChangeListener(VALUE, this.triggerListener); - } - - /** - * Extend to disengage the trigger model also. - */ - @Override - protected void disengageModel() { - this.triggerModel.removePropertyChangeListener(VALUE, this.triggerListener); - super.disengageModel(); - } - - - // ********** behavior ********** - - /** - * If we are currently "accepting" the value (i.e passing it on to the - * "wrapped" model), ignore change notifications, since we caused - * them and our own listeners are already aware of the change. - */ - @Override - protected void wrappedValueChanged(PropertyChangeEvent event) { - if ( ! this.accepting) { - this.wrappedValueChanged_(event); - } - } - - /** - * If we have a "buffered" value, check whether the "wrapped" value has - * changed to be the same as the "buffered" value. If it has, stop "buffering"; - * if not, do nothing. - * If we do not yet have a "buffered" value, simply propagate the - * change notification with the buffered model as the source. - */ - protected void wrappedValueChanged_(PropertyChangeEvent event) { - if (this.buffering) { - if (ObjectTools.equals(event.getNewValue(), this.bufferedValue)) { - // the buffered value is being set back to the original value - this.reset(); - } else { - this.handleChangeConflict(event); - } - } else { - this.firePropertyChanged(event.clone(this)); - } - } - - /** - * By default, if we have a "buffered" value and the "wrapped" value changes, - * we simply ignore the new "wrapped" value and simply overlay it with the - * "buffered" value if it is "accepted". ("Last One In Wins" concurrency model) - * Subclasses can override this method to change that behavior with a - * different concurrency model. For example, you could drop the "buffered" value - * and replace it with the new "wrapped" value, or you could throw an - * exception. - */ - protected void handleChangeConflict(@SuppressWarnings("unused") PropertyChangeEvent event) { - // the default is to do nothing - } - - protected void triggerChanged(PropertyChangeEvent event) { - this.triggerChanged(((Boolean) event.getNewValue()).booleanValue()); - } - - /** - * The trigger changed:<ul> - * <li>If it is now <code>true</code>, "accept" the buffered value and push - * it to the wrapped value model. - * <li>If it is now <code>false</code>, "reset" the buffered value to its - * original value. - * </ul> - */ - protected void triggerChanged(boolean triggerValue) { - // if nothing has been "buffered", we don't need to do anything: - // nothing needs to be passed through; nothing needs to be reset; - if (this.buffering) { - if (triggerValue) { - this.accept(); - } else { - this.reset(); - } - } - } - - protected void accept() { - // set the accepting flag so we ignore any events - // fired by the wrapped value model - this.accepting = true; - try { - this.getValueModel().setValue(this.bufferedValue); - } finally { - this.bufferedValue = null; - this.buffering = false; - // clear the flag once the "accept" is complete - this.accepting = false; - } - } - - protected void reset() { - // notify our listeners that our value has been reset - Object old = this.bufferedValue; - this.bufferedValue = null; - this.buffering = false; - this.firePropertyChanged(VALUE, old, this.valueModel.getValue()); - } - - @Override - public void toString(StringBuilder sb) { - sb.append(this.getValue()); - } - - - // ********** misc ********** - - /** - * Return whether the buffered model is currently "buffering" - * a value. - */ - public boolean isBuffering() { - return this.buffering; - } - - /** - * Our constructor accepts only a {@link ModifiablePropertyValueModel}{@code<T>}. - */ - @SuppressWarnings("unchecked") - protected ModifiablePropertyValueModel<V> getValueModel() { - return (ModifiablePropertyValueModel<V>) this.valueModel; - } - - - // ********** trigger ********** - - /** - * <code>Trigger</code> is a special property value model that only maintains its - * value (of <code>true</code> or <code>false</code>) during the change notification caused by - * {@link #setValue(Object)}. In other words, a <code>Trigger</code> - * only has a valid value when it is being set. - */ - public static class Trigger - extends SimplePropertyValueModel<Boolean> - { - /** - * Construct a trigger with a null value. - */ - public Trigger() { - super(); - } - - - // ********** ValueModel implementation ********** - - /** - * Extend so that this method can only be invoked during - * change notification triggered by {@link #setValue(Object)}. - */ - @Override - public Boolean getValue() { - if (this.value == null) { - throw new IllegalStateException("The method Trigger.getValue() may only be called during change notification."); //$NON-NLS-1$ - } - return this.value; - } - - /** - * Extend to reset the value to <code>null</code> once all the - * listeners have been notified. - */ - @Override - public void setValue(Boolean value) { - super.setValue(value); - this.value = null; - } - - - // ********** convenience methods ********** - - /** - * Set the trigger's value:<ul> - * <li><code>true</code> indicates "accept" - * <li><code>false</code> indicates "reset" - * </ul> - */ - public void setValue(boolean value) { - this.setValue(Boolean.valueOf(value)); - } - - /** - * Return the trigger's value:<ul> - * <li><code>true</code> indicates "accept" - * <li><code>false</code> indicates "reset" - * </ul> - * This method can only be invoked during change notification. - */ - public boolean booleanValue() { - return this.getValue().booleanValue(); - } - - /** - * Accept the trigger (i.e. set its value to <code>true</code>). - */ - public void accept() { - this.setValue(true); - } - - /** - * Return whether the trigger has been accepted - * (i.e. its value was changed to <code>true</code>). - * This method can only be invoked during change notification. - */ - public boolean isAccepted() { - return this.booleanValue(); - } - - /** - * Reset the trigger (i.e. set its value to <code>false</code>). - */ - public void reset() { - this.setValue(false); - } - - /** - * Return whether the trigger has been reset - * (i.e. its value was changed to <code>false</code>). - * This method can only be invoked during change notification. - */ - public boolean isReset() { - return ! this.booleanValue(); - } - } -} diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/BufferedPropertyValueModelAdapter.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/BufferedPropertyValueModelAdapter.java new file mode 100644 index 0000000000..8ac19c8530 --- /dev/null +++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/BufferedPropertyValueModelAdapter.java @@ -0,0 +1,349 @@ +/******************************************************************************* + * Copyright (c) 2007, 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.ListenerList; +import org.eclipse.jpt.common.utility.internal.ObjectTools; +import org.eclipse.jpt.common.utility.internal.model.ModelTools; +import org.eclipse.jpt.common.utility.model.event.PropertyChangeEvent; +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; + +/** + * This adapter is used to hold a temporary copy of the value + * in another property value model (the <em>wrapped</em> value model). The application + * can modify this temporary copy, ad nauseam; but the temporary copy is only + * passed through to the <em>wrapped</em> value model when the trigger <em>accepts</em> the + * buffered value. Alternatively, the application can <em>reset</em> the buffered value + * to the original, <em>wrapped</em> value. + * <p> + * The trigger is an object that can be used to <em>accept</em> or <em>reset</em> + * the buffered value on one or more buffered value models. + * <p> + * Typically, in a dialog:<ul> + * <li>pressing the "OK" button will trigger an <em>accept</em> and close the dialog + * <li>pressing the "Cancel" button will simply close the dialog, + * dropping the <em>buffered</em> values into the bit bucket + * <li>pressing the "Apply" button will trigger an <em>accept</em> and leave the + * dialog open + * <li>pressing the "Restore" button will trigger a <em>reset</em> and leave the + * dialog open + * </ul> + * As an example: A number of buffered property value models can wrap another set of + * property aspect adapters that adapt the various aspects of a single + * domain model. All the buffered property value models can be hooked to the + * same trigger, and that trigger is controlled by the application, typically + * via the "OK" button in a dialog. + * + * @param <V> the type of the model's value + * @see PropertyAspectAdapter + */ +public class BufferedPropertyValueModelAdapter<V> + implements PluggableModifiablePropertyValueModel.Adapter<V>, PropertyChangeListener +{ + /** + * The <em>wrapped</em> model. + */ + private final ModifiablePropertyValueModel<V> wrappedValueModel; + + /** + * The cached value of {@link #wrappedValueModel}. + */ + private volatile V wrappedValue; + + /** + * The trigger that <em>accepts</em> or <em>resets</em> {@link #bufferedValue}. + */ + private final Trigger trigger; + private final Trigger.Listener triggerListener; + + /** + * The <em>real</em> adapter. + */ + private final BasePluggablePropertyValueModel.Adapter.Listener<V> listener; + + /** + * This flag indicates whether {@link #bufferedValue} has been assigned + * a value and is out of sync with {@link #wrappedValue}. + */ + private final SimplePropertyValueModel<Boolean> bufferingModel; + + /** + * We cache the value here until it is accepted and passed + * through to {@link #wrappedValueModel}. + */ + private volatile V bufferedValue; + + + // ********** constructors ********** + + public BufferedPropertyValueModelAdapter(Factory<V> factory, BasePluggablePropertyValueModel.Adapter.Listener<V> listener) { + super(); + if (factory == null) { + throw new NullPointerException(); + } + this.wrappedValueModel = factory.wrappedValueModel; + this.trigger = factory.trigger; + this.triggerListener = this.buildTriggerListener(); + this.bufferingModel = factory.bufferingModel; + + if (listener == null) { + throw new NullPointerException(); + } + this.listener = listener; + } + + private Trigger.Listener buildTriggerListener() { + return new TriggerListener(); + } + + /* CU private */ class TriggerListener + implements Trigger.Listener + { + public void accept() { + BufferedPropertyValueModelAdapter.this.accept(); + } + public void reset() { + BufferedPropertyValueModelAdapter.this.reset(); + } + @Override + public String toString() { + return ObjectTools.toString(this); + } + } + + + // ********** PluggableModifiablePropertyValueModel.Adapter ********** + + public V getValue() { + return this.isBuffering() ? this.bufferedValue : this.wrappedValue; + } + + public void setValue(V value) { + if (this.isBuffering()) { + if (ObjectTools.equals(value, this.wrappedValue)) { + // our value is being set back to the original wrapped value - stop buffering + this.bufferedValue = null; + this.setBuffering(false); + this.listener.valueChanged(this.wrappedValue); + } else { + // our (buffered) value is being changed + this.listener.valueChanged(this.bufferedValue = value); + } + } else { + if (ObjectTools.equals(value, this.wrappedValue)) { + // our value is being set to the same as the original wrapped value - ignore + } else { + // our value is being changed for the first time - start buffering + this.setBuffering(true); + this.listener.valueChanged(this.bufferedValue = value); + } + } + } + + public void engageModel() { + this.wrappedValueModel.addPropertyChangeListener(PropertyValueModel.VALUE, this); + this.wrappedValue = this.wrappedValueModel.getValue(); + this.trigger.addListener(this.triggerListener); + } + + public void disengageModel() { + this.setBuffering(false); + this.bufferedValue = null; + this.trigger.removeListener(this.triggerListener); + this.wrappedValue = null; + this.wrappedValueModel.removePropertyChangeListener(PropertyValueModel.VALUE, this); + } + + + // ********** PropertyChangeListener ********** + + public void propertyChanged(PropertyChangeEvent event) { + @SuppressWarnings("unchecked") + V newWrappedValue = (V) event.getNewValue(); + this.wrappedValueChanged(newWrappedValue); + } + + /** + * If we have a <em>buffered</em> value, check whether the <em>wrapped</em> value has + * changed to be the same as the <em>buffered</em> value. If it has, stop <em>buffering</em>; + * if not, do nothing. + * If we do not yet have a <em>buffered</em> value, simply propagate the + * change notification with the buffered model as the source. + * <p> + * <strong>NB:</strong> + * By default, if we have a <em>buffered</em> value and the <em>wrapped</em> value changes + * to something other than the current <em>buffered</em> value, + * we simply ignore the new <em>wrapped</em> value and simply overlay it with the + * <em>buffered</em> value if it is <em>accepted</em>. ("Last One In Wins" concurrency model) + * Subclasses can override this method to change that behavior with a + * different concurrency model. For example, it could drop the <em>buffered</em> value + * and replace it with the new <em>wrapped</em> value, or it could throw an + * exception. + */ + private void wrappedValueChanged(V newWrappedValue) { + this.wrappedValue = newWrappedValue; + if (this.isBuffering()) { + if (ObjectTools.equals(this.bufferedValue, this.wrappedValue)) { + // if the buffered value is now the same as the original value, + // there is no need to continue "buffering" + this.bufferedValue = null; + this.setBuffering(false); + } else { + // NOP - see note in method comment + } + } else { + this.listener.valueChanged(this.wrappedValue); + } + } + + + // ********** Trigger calls ********** + + /** + * The trigger has been accepted. + * If we are buffering, push the {@link #bufferedValue} to the {@link #wrappedValue}. + * The resulting change event will clear the {@link #bufferedValue} + * and the {@link #bufferingModel buffering} flag. + */ + /* CU private */ void accept() { + if (this.isBuffering()) { + // the resulting change event will clear the 'bufferedValue' and the 'buffering' flag + this.wrappedValueModel.setValue(this.bufferedValue); + } + } + + /** + * The trigger has been reset. + * If we are buffering, clear the {@link #bufferedValue} + * and the {@link #bufferingModel buffering} flag and notify our listener + * that our value has reverted to the original {@link #wrappedValue}. + */ + /* CU private */ void reset() { + if (this.isBuffering()) { + this.bufferedValue = null; + this.setBuffering(false); + this.listener.valueChanged(this.wrappedValue); + } + } + + + // ********** misc ********** + + private boolean isBuffering() { + return this.bufferingModel.getValue().booleanValue(); + } + + private void setBuffering(boolean buffering) { + this.bufferingModel.setValue(Boolean.valueOf(buffering)); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + if (this.isBuffering()) { + sb.append(this.bufferedValue); + sb.append(" ["); //$NON-NLS-1$ + sb.append(this.wrappedValue); + sb.append("]"); //$NON-NLS-1$ + } else { + sb.append(this.wrappedValue); + } + return ObjectTools.toString(this, sb.toString()); + } + + + // ********** Trigger ********** + + /** + * A trigger is used to <em>accept</em> or <em>reset</em> one or more + * buffered value models. + */ + public static class Trigger { + private final ListenerList<Listener> listenerList = ModelTools.listenerList(); + + public Trigger() { + super(); + } + + /** + * Accept the trigger. + */ + public void accept() { + for (Listener listener : this.listenerList) { + listener.accept(); + } + } + + /** + * Reset the trigger. + */ + public void reset() { + for (Listener listener : this.listenerList) { + listener.reset(); + } + } + + public void addListener(Listener listener) { + this.listenerList.add(listener); + } + + public void removeListener(Listener listener) { + this.listenerList.remove(listener); + } + + @Override + public String toString() { + return ObjectTools.toString(this); + } + + public interface Listener { + void reset(); + void accept(); + } + } + + + // ********** Factory ********** + + public static class Factory<V> + implements PluggableModifiablePropertyValueModel.Adapter.Factory<V> + { + /* CU private */ final ModifiablePropertyValueModel<V> wrappedValueModel; + /* CU private */ final Trigger trigger; + /* CU private */ final SimplePropertyValueModel<Boolean> bufferingModel = new SimplePropertyValueModel<>(Boolean.FALSE); + + public Factory(ModifiablePropertyValueModel<V> wrappedValueModel, Trigger trigger) { + super(); + if (wrappedValueModel == null) { + throw new NullPointerException(); + } + this.wrappedValueModel = wrappedValueModel; + if (trigger == null) { + throw new NullPointerException(); + } + this.trigger = trigger; + } + + public PropertyValueModel<Boolean> getBufferingModel() { + return this.bufferingModel; + } + + public BufferedPropertyValueModelAdapter<V> buildAdapter(BasePluggablePropertyValueModel.Adapter.Listener<V> listener) { + return new BufferedPropertyValueModelAdapter<>(this, 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/PropertyValueModelTools.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/PropertyValueModelTools.java index 3932494f74..7907f101fa 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 @@ -10,7 +10,9 @@ package org.eclipse.jpt.common.utility.internal.model.value; import java.util.Collection; +import org.eclipse.jpt.common.utility.Association; import org.eclipse.jpt.common.utility.closure.Closure; +import org.eclipse.jpt.common.utility.internal.SimpleAssociation; import org.eclipse.jpt.common.utility.internal.predicate.PredicateTools; import org.eclipse.jpt.common.utility.internal.transformer.TransformerAdapter; import org.eclipse.jpt.common.utility.internal.transformer.TransformerTools; @@ -500,6 +502,34 @@ public final class PropertyValueModelTools { } + // ********** buffered wrapper ********** + + /** + * Construct a trigger that can be used to accept or reset one or more + * buffered property value models (or any other listeners). + * + * @see #buffer(ModifiablePropertyValueModel, BufferedPropertyValueModelAdapter.Trigger) + */ + public static BufferedPropertyValueModelAdapter.Trigger bufferedPropertyValueModelAdapterTrigger() { + return new BufferedPropertyValueModelAdapter.Trigger(); + } + + /** + * Construct a property value model that wraps the specified + * property value model and buffers its value, using the specified trigger. + * + * @see BufferedPropertyValueModelAdapter + * @see #bufferedPropertyValueModelAdapterTrigger() + * @see PluggablePropertyValueModel + */ + public static <V> Association<ModifiablePropertyValueModel<V>, PropertyValueModel<Boolean>> buffer(ModifiablePropertyValueModel<V> propertyModel, BufferedPropertyValueModelAdapter.Trigger trigger) { + BufferedPropertyValueModelAdapter.Factory<V> factory = new BufferedPropertyValueModelAdapter.Factory<>(propertyModel, trigger); + ModifiablePropertyValueModel<V> model = modifiablePropertyValueModel(factory); + PropertyValueModel<Boolean> bufferingModel = factory.getBufferingModel(); + return new SimpleAssociation<>(model, bufferingModel); + } + + // ********** null check wrapper ********** /** diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/PropertyValueModelWrapper.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/PropertyValueModelWrapper.java deleted file mode 100644 index 8cb4841bb7..0000000000 --- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/PropertyValueModelWrapper.java +++ /dev/null @@ -1,124 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007, 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 abstract class provides the infrastructure needed to wrap - * another property value model, "lazily" listen to it, and propagate - * its change notifications. Subclasses must implement the appropriate - * {@link PropertyValueModel}. - * <p> - * Subclasses must implement at least one of the following methods:<ul> - * <li>{@link #wrappedValueChanged(PropertyChangeEvent)}<p> - * implement this method to propagate the appropriate change notification - * <li>{@link #wrappedValueChanged(Object, Object) wrappedValueChanged(V, V)}<p> - * implement this method to propagate the appropriate change notification - * <li>{@link #wrappedValueChanged(Object) wrappedValueChanged(V)}<p> - * implement this method to propagate the appropriate change notification - * </ul> - * - * @param <V> the type of the <em>wrapped</em> model's value - */ -public abstract class PropertyValueModelWrapper<V> - extends AbstractPropertyValueModel -{ - /** The wrapped property value model. Never <code>null</code>. */ - protected final PropertyValueModel<? extends V> valueModel; - - /** A listener that allows us to sync with changes to the wrapped value model. */ - protected final PropertyChangeListener valueListener; - - - // ********** constructors/initialization ********** - - /** - * Construct a property value model with the specified wrapped - * property value model. - */ - protected PropertyValueModelWrapper(PropertyValueModel<? extends V> valueModel) { - super(); - if (valueModel == null) { - throw new NullPointerException(); - } - this.valueModel = valueModel; - this.valueListener = this.buildValueListener(); - } - - protected PropertyChangeListener buildValueListener() { - return new ValueListener(); - } - - /* CU private */ class ValueListener - extends PropertyChangeAdapter - { - @Override - public void propertyChanged(PropertyChangeEvent event) { - PropertyValueModelWrapper.this.wrappedValueChanged(event); - } - } - - - // ********** listen to wrapped value model ********** - - /** - * Begin listening to the value model. - */ - @Override - protected void engageModel() { - this.valueModel.addPropertyChangeListener(PropertyValueModel.VALUE, this.valueListener); - } - - /** - * Stop listening to the value model. - */ - @Override - protected void disengageModel() { - this.valueModel.removePropertyChangeListener(PropertyValueModel.VALUE, this.valueListener); - } - - - // ********** property change support ********** - - /** - * The value of the wrapped value model has changed; - * propagate the change notification appropriately. - * @see #wrappedValueChanged(Object, Object) - * @see #wrappedValueChanged(Object) - */ - @SuppressWarnings("unchecked") - protected void wrappedValueChanged(PropertyChangeEvent event) { - this.wrappedValueChanged((V) event.getOldValue(), (V) event.getNewValue()); - } - - /** - * The value of the wrapped value model has changed; - * propagate the change notification appropriately. - * @see #wrappedValueChanged(PropertyChangeEvent) - * @see #wrappedValueChanged(Object) - */ - protected void wrappedValueChanged(@SuppressWarnings("unused") V oldValue, V newValue) { - this.wrappedValueChanged(newValue); - } - - /** - * The value of the wrapped value model has changed; - * propagate the change notification appropriately. - * @see #wrappedValueChanged(PropertyChangeEvent) - * @see #wrappedValueChanged(Object, Object) - */ - protected void wrappedValueChanged(@SuppressWarnings("unused") V newValue) { - throw new RuntimeException("This method was not overridden."); //$NON-NLS-1$ - } -} diff --git a/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/model/value/BufferedModifiablePropertyValueModelTests.java b/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/model/value/BufferedModifiablePropertyValueModelTests.java deleted file mode 100644 index fa7ed7c89e..0000000000 --- a/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/model/value/BufferedModifiablePropertyValueModelTests.java +++ /dev/null @@ -1,504 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007, 2012 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.tests.internal.model.value; - -import java.util.Date; -import junit.framework.TestCase; -import org.eclipse.jpt.common.utility.internal.model.AbstractModel; -import org.eclipse.jpt.common.utility.internal.model.value.BufferedModifiablePropertyValueModel; -import org.eclipse.jpt.common.utility.internal.model.value.PropertyAspectAdapter; -import org.eclipse.jpt.common.utility.internal.model.value.SimplePropertyValueModel; -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; - -@SuppressWarnings("nls") -public class BufferedModifiablePropertyValueModelTests - extends TestCase -{ - private Employee employee; - private ModifiablePropertyValueModel<Employee> employeeHolder; - PropertyChangeEvent employeeEvent; - - private ModifiablePropertyValueModel<Integer> idAdapter; - private ModifiablePropertyValueModel<String> nameAdapter; - private ModifiablePropertyValueModel<Date> hireDateAdapter; - PropertyChangeEvent adapterEvent; - - private BufferedModifiablePropertyValueModel.Trigger trigger; - private BufferedModifiablePropertyValueModel<Integer> bufferedIDHolder; - private BufferedModifiablePropertyValueModel<String> bufferedNameHolder; - private BufferedModifiablePropertyValueModel<Date> bufferedHireDateHolder; - PropertyChangeEvent bufferedEvent; - - public BufferedModifiablePropertyValueModelTests(String name) { - super(name); - } - - @Override - protected void setUp() throws Exception { - super.setUp(); - - this.employee = new Employee(17, "Freddy", new Date()); - this.employeeHolder = new SimplePropertyValueModel<Employee>(this.employee); - - this.trigger = new BufferedModifiablePropertyValueModel.Trigger(); - - this.idAdapter = this.buildIDAdapter(this.employeeHolder); - this.bufferedIDHolder = new BufferedModifiablePropertyValueModel<Integer>(this.idAdapter, this.trigger); - - this.nameAdapter = this.buildNameAdapter(this.employeeHolder); - this.bufferedNameHolder = new BufferedModifiablePropertyValueModel<String>(this.nameAdapter, this.trigger); - - this.hireDateAdapter = this.buildHireDateAdapter(this.employeeHolder); - this.bufferedHireDateHolder = new BufferedModifiablePropertyValueModel<Date>(this.hireDateAdapter, this.trigger); - } - - private ModifiablePropertyValueModel<Integer> buildIDAdapter(PropertyValueModel<Employee> eHolder) { - return new PropertyAspectAdapter<Employee, Integer>(eHolder, Employee.ID_PROPERTY) { - @Override - protected Integer buildValue_() { - return new Integer(this.subject.getID()); - } - @Override - protected void setValue_(Integer value) { - this.subject.setID(value.intValue()); - } - }; - } - - private ModifiablePropertyValueModel<String> buildNameAdapter(PropertyValueModel<Employee> eHolder) { - return new PropertyAspectAdapter<Employee, String>(eHolder, Employee.NAME_PROPERTY) { - @Override - protected String buildValue_() { - return this.subject.getName(); - } - @Override - protected void setValue_(String value) { - this.subject.setName(value); - } - }; - } - - private ModifiablePropertyValueModel<Date> buildHireDateAdapter(PropertyValueModel<Employee> eHolder) { - return new PropertyAspectAdapter<Employee, Date>(eHolder, Employee.HIRE_DATE_PROPERTY) { - @Override - protected Date buildValue_() { - return this.subject.getHireDate(); - } - @Override - protected void setValue_(Date value) { - this.subject.setHireDate(value); - } - }; - } - - @Override - protected void tearDown() throws Exception { - TestTools.clear(this); - super.tearDown(); - } - - public void testGetValue() { - PropertyChangeListener bufferedListener = this.buildBufferedListener(); - this.bufferedIDHolder.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); - this.bufferedNameHolder.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); - this.bufferedHireDateHolder.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); - - assertEquals(new Integer(17), this.idAdapter.getValue()); - assertEquals(new Integer(17), this.bufferedIDHolder.getValue()); - - assertEquals("Freddy", this.employee.getName()); - assertEquals("Freddy", this.nameAdapter.getValue()); - assertEquals("Freddy", this.bufferedNameHolder.getValue()); - - Date temp = this.employee.getHireDate(); - assertEquals(temp, this.employee.getHireDate()); - assertEquals(temp, this.hireDateAdapter.getValue()); - assertEquals(temp, this.bufferedHireDateHolder.getValue()); - - this.bufferedIDHolder.setValue(new Integer(323)); - assertEquals(17, this.employee.getID()); - assertEquals(new Integer(17), this.idAdapter.getValue()); - assertEquals(new Integer(323), this.bufferedIDHolder.getValue()); - - this.bufferedNameHolder.setValue("Ripley"); - assertEquals("Freddy", this.employee.getName()); - assertEquals("Freddy", this.nameAdapter.getValue()); - assertEquals("Ripley", this.bufferedNameHolder.getValue()); - - this.bufferedHireDateHolder.setValue(null); - assertEquals(temp, this.employee.getHireDate()); - assertEquals(temp, this.hireDateAdapter.getValue()); - assertEquals(null, this.bufferedHireDateHolder.getValue()); - } - - public void testTriggerAccept() { - PropertyChangeListener bufferedListener = this.buildBufferedListener(); - this.bufferedIDHolder.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); - this.bufferedNameHolder.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); - this.bufferedHireDateHolder.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); - - this.bufferedIDHolder.setValue(new Integer(323)); - assertEquals(17, this.employee.getID()); - assertEquals(new Integer(17), this.idAdapter.getValue()); - assertEquals(new Integer(323), this.bufferedIDHolder.getValue()); - - this.bufferedNameHolder.setValue("Ripley"); - assertEquals("Freddy", this.employee.getName()); - assertEquals("Freddy", this.nameAdapter.getValue()); - assertEquals("Ripley", this.bufferedNameHolder.getValue()); - - Date temp = this.employee.getHireDate(); - this.bufferedHireDateHolder.setValue(null); - assertEquals(temp, this.employee.getHireDate()); - assertEquals(temp, this.hireDateAdapter.getValue()); - assertEquals(null, this.bufferedHireDateHolder.getValue()); - - this.trigger.accept(); - - assertEquals(323, this.employee.getID()); - assertEquals(new Integer(323), this.idAdapter.getValue()); - assertEquals(new Integer(323), this.bufferedIDHolder.getValue()); - - assertEquals("Ripley", this.employee.getName()); - assertEquals("Ripley", this.nameAdapter.getValue()); - assertEquals("Ripley", this.bufferedNameHolder.getValue()); - - assertEquals(null, this.employee.getHireDate()); - assertEquals(null, this.hireDateAdapter.getValue()); - assertEquals(null, this.bufferedHireDateHolder.getValue()); - } - - public void testTriggerReset() { - PropertyChangeListener bufferedListener = this.buildBufferedListener(); - this.bufferedIDHolder.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); - this.bufferedNameHolder.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); - this.bufferedHireDateHolder.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); - - this.bufferedIDHolder.setValue(new Integer(323)); - assertEquals(17, this.employee.getID()); - assertEquals(new Integer(17), this.idAdapter.getValue()); - assertEquals(new Integer(323), this.bufferedIDHolder.getValue()); - - this.bufferedNameHolder.setValue("Ripley"); - assertEquals("Freddy", this.employee.getName()); - assertEquals("Freddy", this.nameAdapter.getValue()); - assertEquals("Ripley", this.bufferedNameHolder.getValue()); - - Date temp = this.employee.getHireDate(); - this.bufferedHireDateHolder.setValue(null); - assertEquals(temp, this.employee.getHireDate()); - assertEquals(temp, this.hireDateAdapter.getValue()); - assertEquals(null, this.bufferedHireDateHolder.getValue()); - - this.trigger.reset(); - - assertEquals(17, this.employee.getID()); - assertEquals(new Integer(17), this.idAdapter.getValue()); - assertEquals(new Integer(17), this.bufferedIDHolder.getValue()); - - assertEquals("Freddy", this.employee.getName()); - assertEquals("Freddy", this.nameAdapter.getValue()); - assertEquals("Freddy", this.bufferedNameHolder.getValue()); - - assertEquals(temp, this.employee.getHireDate()); - assertEquals(temp, this.hireDateAdapter.getValue()); - assertEquals(temp, this.bufferedHireDateHolder.getValue()); - } - - public void testLazyListening() { - assertTrue(((AbstractModel) this.bufferedIDHolder).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) this.bufferedNameHolder).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) this.bufferedHireDateHolder).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - - assertTrue(((AbstractModel) this.idAdapter).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) this.nameAdapter).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) this.hireDateAdapter).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - - assertTrue(this.employee.hasNoPropertyChangeListeners(Employee.ID_PROPERTY)); - assertTrue(this.employee.hasNoPropertyChangeListeners(Employee.NAME_PROPERTY)); - assertTrue(this.employee.hasNoPropertyChangeListeners(Employee.HIRE_DATE_PROPERTY)); - - PropertyChangeListener bufferedListener = this.buildBufferedListener(); - this.bufferedIDHolder.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); - this.bufferedNameHolder.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); - this.bufferedHireDateHolder.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); - - assertTrue(((AbstractModel) this.bufferedIDHolder).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) this.bufferedNameHolder).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) this.bufferedHireDateHolder).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); - - assertTrue(((AbstractModel) this.idAdapter).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) this.nameAdapter).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) this.hireDateAdapter).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); - - assertTrue(this.employee.hasAnyPropertyChangeListeners(Employee.ID_PROPERTY)); - assertTrue(this.employee.hasAnyPropertyChangeListeners(Employee.NAME_PROPERTY)); - assertTrue(this.employee.hasAnyPropertyChangeListeners(Employee.HIRE_DATE_PROPERTY)); - - this.bufferedIDHolder.removePropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); - this.bufferedNameHolder.removePropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); - this.bufferedHireDateHolder.removePropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); - - assertTrue(((AbstractModel) this.bufferedIDHolder).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) this.bufferedNameHolder).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) this.bufferedHireDateHolder).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - - assertTrue(((AbstractModel) this.idAdapter).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) this.nameAdapter).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - assertTrue(((AbstractModel) this.hireDateAdapter).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); - - assertTrue(this.employee.hasNoPropertyChangeListeners(Employee.ID_PROPERTY)); - assertTrue(this.employee.hasNoPropertyChangeListeners(Employee.NAME_PROPERTY)); - assertTrue(this.employee.hasNoPropertyChangeListeners(Employee.HIRE_DATE_PROPERTY)); - } - - public void testPropertyChange1() { - PropertyChangeListener bufferedListener = this.buildBufferedListener(); - this.bufferedNameHolder.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); - - PropertyChangeListener adapterListener = this.buildAdapterListener(); - this.nameAdapter.addPropertyChangeListener(PropertyValueModel.VALUE, adapterListener); - - PropertyChangeListener employeeListener = this.buildEmployeeListener(); - this.employee.addPropertyChangeListener(Employee.NAME_PROPERTY, employeeListener); - - this.verifyPropertyChanges(); - } - - public void testPropertyChange2() { - ChangeListener bufferedListener = this.buildBufferedListener(); - this.bufferedNameHolder.addChangeListener(bufferedListener); - - ChangeListener adapterListener = this.buildAdapterListener(); - this.nameAdapter.addChangeListener(adapterListener); - - ChangeListener employeeListener = this.buildEmployeeListener(); - this.employee.addChangeListener(employeeListener); - - this.verifyPropertyChanges(); - } - - private void verifyPropertyChanges() { - this.bufferedEvent = null; - this.adapterEvent = null; - this.employeeEvent = null; - this.bufferedNameHolder.setValue("Ripley"); - this.verifyEvent(this.bufferedEvent, this.bufferedNameHolder, PropertyValueModel.VALUE, "Freddy", "Ripley"); - assertNull(this.adapterEvent); - assertNull(this.employeeEvent); - - this.bufferedEvent = null; - this.adapterEvent = null; - this.employeeEvent = null; - this.bufferedNameHolder.setValue("Charlie"); - this.verifyEvent(this.bufferedEvent, this.bufferedNameHolder, PropertyValueModel.VALUE, "Ripley", "Charlie"); - assertNull(this.adapterEvent); - assertNull(this.employeeEvent); - - this.bufferedEvent = null; - this.adapterEvent = null; - this.employeeEvent = null; - this.trigger.accept(); - assertNull(this.bufferedEvent); - this.verifyEvent(this.adapterEvent, this.nameAdapter, PropertyValueModel.VALUE, "Freddy", "Charlie"); - this.verifyEvent(this.employeeEvent, this.employee, Employee.NAME_PROPERTY, "Freddy", "Charlie"); - - this.bufferedEvent = null; - this.adapterEvent = null; - this.employeeEvent = null; - this.bufferedNameHolder.setValue("Jason"); - this.verifyEvent(this.bufferedEvent, this.bufferedNameHolder, PropertyValueModel.VALUE, "Charlie", "Jason"); - assertNull(this.adapterEvent); - assertNull(this.employeeEvent); - - this.bufferedEvent = null; - this.adapterEvent = null; - this.employeeEvent = null; - this.trigger.reset(); - this.verifyEvent(this.bufferedEvent, this.bufferedNameHolder, PropertyValueModel.VALUE, "Jason", "Charlie"); - assertNull(this.adapterEvent); - assertNull(this.employeeEvent); - } - - /** - * changing the value should trigger buffering - */ - public void testBuffering1() { - PropertyChangeListener bufferedListener = this.buildBufferedListener(); - this.bufferedNameHolder.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); - - this.bufferedNameHolder.setValue("Ripley"); - assertEquals("Freddy", this.nameAdapter.getValue()); - assertEquals("Ripley", this.bufferedNameHolder.getValue()); - assertTrue(this.bufferedNameHolder.isBuffering()); - } - - /** - * setting to the same value should not trigger buffering (?) - */ - public void testBuffering2() { - PropertyChangeListener bufferedListener = this.buildBufferedListener(); - this.bufferedNameHolder.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); - - this.bufferedNameHolder.setValue("Freddy"); - assertEquals("Freddy", this.bufferedNameHolder.getValue()); - assertEquals("Freddy", this.nameAdapter.getValue()); - assertFalse(this.bufferedNameHolder.isBuffering()); - } - - /** - * setting to the original value should not trigger buffering (?) - */ - public void testBuffering3() { - PropertyChangeListener bufferedListener = this.buildBufferedListener(); - this.bufferedNameHolder.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); - - this.bufferedNameHolder.setValue("Ripley"); - assertEquals("Freddy", this.nameAdapter.getValue()); - assertEquals("Ripley", this.bufferedNameHolder.getValue()); - assertTrue(this.bufferedNameHolder.isBuffering()); - - this.bufferedNameHolder.setValue("Freddy"); - assertEquals("Freddy", this.nameAdapter.getValue()); - assertEquals("Freddy", this.bufferedNameHolder.getValue()); - assertFalse(this.bufferedNameHolder.isBuffering()); - } - - /** - * back-door changes are ignored - "Last One In Wins" - */ - public void testChangeConflict1() { - PropertyChangeListener bufferedListener = this.buildBufferedListener(); - this.bufferedNameHolder.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); - - this.bufferedNameHolder.setValue("Ripley"); - assertEquals("Freddy", this.employee.getName()); - assertEquals("Freddy", this.nameAdapter.getValue()); - assertEquals("Ripley", this.bufferedNameHolder.getValue()); - - this.nameAdapter.setValue("Jason"); - assertEquals("Jason", this.employee.getName()); - assertEquals("Jason", this.nameAdapter.getValue()); - assertEquals("Ripley", this.bufferedNameHolder.getValue()); - - this.trigger.accept(); - // "Jason" is dropped on the floor... - assertEquals("Ripley", this.employee.getName()); - assertEquals("Ripley", this.nameAdapter.getValue()); - assertEquals("Ripley", this.bufferedNameHolder.getValue()); - } - - /** - * back-door changes can de-activate buffering (?) - */ - public void testChangeConflict2() { - PropertyChangeListener bufferedListener = this.buildBufferedListener(); - this.bufferedNameHolder.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); - - this.bufferedNameHolder.setValue("Ripley"); - assertEquals("Freddy", this.employee.getName()); - assertEquals("Freddy", this.nameAdapter.getValue()); - assertEquals("Ripley", this.bufferedNameHolder.getValue()); - assertTrue(this.bufferedNameHolder.isBuffering()); - - this.nameAdapter.setValue("Ripley"); - assertEquals("Ripley", this.employee.getName()); - assertEquals("Ripley", this.nameAdapter.getValue()); - assertEquals("Ripley", this.bufferedNameHolder.getValue()); - assertFalse(this.bufferedNameHolder.isBuffering()); - } - - private ChangeListener buildBufferedListener() { - return new ChangeAdapter() { - @Override - public void propertyChanged(PropertyChangeEvent e) { - BufferedModifiablePropertyValueModelTests.this.bufferedEvent = e; - } - }; - } - - private ChangeListener buildAdapterListener() { - return new ChangeAdapter() { - @Override - public void propertyChanged(PropertyChangeEvent e) { - BufferedModifiablePropertyValueModelTests.this.adapterEvent = e; - } - }; - } - - private ChangeListener buildEmployeeListener() { - return new ChangeAdapter() { - @Override - public void propertyChanged(PropertyChangeEvent e) { - BufferedModifiablePropertyValueModelTests.this.employeeEvent = e; - } - }; - } - - private void verifyEvent(PropertyChangeEvent event, Object source, String propertyName, Object oldValue, Object newValue) { - assertEquals(source, event.getSource()); - assertEquals(propertyName, event.getPropertyName()); - assertEquals(oldValue, event.getOldValue()); - assertEquals(newValue, event.getNewValue()); - } - - - // ********** inner class ********** - - class Employee extends AbstractModel { - private int id; - public static final String ID_PROPERTY = "id"; - private String name; - public static final String NAME_PROPERTY = "name"; - private Date hireDate; - public static final String HIRE_DATE_PROPERTY = "hireDate"; - - Employee(int id, String name, Date hireDate) { - super(); - this.id = id; - this.name = name; - this.hireDate = hireDate; - } - int getID() { - return this.id; - } - void setID(int id) { - int old = this.id; - this.id = id; - this.firePropertyChanged(ID_PROPERTY, old, id); - } - String getName() { - return this.name; - } - void setName(String name) { - Object old = this.name; - this.name = name; - this.firePropertyChanged(NAME_PROPERTY, old, name); - } - Date getHireDate() { - return this.hireDate; - } - void setHireDate(Date hireDate) { - Object old = this.hireDate; - this.hireDate = hireDate; - this.firePropertyChanged(HIRE_DATE_PROPERTY, old, hireDate); - } - @Override - public void toString(StringBuilder sb) { - sb.append(this.name); - } - } -} diff --git a/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/model/value/BufferedPropertyValueModelTests.java b/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/model/value/BufferedPropertyValueModelTests.java new file mode 100644 index 0000000000..bf831c5293 --- /dev/null +++ b/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/model/value/BufferedPropertyValueModelTests.java @@ -0,0 +1,597 @@ +/******************************************************************************* + * Copyright (c) 2007, 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.tests.internal.model.value; + +import java.util.Date; +import org.eclipse.jpt.common.utility.Association; +import org.eclipse.jpt.common.utility.internal.ObjectTools; +import org.eclipse.jpt.common.utility.internal.model.AbstractModel; +import org.eclipse.jpt.common.utility.internal.model.value.BufferedPropertyValueModelAdapter; +import org.eclipse.jpt.common.utility.internal.model.value.PropertyAspectAdapter; +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.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; + +@SuppressWarnings("nls") +public class BufferedPropertyValueModelTests + extends TestCase +{ + private Employee employee; + private ModifiablePropertyValueModel<Employee> employeeModel; + PropertyChangeEvent employeeEvent; + + private ModifiablePropertyValueModel<Integer> idModel; + private ModifiablePropertyValueModel<String> nameModel; + private ModifiablePropertyValueModel<Date> hireDateModel; + PropertyChangeEvent adapterEvent; + + private BufferedPropertyValueModelAdapter.Trigger trigger; + + private ModifiablePropertyValueModel<Integer> bufferedIDModel; + + private ModifiablePropertyValueModel<String> bufferedNameModel; + private PropertyValueModel<Boolean> nameIsBufferingModel; + + private ModifiablePropertyValueModel<Date> bufferedHireDateModel; + + PropertyChangeEvent bufferedEvent; + + public BufferedPropertyValueModelTests(String name) { + super(name); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + + this.employee = new Employee(17, "Freddy", new Date()); + this.employeeModel = new SimplePropertyValueModel<>(this.employee); + + this.trigger = PropertyValueModelTools.bufferedPropertyValueModelAdapterTrigger(); + + this.idModel = this.buildIDModel(this.employeeModel); + Association<ModifiablePropertyValueModel<Integer>, PropertyValueModel<Boolean>> idAssociation = PropertyValueModelTools.buffer(this.idModel, this.trigger); + this.bufferedIDModel = idAssociation.getKey(); + + this.nameModel = this.buildNameModel(this.employeeModel); + Association<ModifiablePropertyValueModel<String>, PropertyValueModel<Boolean>> nameAssociation = PropertyValueModelTools.buffer(this.nameModel, this.trigger); + this.bufferedNameModel = nameAssociation.getKey(); + this.nameIsBufferingModel = nameAssociation.getValue(); + + this.hireDateModel = this.buildHireDateModel(this.employeeModel); + Association<ModifiablePropertyValueModel<Date>, PropertyValueModel<Boolean>> hireDateAssociation = PropertyValueModelTools.buffer(this.hireDateModel, this.trigger); + this.bufferedHireDateModel = hireDateAssociation.getKey(); + } + + private ModifiablePropertyValueModel<Integer> buildIDModel(PropertyValueModel<Employee> eHolder) { + return new PropertyAspectAdapter<Employee, Integer>(eHolder, Employee.ID_PROPERTY) { + @Override + protected Integer buildValue_() { + return new Integer(this.subject.getID()); + } + @Override + protected void setValue_(Integer value) { + this.subject.setID(value.intValue()); + } + }; + } + + private ModifiablePropertyValueModel<String> buildNameModel(PropertyValueModel<Employee> eHolder) { + return new PropertyAspectAdapter<Employee, String>(eHolder, Employee.NAME_PROPERTY) { + @Override + protected String buildValue_() { + return this.subject.getName(); + } + @Override + protected void setValue_(String value) { + this.subject.setName(value); + } + }; + } + + private ModifiablePropertyValueModel<Date> buildHireDateModel(PropertyValueModel<Employee> eHolder) { + return new PropertyAspectAdapter<Employee, Date>(eHolder, Employee.HIRE_DATE_PROPERTY) { + @Override + protected Date buildValue_() { + return this.subject.getHireDate(); + } + @Override + protected void setValue_(Date value) { + this.subject.setHireDate(value); + } + }; + } + + @Override + protected void tearDown() throws Exception { + TestTools.clear(this); + super.tearDown(); + } + + public void testGetValue() { + PropertyChangeListener bufferedListener = this.buildBufferedListener(); + this.bufferedIDModel.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); + this.bufferedNameModel.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); + this.bufferedHireDateModel.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); + + assertEquals(new Integer(17), this.idModel.getValue()); + assertEquals(new Integer(17), this.bufferedIDModel.getValue()); + + assertEquals("Freddy", this.employee.getName()); + assertEquals("Freddy", this.nameModel.getValue()); + assertEquals("Freddy", this.bufferedNameModel.getValue()); + + Date temp = this.employee.getHireDate(); + assertEquals(temp, this.employee.getHireDate()); + assertEquals(temp, this.hireDateModel.getValue()); + assertEquals(temp, this.bufferedHireDateModel.getValue()); + + this.bufferedIDModel.setValue(new Integer(323)); + assertEquals(17, this.employee.getID()); + assertEquals(new Integer(17), this.idModel.getValue()); + assertEquals(new Integer(323), this.bufferedIDModel.getValue()); + + this.bufferedNameModel.setValue("Ripley"); + assertEquals("Freddy", this.employee.getName()); + assertEquals("Freddy", this.nameModel.getValue()); + assertEquals("Ripley", this.bufferedNameModel.getValue()); + + this.bufferedHireDateModel.setValue(null); + assertEquals(temp, this.employee.getHireDate()); + assertEquals(temp, this.hireDateModel.getValue()); + assertEquals(null, this.bufferedHireDateModel.getValue()); + } + + public void testTriggerAccept() { + PropertyChangeListener bufferedListener = this.buildBufferedListener(); + this.bufferedIDModel.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); + this.bufferedNameModel.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); + this.bufferedHireDateModel.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); + + assertEquals(17, this.employee.getID()); + assertEquals(new Integer(17), this.idModel.getValue()); + assertEquals(new Integer(17), this.bufferedIDModel.getValue()); + + this.trigger.accept(); // NOP + + assertEquals(17, this.employee.getID()); + assertEquals(new Integer(17), this.idModel.getValue()); + assertEquals(new Integer(17), this.bufferedIDModel.getValue()); + + this.bufferedIDModel.setValue(new Integer(323)); + assertEquals(17, this.employee.getID()); + assertEquals(new Integer(17), this.idModel.getValue()); + assertEquals(new Integer(323), this.bufferedIDModel.getValue()); + + this.bufferedNameModel.setValue("Ripley"); + assertEquals("Freddy", this.employee.getName()); + assertEquals("Freddy", this.nameModel.getValue()); + assertEquals("Ripley", this.bufferedNameModel.getValue()); + + Date temp = this.employee.getHireDate(); + this.bufferedHireDateModel.setValue(null); + assertEquals(temp, this.employee.getHireDate()); + assertEquals(temp, this.hireDateModel.getValue()); + assertEquals(null, this.bufferedHireDateModel.getValue()); + + this.trigger.accept(); + + assertEquals(323, this.employee.getID()); + assertEquals(new Integer(323), this.idModel.getValue()); + assertEquals(new Integer(323), this.bufferedIDModel.getValue()); + + assertEquals("Ripley", this.employee.getName()); + assertEquals("Ripley", this.nameModel.getValue()); + assertEquals("Ripley", this.bufferedNameModel.getValue()); + + assertNull(this.employee.getHireDate()); + assertNull(this.hireDateModel.getValue()); + assertNull(this.bufferedHireDateModel.getValue()); + } + + public void testTriggerReset() { + PropertyChangeListener bufferedListener = this.buildBufferedListener(); + this.bufferedIDModel.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); + this.bufferedNameModel.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); + this.bufferedHireDateModel.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); + + assertEquals(17, this.employee.getID()); + assertEquals(new Integer(17), this.idModel.getValue()); + assertEquals(new Integer(17), this.bufferedIDModel.getValue()); + + this.trigger.reset(); // NOP + + assertEquals(17, this.employee.getID()); + assertEquals(new Integer(17), this.idModel.getValue()); + assertEquals(new Integer(17), this.bufferedIDModel.getValue()); + + this.bufferedIDModel.setValue(new Integer(323)); + assertEquals(17, this.employee.getID()); + assertEquals(new Integer(17), this.idModel.getValue()); + assertEquals(new Integer(323), this.bufferedIDModel.getValue()); + + this.bufferedNameModel.setValue("Ripley"); + assertEquals("Freddy", this.employee.getName()); + assertEquals("Freddy", this.nameModel.getValue()); + assertEquals("Ripley", this.bufferedNameModel.getValue()); + + Date temp = this.employee.getHireDate(); + this.bufferedHireDateModel.setValue(null); + assertEquals(temp, this.employee.getHireDate()); + assertEquals(temp, this.hireDateModel.getValue()); + assertEquals(null, this.bufferedHireDateModel.getValue()); + + this.trigger.reset(); + + assertEquals(17, this.employee.getID()); + assertEquals(new Integer(17), this.idModel.getValue()); + assertEquals(new Integer(17), this.bufferedIDModel.getValue()); + + assertEquals("Freddy", this.employee.getName()); + assertEquals("Freddy", this.nameModel.getValue()); + assertEquals("Freddy", this.bufferedNameModel.getValue()); + + assertEquals(temp, this.employee.getHireDate()); + assertEquals(temp, this.hireDateModel.getValue()); + assertEquals(temp, this.bufferedHireDateModel.getValue()); + } + + public void testLazyListening() { + assertTrue(((AbstractModel) this.bufferedIDModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); + assertTrue(((AbstractModel) this.bufferedNameModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); + assertTrue(((AbstractModel) this.bufferedHireDateModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); + + assertTrue(((AbstractModel) this.idModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); + assertTrue(((AbstractModel) this.nameModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); + assertTrue(((AbstractModel) this.hireDateModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); + + assertTrue(this.employee.hasNoPropertyChangeListeners(Employee.ID_PROPERTY)); + assertTrue(this.employee.hasNoPropertyChangeListeners(Employee.NAME_PROPERTY)); + assertTrue(this.employee.hasNoPropertyChangeListeners(Employee.HIRE_DATE_PROPERTY)); + + PropertyChangeListener bufferedListener = this.buildBufferedListener(); + this.bufferedIDModel.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); + this.bufferedNameModel.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); + this.bufferedHireDateModel.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); + + assertTrue(((AbstractModel) this.bufferedIDModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); + assertTrue(((AbstractModel) this.bufferedNameModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); + assertTrue(((AbstractModel) this.bufferedHireDateModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); + + assertTrue(((AbstractModel) this.idModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); + assertTrue(((AbstractModel) this.nameModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); + assertTrue(((AbstractModel) this.hireDateModel).hasAnyPropertyChangeListeners(PropertyValueModel.VALUE)); + + assertTrue(this.employee.hasAnyPropertyChangeListeners(Employee.ID_PROPERTY)); + assertTrue(this.employee.hasAnyPropertyChangeListeners(Employee.NAME_PROPERTY)); + assertTrue(this.employee.hasAnyPropertyChangeListeners(Employee.HIRE_DATE_PROPERTY)); + + this.bufferedIDModel.removePropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); + this.bufferedNameModel.removePropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); + this.bufferedHireDateModel.removePropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); + + assertTrue(((AbstractModel) this.bufferedIDModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); + assertTrue(((AbstractModel) this.bufferedNameModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); + assertTrue(((AbstractModel) this.bufferedHireDateModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); + + assertTrue(((AbstractModel) this.idModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); + assertTrue(((AbstractModel) this.nameModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); + assertTrue(((AbstractModel) this.hireDateModel).hasNoPropertyChangeListeners(PropertyValueModel.VALUE)); + + assertTrue(this.employee.hasNoPropertyChangeListeners(Employee.ID_PROPERTY)); + assertTrue(this.employee.hasNoPropertyChangeListeners(Employee.NAME_PROPERTY)); + assertTrue(this.employee.hasNoPropertyChangeListeners(Employee.HIRE_DATE_PROPERTY)); + } + + public void testPropertyChange1() { + PropertyChangeListener bufferedListener = this.buildBufferedListener(); + this.bufferedNameModel.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); + + PropertyChangeListener adapterListener = this.buildAdapterListener(); + this.nameModel.addPropertyChangeListener(PropertyValueModel.VALUE, adapterListener); + + PropertyChangeListener employeeListener = this.buildEmployeeListener(); + this.employee.addPropertyChangeListener(Employee.NAME_PROPERTY, employeeListener); + + this.verifyPropertyChanges(); + } + + public void testPropertyChange2() { + ChangeListener bufferedListener = this.buildBufferedListener(); + this.bufferedNameModel.addChangeListener(bufferedListener); + + ChangeListener adapterListener = this.buildAdapterListener(); + this.nameModel.addChangeListener(adapterListener); + + ChangeListener employeeListener = this.buildEmployeeListener(); + this.employee.addChangeListener(employeeListener); + + this.verifyPropertyChanges(); + } + + private void verifyPropertyChanges() { + this.bufferedEvent = null; + this.adapterEvent = null; + this.employeeEvent = null; + this.bufferedNameModel.setValue("Ripley"); + this.verifyEvent(this.bufferedEvent, this.bufferedNameModel, PropertyValueModel.VALUE, "Freddy", "Ripley"); + assertNull(this.adapterEvent); + assertNull(this.employeeEvent); + + this.bufferedEvent = null; + this.adapterEvent = null; + this.employeeEvent = null; + this.bufferedNameModel.setValue("Charlie"); + this.verifyEvent(this.bufferedEvent, this.bufferedNameModel, PropertyValueModel.VALUE, "Ripley", "Charlie"); + assertNull(this.adapterEvent); + assertNull(this.employeeEvent); + + this.bufferedEvent = null; + this.adapterEvent = null; + this.employeeEvent = null; + this.trigger.accept(); + assertNull(this.bufferedEvent); + this.verifyEvent(this.adapterEvent, this.nameModel, PropertyValueModel.VALUE, "Freddy", "Charlie"); + this.verifyEvent(this.employeeEvent, this.employee, Employee.NAME_PROPERTY, "Freddy", "Charlie"); + + this.bufferedEvent = null; + this.adapterEvent = null; + this.employeeEvent = null; + this.bufferedNameModel.setValue("Jason"); + this.verifyEvent(this.bufferedEvent, this.bufferedNameModel, PropertyValueModel.VALUE, "Charlie", "Jason"); + assertNull(this.adapterEvent); + assertNull(this.employeeEvent); + + this.bufferedEvent = null; + this.adapterEvent = null; + this.employeeEvent = null; + this.trigger.reset(); + this.verifyEvent(this.bufferedEvent, this.bufferedNameModel, PropertyValueModel.VALUE, "Jason", "Charlie"); + assertNull(this.adapterEvent); + assertNull(this.employeeEvent); + } + + /** + * changing the value should trigger buffering + */ + public void testBuffering1() { + PropertyChangeListener bufferedListener = this.buildBufferedListener(); + this.bufferedNameModel.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); + + this.bufferedNameModel.setValue("Ripley"); + assertEquals("Freddy", this.nameModel.getValue()); + assertEquals("Ripley", this.bufferedNameModel.getValue()); + assertTrue(this.nameIsBufferingModel.getValue().booleanValue()); + } + + /** + * setting to the same value should not trigger buffering (?) + */ + public void testBuffering2() { + PropertyChangeListener bufferedListener = this.buildBufferedListener(); + this.bufferedNameModel.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); + + this.bufferedNameModel.setValue("Freddy"); + assertEquals("Freddy", this.bufferedNameModel.getValue()); + assertEquals("Freddy", this.nameModel.getValue()); + assertFalse(this.nameIsBufferingModel.getValue().booleanValue()); + } + + /** + * setting to the original value should not trigger buffering (?) + */ + public void testBuffering3() { + PropertyChangeListener bufferedListener = this.buildBufferedListener(); + this.bufferedNameModel.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); + + this.bufferedNameModel.setValue("Ripley"); + assertEquals("Freddy", this.nameModel.getValue()); + assertEquals("Ripley", this.bufferedNameModel.getValue()); + assertTrue(this.nameIsBufferingModel.getValue().booleanValue()); + + this.bufferedNameModel.setValue("Freddy"); + assertEquals("Freddy", this.nameModel.getValue()); + assertEquals("Freddy", this.bufferedNameModel.getValue()); + assertFalse(this.nameIsBufferingModel.getValue().booleanValue()); + } + + /** + * back-door changes are ignored - "Last One In Wins" + */ + public void testChangeConflict1() { + PropertyChangeListener bufferedListener = this.buildBufferedListener(); + this.bufferedNameModel.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); + + this.bufferedNameModel.setValue("Ripley"); + assertEquals("Freddy", this.employee.getName()); + assertEquals("Freddy", this.nameModel.getValue()); + assertEquals("Ripley", this.bufferedNameModel.getValue()); + + this.nameModel.setValue("Jason"); + assertEquals("Jason", this.employee.getName()); + assertEquals("Jason", this.nameModel.getValue()); + assertEquals("Ripley", this.bufferedNameModel.getValue()); + + this.trigger.accept(); + // "Jason" is dropped on the floor... + assertEquals("Ripley", this.employee.getName()); + assertEquals("Ripley", this.nameModel.getValue()); + assertEquals("Ripley", this.bufferedNameModel.getValue()); + } + + /** + * back-door changes can de-activate buffering (?) + */ + public void testChangeConflict2() { + PropertyChangeListener bufferedListener = this.buildBufferedListener(); + this.bufferedNameModel.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); + + this.bufferedNameModel.setValue("Ripley"); + assertEquals("Freddy", this.employee.getName()); + assertEquals("Freddy", this.nameModel.getValue()); + assertEquals("Ripley", this.bufferedNameModel.getValue()); + assertTrue(this.nameIsBufferingModel.getValue().booleanValue()); + + this.nameModel.setValue("Ripley"); + assertEquals("Ripley", this.employee.getName()); + assertEquals("Ripley", this.nameModel.getValue()); + assertEquals("Ripley", this.bufferedNameModel.getValue()); + assertFalse(this.nameIsBufferingModel.getValue().booleanValue()); + } + + /** + * back-door change when not buffering + */ + public void testChangeConflict3() { + PropertyChangeListener bufferedListener = this.buildBufferedListener(); + this.bufferedNameModel.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); + + this.nameModel.setValue("Ripley"); + assertEquals("Ripley", this.employee.getName()); + assertEquals("Ripley", this.nameModel.getValue()); + assertEquals("Ripley", this.bufferedNameModel.getValue()); + assertEquals("Ripley", this.bufferedEvent.getNewValue()); + assertFalse(this.nameIsBufferingModel.getValue().booleanValue()); + } + + public void testAdapterToString() { + PropertyChangeListener bufferedListener = this.buildBufferedListener(); + this.bufferedNameModel.addPropertyChangeListener(PropertyValueModel.VALUE, bufferedListener); + + Object adapter = ObjectTools.get(this.bufferedNameModel, "adapter"); + String s = adapter.toString(); + assertTrue(s.contains("(Freddy)")); + + this.bufferedNameModel.setValue("Ripley"); + assertEquals("Freddy", this.employee.getName()); + assertEquals("Freddy", this.nameModel.getValue()); + assertEquals("Ripley", this.bufferedNameModel.getValue()); + assertTrue(this.nameIsBufferingModel.getValue().booleanValue()); + + s = adapter.toString(); + assertTrue(s.contains("(Ripley [Freddy])")); + } + + public void testTriggerToString() { + assertNotNull(this.trigger.toString()); + } + + public void testFactoryCtor_NPE1() { + boolean exCaught = false; + try { + Association<ModifiablePropertyValueModel<Integer>, PropertyValueModel<Boolean>> association = PropertyValueModelTools.buffer(null, this.trigger); + fail("bogus: " + association); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testFactoryCtor_NPE2() { + boolean exCaught = false; + try { + Association<ModifiablePropertyValueModel<Integer>, PropertyValueModel<Boolean>> association = PropertyValueModelTools.buffer(this.idModel, null); + fail("bogus: " + association); + } catch (NullPointerException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + private ChangeListener buildBufferedListener() { + return new ChangeAdapter() { + @Override + public void propertyChanged(PropertyChangeEvent e) { + BufferedPropertyValueModelTests.this.bufferedEvent = e; + } + }; + } + + private ChangeListener buildAdapterListener() { + return new ChangeAdapter() { + @Override + public void propertyChanged(PropertyChangeEvent e) { + BufferedPropertyValueModelTests.this.adapterEvent = e; + } + }; + } + + private ChangeListener buildEmployeeListener() { + return new ChangeAdapter() { + @Override + public void propertyChanged(PropertyChangeEvent e) { + BufferedPropertyValueModelTests.this.employeeEvent = e; + } + }; + } + + private void verifyEvent(PropertyChangeEvent event, Object source, String propertyName, Object oldValue, Object newValue) { + assertEquals(source, event.getSource()); + assertEquals(propertyName, event.getPropertyName()); + assertEquals(oldValue, event.getOldValue()); + assertEquals(newValue, event.getNewValue()); + } + + + // ********** Employee ********** + + class Employee + extends AbstractModel + { + private int id; + public static final String ID_PROPERTY = "id"; + private String name; + public static final String NAME_PROPERTY = "name"; + private Date hireDate; + public static final String HIRE_DATE_PROPERTY = "hireDate"; + + Employee(int id, String name, Date hireDate) { + super(); + this.id = id; + this.name = name; + this.hireDate = hireDate; + } + int getID() { + return this.id; + } + void setID(int id) { + int old = this.id; + this.id = id; + this.firePropertyChanged(ID_PROPERTY, old, id); + } + String getName() { + return this.name; + } + void setName(String name) { + Object old = this.name; + this.name = name; + this.firePropertyChanged(NAME_PROPERTY, old, name); + } + Date getHireDate() { + return this.hireDate; + } + void setHireDate(Date hireDate) { + Object old = this.hireDate; + this.hireDate = hireDate; + this.firePropertyChanged(HIRE_DATE_PROPERTY, old, hireDate); + } + @Override + public void toString(StringBuilder sb) { + sb.append(this.name); + } + } +} diff --git a/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/model/value/JptCommonUtilityModelValueTests.java b/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/model/value/JptCommonUtilityModelValueTests.java index 3a84dc44ef..be6e0220b3 100644 --- a/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/model/value/JptCommonUtilityModelValueTests.java +++ b/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/model/value/JptCommonUtilityModelValueTests.java @@ -22,7 +22,7 @@ public class JptCommonUtilityModelValueTests { suite.addTest(JptCommonUtilityModelValuePrefsTests.suite()); suite.addTest(JptCommonUtilityModelValueSwingTests.suite()); - suite.addTestSuite(BufferedModifiablePropertyValueModelTests.class); + suite.addTestSuite(BufferedPropertyValueModelTests.class); suite.addTestSuite(CachingTransformationPropertyValueModelTests.class); suite.addTestSuite(CollectionAspectAdapterTests.class); suite.addTestSuite(CollectionListValueModelAdapterTests.class); diff --git a/jaxb/plugins/org.eclipse.jpt.jaxb.ui/src/org/eclipse/jpt/jaxb/ui/internal/properties/JaxbProjectPropertiesPage.java b/jaxb/plugins/org.eclipse.jpt.jaxb.ui/src/org/eclipse/jpt/jaxb/ui/internal/properties/JaxbProjectPropertiesPage.java index 0d932c884d..3288b65f2a 100644 --- a/jaxb/plugins/org.eclipse.jpt.jaxb.ui/src/org/eclipse/jpt/jaxb/ui/internal/properties/JaxbProjectPropertiesPage.java +++ b/jaxb/plugins/org.eclipse.jpt.jaxb.ui/src/org/eclipse/jpt/jaxb/ui/internal/properties/JaxbProjectPropertiesPage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2013 Oracle. All rights reserved. + * Copyright (c) 2007, 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. @@ -19,11 +19,12 @@ import org.eclipse.jpt.common.core.internal.utility.ICUStringCollator; import org.eclipse.jpt.common.ui.internal.WorkbenchTools; import org.eclipse.jpt.common.ui.internal.properties.JptProjectPropertiesPage; import org.eclipse.jpt.common.ui.internal.swt.bindings.SWTBindingTools; +import org.eclipse.jpt.common.utility.Association; import org.eclipse.jpt.common.utility.internal.iterable.IterableTools; import org.eclipse.jpt.common.utility.internal.model.value.AspectPropertyValueModelAdapter; -import org.eclipse.jpt.common.utility.internal.model.value.BufferedModifiablePropertyValueModel; import org.eclipse.jpt.common.utility.internal.model.value.CompositeCollectionValueModel; import org.eclipse.jpt.common.utility.internal.model.value.PropertyCollectionValueModelAdapter; +import org.eclipse.jpt.common.utility.internal.model.value.PropertyValueModelTools; import org.eclipse.jpt.common.utility.internal.model.value.SetCollectionValueModel; import org.eclipse.jpt.common.utility.internal.model.value.SortedListValueModelAdapter; import org.eclipse.jpt.common.utility.internal.model.value.StaticCollectionValueModel; @@ -33,6 +34,7 @@ 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.CollectionValueModel; import org.eclipse.jpt.common.utility.model.value.ListValueModel; +import org.eclipse.jpt.common.utility.model.value.ModifiablePropertyValueModel; import org.eclipse.jpt.common.utility.model.value.PropertyValueModel; import org.eclipse.jpt.jaxb.core.JaxbPreferences; import org.eclipse.jpt.jaxb.core.JaxbProject; @@ -66,7 +68,8 @@ public class JaxbProjectPropertiesPage private PropertyValueModel<JaxbProject> jaxbProjectModel; - private BufferedModifiablePropertyValueModel<JaxbPlatformConfig> platformModel; + private ModifiablePropertyValueModel<JaxbPlatformConfig> platformModel; + private PropertyValueModel<Boolean> platformModelBufferingFlag; private PropertyChangeListener platformListener; /* private */ static final Comparator<String> STRING_COMPARATOR = new ICUStringCollator(); @@ -82,16 +85,17 @@ public class JaxbProjectPropertiesPage protected void buildModels() { this.jaxbProjectModel = new JaxbProjectModel(this.projectModel); - this.platformModel = this.buildPlatformModel(); + Association<ModifiablePropertyValueModel<JaxbPlatformConfig>, PropertyValueModel<Boolean>> platformAssoc = this.buildPlatformModel(); + this.platformModel = platformAssoc.getKey(); + this.platformModelBufferingFlag = platformAssoc.getValue(); this.platformListener = this.buildPlatformListener(); } // ***** platform ID model - private BufferedModifiablePropertyValueModel<JaxbPlatformConfig> buildPlatformModel() { - return new BufferedModifiablePropertyValueModel<JaxbPlatformConfig>( - new PlatformModel(this.jaxbProjectModel), this.trigger); + private Association<ModifiablePropertyValueModel<JaxbPlatformConfig>, PropertyValueModel<Boolean>> buildPlatformModel() { + return PropertyValueModelTools.buffer(new PlatformModel(this.jaxbProjectModel), this.trigger); } private PropertyChangeListener buildPlatformListener(){ @@ -134,8 +138,7 @@ public class JaxbProjectPropertiesPage protected void adjustLibraryProviders() { LibraryInstallDelegate lid = this.getLibraryInstallDelegate(); if (lid != null) { - List<JaxbLibraryProviderInstallOperationConfig> jaxbConfigs - = new ArrayList<JaxbLibraryProviderInstallOperationConfig>(); + List<JaxbLibraryProviderInstallOperationConfig> jaxbConfigs = new ArrayList<>(); // add the currently selected one first JaxbLibraryProviderInstallOperationConfig currentJaxbConfig = null; LibraryProviderOperationConfig config = lid.getLibraryProviderOperationConfig(); @@ -216,10 +219,10 @@ public class JaxbProjectPropertiesPage */ @SuppressWarnings("unchecked") private ListValueModel<JaxbPlatformConfig> buildPlatformChoicesModel() { - return new SortedListValueModelAdapter<JaxbPlatformConfig>( - new SetCollectionValueModel<JaxbPlatformConfig>( + return new SortedListValueModelAdapter<>( + new SetCollectionValueModel<>( CompositeCollectionValueModel.forModels( - new PropertyCollectionValueModelAdapter<JaxbPlatformConfig>(this.platformModel), + new PropertyCollectionValueModelAdapter<>(this.platformModel), buildRegistryPlatformsModel())), JAXB_PLATFORM_CONFIG_COMPARATOR); } @@ -229,7 +232,7 @@ public class JaxbProjectPropertiesPage IterableTools.filter( this.getJaxbPlatformConfigs(), new JaxbPlatformConfig.SupportsJaxbFacetVersion(getProjectFacetVersion())); - return new StaticCollectionValueModel<JaxbPlatformConfig>(enabledPlatforms); + return new StaticCollectionValueModel<>(enabledPlatforms); } private Iterable<JaxbPlatformConfig> getJaxbPlatformConfigs() { @@ -249,7 +252,7 @@ public class JaxbProjectPropertiesPage @Override protected boolean projectRebuildRequired() { - return this.platformModel.isBuffering(); + return this.platformModelBufferingFlag.getValue().booleanValue(); } @Override @@ -262,9 +265,10 @@ public class JaxbProjectPropertiesPage } @Override - protected BufferedModifiablePropertyValueModel<?>[] buildBufferedModels() { - return new BufferedModifiablePropertyValueModel[] { - this.platformModel + @SuppressWarnings("unchecked") + protected PropertyValueModel<Boolean>[] buildBufferingFlags() { + return new PropertyValueModel[] { + this.platformModelBufferingFlag }; } diff --git a/jaxb/plugins/org.eclipse.jpt.jaxb.ui/src/org/eclipse/jpt/jaxb/ui/internal/properties/JaxbSchemasPropertiesPage.java b/jaxb/plugins/org.eclipse.jpt.jaxb.ui/src/org/eclipse/jpt/jaxb/ui/internal/properties/JaxbSchemasPropertiesPage.java index 3d7f2e830c..03d93ed94d 100644 --- a/jaxb/plugins/org.eclipse.jpt.jaxb.ui/src/org/eclipse/jpt/jaxb/ui/internal/properties/JaxbSchemasPropertiesPage.java +++ b/jaxb/plugins/org.eclipse.jpt.jaxb.ui/src/org/eclipse/jpt/jaxb/ui/internal/properties/JaxbSchemasPropertiesPage.java @@ -55,9 +55,10 @@ import org.eclipse.jpt.common.utility.internal.collection.CollectionTools; import org.eclipse.jpt.common.utility.internal.iterable.SingleElementIterable; import org.eclipse.jpt.common.utility.internal.model.AbstractModel; import org.eclipse.jpt.common.utility.internal.model.value.AspectAdapter; -import org.eclipse.jpt.common.utility.internal.model.value.BufferedModifiablePropertyValueModel; +import org.eclipse.jpt.common.utility.internal.model.value.BufferedPropertyValueModelAdapter; import org.eclipse.jpt.common.utility.internal.model.value.CollectionValueModelTools; import org.eclipse.jpt.common.utility.internal.model.value.PropertyAspectAdapter; +import org.eclipse.jpt.common.utility.internal.model.value.PropertyValueModelTools; import org.eclipse.jpt.common.utility.internal.model.value.SimpleCollectionValueModel; import org.eclipse.jpt.common.utility.internal.model.value.SimplePropertyValueModel; import org.eclipse.jpt.common.utility.internal.model.value.SortedListValueModelAdapter; @@ -108,7 +109,7 @@ public class JaxbSchemasPropertiesPage private final PropertyValueModel<JaxbProject> jaxbProjectModel; - protected final BufferedModifiablePropertyValueModel.Trigger trigger; + protected final BufferedPropertyValueModelAdapter.Trigger trigger; private final SchemasModel schemasModel; @@ -118,11 +119,11 @@ public class JaxbSchemasPropertiesPage public JaxbSchemasPropertiesPage() { super(); this.resourceManager = this.buildResourceManager(); - this.projectModel = new SimplePropertyValueModel<IProject>(); + this.projectModel = new SimplePropertyValueModel<>(); this.jaxbProjectModel = new JaxbProjectModel(this.projectModel); - this.trigger = new BufferedModifiablePropertyValueModel.Trigger(); + this.trigger = PropertyValueModelTools.bufferedPropertyValueModelAdapterTrigger(); this.schemasModel = new SchemasModel(this.jaxbProjectModel, this.trigger); - this.schemasSelectionModel = new SimpleCollectionValueModel<Schema>(); + this.schemasSelectionModel = new SimpleCollectionValueModel<>(); setDescription(JptJaxbUiMessages.SCHEMAS_PAGE_DESCRIPTION); } @@ -198,7 +199,7 @@ public class JaxbSchemasPropertiesPage // create the table TableViewer schemasTable = new TableViewer(tableComposite, SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI); TableModelAdapter.adapt( - new SortedListValueModelAdapter<Schema>(this.schemasModel), + new SortedListValueModelAdapter<>(this.schemasModel), this.schemasSelectionModel, schemasTable.getTable(), new SchemaColumnAdapter(), @@ -274,7 +275,7 @@ public class JaxbSchemasPropertiesPage } - private void addSchema() { + void addSchema() { // constructs a dialog for editing the new schema namespace and location AddEditSchemaDialog dialog = new AddEditSchemaDialog( @@ -292,14 +293,14 @@ public class JaxbSchemasPropertiesPage Schema schema = this.schemasModel.addSchema(dialog.getNamespace(), dialog.getLocation()); // select the new schema - this.schemasSelectionModel.setValues(new SingleElementIterable<Schema>(schema)); + this.schemasSelectionModel.setValues(new SingleElementIterable<>(schema)); } private PropertyValueModel<Boolean> buildEditEnabledModel() { return CollectionValueModelTools.containsSingleElementPropertyValueModel(this.schemasSelectionModel); } - private void editSelectedSchema() { + void editSelectedSchema() { // constructs a dialog for editing the new schema namespace and location final Schema schema = this.schemasSelectionModel.iterator().next(); AddEditSchemaDialog dialog = @@ -323,7 +324,7 @@ public class JaxbSchemasPropertiesPage return CollectionValueModelTools.isNotEmptyPropertyValueModel(this.schemasSelectionModel); } - private void removeSelectedSchemas() { + void removeSelectedSchemas() { this.schemasModel.removeSchemas(this.schemasSelectionModel); } @@ -436,7 +437,8 @@ public class JaxbSchemasPropertiesPage static class SchemasModel extends AspectAdapter<JaxbProject, Collection<Schema>> - implements CollectionValueModel<Schema> { + implements CollectionValueModel<Schema>, BufferedPropertyValueModelAdapter.Trigger.Listener + { /** * The collection of schemas @@ -447,64 +449,45 @@ public class JaxbSchemasPropertiesPage * This is the trigger that indicates whether the buffered value * should be accepted or reset. */ - protected final PropertyValueModel<Boolean> triggerHolder; + protected final BufferedPropertyValueModelAdapter.Trigger trigger; - /** This listens to the trigger holder. */ - protected final PropertyChangeListener triggerChangeListener; - - SchemasModel(PropertyValueModel<JaxbProject> subjectHolder, PropertyValueModel<Boolean> triggerHolder) { - super(subjectHolder); - this.schemas = new ArrayList<Schema>(); - this.triggerHolder = triggerHolder; - this.triggerChangeListener = buildTriggerChangeListener(); - } - - - protected PropertyChangeListener buildTriggerChangeListener() { - return new PropertyChangeListener() { - public void propertyChanged(PropertyChangeEvent event) { - triggerChanged(event); - } - }; + SchemasModel(PropertyValueModel<JaxbProject> projectModel, BufferedPropertyValueModelAdapter.Trigger trigger) { + super(projectModel); + this.schemas = new ArrayList<>(); + this.trigger = trigger; } protected Collection<Schema> buildSchemas_() { - ArrayList<Schema> schemas = new ArrayList<Schema>(); + ArrayList<Schema> result = new ArrayList<>(); for (SchemaEntry entry : this.subject.getSchemaLibrary().getSchemaEntries()) { - schemas.add(new Schema(entry.getNamespace(), entry.getLocation())); + result.add(new Schema(entry.getNamespace(), entry.getLocation())); } - return schemas; + return result; } public boolean hasChanges() { - return (this.subject == null) ? false : ! this.schemas.equals(buildSchemas_()); - } - - protected void triggerChanged(PropertyChangeEvent event) { - if (hasChanges()) { - if (this.subject != null && ((Boolean) event.getNewValue()).booleanValue()) { - this.accept(); - } else { - this.reset(); - } - } + return (this.subject != null) && ! this.schemas.equals(buildSchemas_()); } public void accept() { - List<String> schemaLocations = new Vector<String>(); - for (Schema schema : this.schemas) { - schemaLocations.add(schema.getLocation()); + if (this.hasChanges()) { + List<String> schemaLocations = new Vector<>(); + for (Schema schema : this.schemas) { + schemaLocations.add(schema.getLocation()); + } + this.subject.getSchemaLibrary().setSchemaLocations(schemaLocations); } - this.subject.getSchemaLibrary().setSchemaLocations(schemaLocations); } public void reset() { - this.schemas.clear(); - if (this.subject != null) { - this.schemas.addAll(buildSchemas_()); + if (this.hasChanges()) { + this.schemas.clear(); + if (this.subject != null) { + this.schemas.addAll(buildSchemas_()); + } + fireCollectionChanged(VALUES, getAspectValue()); } - fireCollectionChanged(VALUES, getAspectValue()); } public Schema addSchema(String namespace, String location) { @@ -513,8 +496,8 @@ public class JaxbSchemasPropertiesPage return schema; } - public void removeSchemas(Iterable<Schema> schemas) { - removeItemsFromCollection(schemas, this.schemas, VALUES); + public void removeSchemas(Iterable<Schema> items) { + removeItemsFromCollection(items, this.schemas, VALUES); } @@ -537,7 +520,7 @@ public class JaxbSchemasPropertiesPage @Override protected void fireAspectChanged(Collection<Schema> oldValue, Collection<Schema> newValue) { - this.synchronizeCollection(newValue, new ArrayList<Schema>(oldValue), VALUES); + this.synchronizeCollection(newValue, new ArrayList<>(oldValue), VALUES); } @Override @@ -553,12 +536,12 @@ public class JaxbSchemasPropertiesPage @Override protected void engageModels() { super.engageModels(); - this.triggerHolder.addPropertyChangeListener(PropertyValueModel.VALUE, this.triggerChangeListener); + this.trigger.addListener(this); } @Override protected void disengageModels() { - this.triggerHolder.removePropertyChangeListener(PropertyValueModel.VALUE, this.triggerChangeListener); + this.trigger.removeListener(this); super.disengageModels(); } @@ -733,9 +716,9 @@ public class JaxbSchemasPropertiesPage private String defaultMessage; - private final ModifiablePropertyValueModel<String> location; + private final ModifiablePropertyValueModel<String> locationModel; - private final ModifiablePropertyValueModel<String> namespace; + private final ModifiablePropertyValueModel<String> namespaceModel; private XSDSchema resolvedSchema; @@ -749,19 +732,19 @@ public class JaxbSchemasPropertiesPage this.resourceManager = resourceManager; this.currentSchema = currentSchema; this.allSchemas = allSchemas; - this.location = new SimplePropertyValueModel<String>(); - this.namespace = new SimplePropertyValueModel<String>(); + this.locationModel = new SimplePropertyValueModel<>(); + this.namespaceModel = new SimplePropertyValueModel<>(); this.mode = (this.currentSchema == null) ? Mode.ADD : Mode.EDIT; if (this.mode == Mode.ADD) { this.defaultMessage = JptJaxbUiMessages.SCHEMAS_PAGE_ADD_SCHEMA_MESSAGE; - this.location.setValue(null); - this.namespace.setValue(null); + this.locationModel.setValue(null); + this.namespaceModel.setValue(null); } else { this.defaultMessage = JptJaxbUiMessages.SCHEMAS_PAGE_EDIT_SCHEMA_MESSAGE; - this.location.setValue(currentSchema.getLocation()); - this.namespace.setValue(currentSchema.getNamespace()); + this.locationModel.setValue(currentSchema.getLocation()); + this.namespaceModel.setValue(currentSchema.getNamespace()); } } @@ -779,7 +762,7 @@ public class JaxbSchemasPropertiesPage @Override protected Control createDialogArea(Composite parent) { - Composite dialogArea = (Composite) super.createDialogArea(parent); + Composite da = (Composite) super.createDialogArea(parent); setMessage(this.defaultMessage); if (this.mode == Mode.ADD) { @@ -789,7 +772,7 @@ public class JaxbSchemasPropertiesPage setTitle(JptJaxbUiMessages.SCHEMAS_PAGE_EDIT_SCHEMA_TITLE); } - Composite composite = new Composite(dialogArea, SWT.NONE); + Composite composite = new Composite(da, SWT.NONE); composite.setLayout(new GridLayout(3, false)); composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); @@ -801,7 +784,7 @@ public class JaxbSchemasPropertiesPage locationText.setText(locationDisplayString()); locationText.setEditable(false); locationText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); - this.location.addPropertyChangeListener( + this.locationModel.addPropertyChangeListener( PropertyValueModel.VALUE, new PropertyChangeListener() { public void propertyChanged(PropertyChangeEvent event) { @@ -831,7 +814,7 @@ public class JaxbSchemasPropertiesPage namespaceText.setText(namespaceDisplayString()); namespaceText.setEditable(false); namespaceText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); - this.namespace.addPropertyChangeListener( + this.namespaceModel.addPropertyChangeListener( PropertyValueModel.VALUE, new PropertyChangeListener() { public void propertyChanged(PropertyChangeEvent event) { @@ -839,9 +822,9 @@ public class JaxbSchemasPropertiesPage } }); - Dialog.applyDialogFont(dialogArea); + Dialog.applyDialogFont(da); - return dialogArea; + return da; } @Override @@ -857,7 +840,7 @@ public class JaxbSchemasPropertiesPage return true; } - private void browseForSchemaLocation() { + void browseForSchemaLocation() { SchemaLocationDialog dialog = new SchemaLocationDialog(getShell(), this.resourceManager); // opens the dialog - just returns if the user cancels it @@ -866,7 +849,7 @@ public class JaxbSchemasPropertiesPage } String location = dialog.getLocation(); - this.location.setValue(location); + this.locationModel.setValue(location); String resolvedUri = XsdUtil.getResolvedUri(location); @@ -877,14 +860,14 @@ public class JaxbSchemasPropertiesPage : ((schema.getTargetNamespace()) == null ? StringTools.EMPTY_STRING : schema.getTargetNamespace()); - this.namespace.setValue(newNamespace); + this.namespaceModel.setValue(newNamespace); this.resolvedSchema = schema; validate(); } public String getNamespace() { - return this.namespace.getValue(); + return this.namespaceModel.getValue(); } protected String namespaceDisplayString() { @@ -892,7 +875,7 @@ public class JaxbSchemasPropertiesPage } public String getLocation() { - return this.location.getValue(); + return this.locationModel.getValue(); } protected String locationDisplayString() { @@ -906,7 +889,7 @@ public class JaxbSchemasPropertiesPage else if (isDuplicateNamespace()) { setErrorMessage(JptJaxbUiMessages.SCHEMAS_PAGE_DUPLICATE_NAMESPACE_MESSAGE); } - else if (StringTools.isBlank(this.location.getValue())) { + else if (StringTools.isBlank(this.locationModel.getValue())) { setErrorMessage(JptJaxbUiMessages.SCHEMAS_PAGE_NO_LOCATION_MESSAGE); } else { diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/properties/JpaProjectPropertiesPage.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/properties/JpaProjectPropertiesPage.java index 2c884d2aab..86a0270a02 100644 --- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/properties/JpaProjectPropertiesPage.java +++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/properties/JpaProjectPropertiesPage.java @@ -30,6 +30,7 @@ import org.eclipse.jpt.common.ui.internal.properties.JptProjectPropertiesPage; import org.eclipse.jpt.common.ui.internal.swt.bindings.SWTBindingTools; import org.eclipse.jpt.common.ui.internal.swt.listeners.SWTListenerTools; import org.eclipse.jpt.common.ui.internal.swt.widgets.ControlTools; +import org.eclipse.jpt.common.utility.Association; import org.eclipse.jpt.common.utility.internal.BitTools; import org.eclipse.jpt.common.utility.internal.ObjectTools; import org.eclipse.jpt.common.utility.internal.StringTools; @@ -39,7 +40,6 @@ import org.eclipse.jpt.common.utility.internal.iterable.IterableTools; import org.eclipse.jpt.common.utility.internal.model.value.AbstractCollectionValueModel; import org.eclipse.jpt.common.utility.internal.model.value.AspectCollectionValueModelAdapter; import org.eclipse.jpt.common.utility.internal.model.value.AspectPropertyValueModelAdapter; -import org.eclipse.jpt.common.utility.internal.model.value.BufferedModifiablePropertyValueModel; import org.eclipse.jpt.common.utility.internal.model.value.CompositeCollectionValueModel; import org.eclipse.jpt.common.utility.internal.model.value.ExtendedListValueModelWrapper; import org.eclipse.jpt.common.utility.internal.model.value.PluggableModifiablePropertyValueModel; @@ -119,31 +119,39 @@ public class JpaProjectPropertiesPage private PropertyValueModel<JpaProject> jpaProjectModel; private PropertyValueModel<Boolean> jpaProjectIsNotNullFlagModel; - private BufferedModifiablePropertyValueModel<JpaPlatform.Config> jpaPlatformConfigModel; + private ModifiablePropertyValueModel<JpaPlatform.Config> jpaPlatformConfigModel; + private PropertyValueModel<Boolean> jpaPlatformConfigModelBufferingFlag; private PropertyChangeListener jpaPlatformConfigListener; - private BufferedModifiablePropertyValueModel<String> connectionModel; + private ModifiablePropertyValueModel<String> connectionModel; + private PropertyValueModel<Boolean> connectionModelBufferingFlag; private PropertyValueModel<ConnectionProfile> connectionProfileModel; private PropertyValueModel<Boolean> disconnectedModel; private PropertyChangeListener disconnectedModelListener; private Link connectLink; - private BufferedModifiablePropertyValueModel<Boolean> userOverrideDefaultCatalogFlagModel; - private BufferedModifiablePropertyValueModel<String> userOverrideDefaultCatalogModel; + private ModifiablePropertyValueModel<Boolean> userOverrideDefaultCatalogFlagModel; + private PropertyValueModel<Boolean> userOverrideDefaultCatalogFlagModelBufferingFlag; + private ModifiablePropertyValueModel<String> userOverrideDefaultCatalogModel; + private PropertyValueModel<Boolean> userOverrideDefaultCatalogModelBufferingFlag; private ModifiablePropertyValueModel<String> defaultCatalogModel; private ListValueModel<String> catalogChoicesModel; - private BufferedModifiablePropertyValueModel<Boolean> userOverrideDefaultSchemaFlagModel; - private BufferedModifiablePropertyValueModel<String> userOverrideDefaultSchemaModel; + private ModifiablePropertyValueModel<Boolean> userOverrideDefaultSchemaFlagModel; + private PropertyValueModel<Boolean> userOverrideDefaultSchemaFlagModelBufferingFlag; + private ModifiablePropertyValueModel<String> userOverrideDefaultSchemaModel; + private PropertyValueModel<Boolean> userOverrideDefaultSchemaModelBufferingFlag; private ModifiablePropertyValueModel<String> defaultSchemaModel; private ListValueModel<String> schemaChoicesModel; - private BufferedModifiablePropertyValueModel<Boolean> discoverAnnotatedClassesModel; + private ModifiablePropertyValueModel<Boolean> discoverAnnotatedClassesModel; + private PropertyValueModel<Boolean> discoverAnnotatedClassesModelBufferingFlag; private ModifiablePropertyValueModel<Boolean> listAnnotatedClassesModel; private PropertyValueModel<Boolean> jpa2_0ProjectFlagModel; - private BufferedModifiablePropertyValueModel<String> metamodelSourceFolderModel; + private ModifiablePropertyValueModel<String> metamodelSourceFolderModel; + private PropertyValueModel<Boolean> metamodelSourceFolderModelBufferingFlag; private ListValueModel<String> javaSourceFolderChoicesModel; private static final String BUILD_PATHS_PROPERTY_PAGE_ID = "org.eclipse.jdt.ui.propertyPages.BuildPathsPropertyPage"; //$NON-NLS-1$ @@ -161,30 +169,46 @@ public class JpaProjectPropertiesPage this.jpaProjectModel = this.buildJpaProjectModel(); this.jpaProjectIsNotNullFlagModel = this.buildJpaProjectIsNotNullFlagModel(); - this.jpaPlatformConfigModel = this.buildJpaPlatformConfigModel(); + Association<ModifiablePropertyValueModel<JpaPlatform.Config>, PropertyValueModel<Boolean>> platformConfigAssoc = this.buildJpaPlatformConfigModel(); + this.jpaPlatformConfigModel = platformConfigAssoc.getKey(); + this.jpaPlatformConfigModelBufferingFlag = platformConfigAssoc.getValue(); this.jpaPlatformConfigListener = this.buildJpaPlatformConfigListener(); - this.connectionModel = this.buildConnectionModel(); + Association<ModifiablePropertyValueModel<String>, PropertyValueModel<Boolean>> connectionAssoc = this.buildConnectionModel(); + this.connectionModel = connectionAssoc.getKey(); + this.connectionModelBufferingFlag = connectionAssoc.getValue(); this.connectionProfileModel = this.buildConnectionProfileModel(); this.disconnectedModel = this.buildDisconnectedModel(); this.disconnectedModelListener = this.buildDisconnectedModelListener(); - this.userOverrideDefaultCatalogFlagModel = this.buildUserOverrideDefaultCatalogFlagModel(); - this.userOverrideDefaultCatalogModel = this.buildUserOverrideDefaultCatalogModel(); + Association<ModifiablePropertyValueModel<Boolean>, PropertyValueModel<Boolean>> userOverrideDefaultCatalogFlagAssoc = this.buildUserOverrideDefaultCatalogFlagModel(); + this.userOverrideDefaultCatalogFlagModel = userOverrideDefaultCatalogFlagAssoc.getKey(); + this.userOverrideDefaultCatalogFlagModelBufferingFlag = userOverrideDefaultCatalogFlagAssoc.getValue(); + Association<ModifiablePropertyValueModel<String>, PropertyValueModel<Boolean>> userOverrideDefaultCatalogAssoc = this.buildUserOverrideDefaultCatalogModel(); + this.userOverrideDefaultCatalogModel = userOverrideDefaultCatalogAssoc.getKey(); + this.userOverrideDefaultCatalogModelBufferingFlag = userOverrideDefaultCatalogAssoc.getValue(); this.defaultCatalogModel = this.buildDefaultCatalogModel(); this.catalogChoicesModel = this.buildCatalogChoicesModel(); - this.userOverrideDefaultSchemaFlagModel = this.buildUserOverrideDefaultSchemaFlagModel(); - this.userOverrideDefaultSchemaModel = this.buildUserOverrideDefaultSchemaModel(); + Association<ModifiablePropertyValueModel<Boolean>, PropertyValueModel<Boolean>> userOverrideDefaultSchemaFlagAssoc = this.buildUserOverrideDefaultSchemaFlagModel(); + this.userOverrideDefaultSchemaFlagModel = userOverrideDefaultSchemaFlagAssoc.getKey(); + this.userOverrideDefaultSchemaFlagModelBufferingFlag = userOverrideDefaultSchemaFlagAssoc.getValue(); + Association<ModifiablePropertyValueModel<String>, PropertyValueModel<Boolean>> userOverrideDefaultSchemaAssoc = this.buildUserOverrideDefaultSchemaModel(); + this.userOverrideDefaultSchemaModel = userOverrideDefaultSchemaAssoc.getKey(); + this.userOverrideDefaultSchemaModelBufferingFlag = userOverrideDefaultSchemaAssoc.getValue(); this.defaultSchemaModel = this.buildDefaultSchemaModel(); this.schemaChoicesModel = this.buildSchemaChoicesModel(); - this.discoverAnnotatedClassesModel = this.buildDiscoverAnnotatedClassesModel(); + Association<ModifiablePropertyValueModel<Boolean>, PropertyValueModel<Boolean>> discoverAnnotatedClassesAssoc = this.buildDiscoverAnnotatedClassesModel(); + this.discoverAnnotatedClassesModel = discoverAnnotatedClassesAssoc.getKey(); + this.discoverAnnotatedClassesModelBufferingFlag = discoverAnnotatedClassesAssoc.getValue(); this.listAnnotatedClassesModel = this.buildListAnnotatedClassesModel(); this.jpa2_0ProjectFlagModel = this.buildJpa2_0ProjectFlagModel(); - this.metamodelSourceFolderModel = this.buildMetamodelSourceFolderModel(); + Association<ModifiablePropertyValueModel<String>, PropertyValueModel<Boolean>> metamodelSourceFolderAssoc = this.buildMetamodelSourceFolderModel(); + this.metamodelSourceFolderModel = metamodelSourceFolderAssoc.getKey(); + this.metamodelSourceFolderModelBufferingFlag = metamodelSourceFolderAssoc.getValue(); this.javaSourceFolderChoicesModel = this.buildJavaSourceFolderChoicesModel(); } @@ -214,8 +238,8 @@ public class JpaProjectPropertiesPage } // ***** JPA platform config model - private BufferedModifiablePropertyValueModel<JpaPlatform.Config> buildJpaPlatformConfigModel() { - return new BufferedModifiablePropertyValueModel<>(new JpaPlatformConfigModel(this.jpaProjectModel), this.trigger); + private Association<ModifiablePropertyValueModel<JpaPlatform.Config>, PropertyValueModel<Boolean>> buildJpaPlatformConfigModel() { + return PropertyValueModelTools.buffer(new JpaPlatformConfigModel(this.jpaProjectModel), this.trigger); } private PropertyChangeListener buildJpaPlatformConfigListener(){ @@ -240,8 +264,8 @@ public class JpaProjectPropertiesPage } // ***** connection models - private BufferedModifiablePropertyValueModel<String> buildConnectionModel() { - return new BufferedModifiablePropertyValueModel<>(new ConnectionModel(this.jpaProjectModel), this.trigger); + private Association<ModifiablePropertyValueModel<String>, PropertyValueModel<Boolean>> buildConnectionModel() { + return PropertyValueModelTools.buffer(new ConnectionModel(this.jpaProjectModel), this.trigger); } private PropertyValueModel<ConnectionProfile> buildConnectionProfileModel() { @@ -264,12 +288,12 @@ public class JpaProjectPropertiesPage } // ***** catalog models - private BufferedModifiablePropertyValueModel<Boolean> buildUserOverrideDefaultCatalogFlagModel() { - return new BufferedModifiablePropertyValueModel<>(new UserOverrideDefaultCatalogFlagModel(this.jpaProjectModel), this.trigger); + private Association<ModifiablePropertyValueModel<Boolean>, PropertyValueModel<Boolean>> buildUserOverrideDefaultCatalogFlagModel() { + return PropertyValueModelTools.buffer(new UserOverrideDefaultCatalogFlagModel(this.jpaProjectModel), this.trigger); } - private BufferedModifiablePropertyValueModel<String> buildUserOverrideDefaultCatalogModel() { - return new BufferedModifiablePropertyValueModel<>(new UserOverrideDefaultCatalogModel(this.jpaProjectModel), this.trigger); + private Association<ModifiablePropertyValueModel<String>, PropertyValueModel<Boolean>> buildUserOverrideDefaultCatalogModel() { + return PropertyValueModelTools.buffer(new UserOverrideDefaultCatalogModel(this.jpaProjectModel), this.trigger); } private ModifiablePropertyValueModel<String> buildDefaultCatalogModel() { @@ -313,12 +337,12 @@ public class JpaProjectPropertiesPage } // ***** schema models - private BufferedModifiablePropertyValueModel<Boolean> buildUserOverrideDefaultSchemaFlagModel() { - return new BufferedModifiablePropertyValueModel<>(new UserOverrideDefaultSchemaFlagModel(this.jpaProjectModel), this.trigger); + private Association<ModifiablePropertyValueModel<Boolean>, PropertyValueModel<Boolean>> buildUserOverrideDefaultSchemaFlagModel() { + return PropertyValueModelTools.buffer(new UserOverrideDefaultSchemaFlagModel(this.jpaProjectModel), this.trigger); } - private BufferedModifiablePropertyValueModel<String> buildUserOverrideDefaultSchemaModel() { - return new BufferedModifiablePropertyValueModel<>(new UserOverrideDefaultSchemaModel(this.jpaProjectModel), this.trigger); + private Association<ModifiablePropertyValueModel<String>, PropertyValueModel<Boolean>> buildUserOverrideDefaultSchemaModel() { + return PropertyValueModelTools.buffer(new UserOverrideDefaultSchemaModel(this.jpaProjectModel), this.trigger); } private ModifiablePropertyValueModel<String> buildDefaultSchemaModel() { @@ -359,8 +383,8 @@ public class JpaProjectPropertiesPage } // ***** discover/list annotated classes models - private BufferedModifiablePropertyValueModel<Boolean> buildDiscoverAnnotatedClassesModel() { - return new BufferedModifiablePropertyValueModel<>(new DiscoverAnnotatedClassesModel(this.jpaProjectModel), this.trigger); + private Association<ModifiablePropertyValueModel<Boolean>, PropertyValueModel<Boolean>> buildDiscoverAnnotatedClassesModel() { + return PropertyValueModelTools.buffer(new DiscoverAnnotatedClassesModel(this.jpaProjectModel), this.trigger); } /** @@ -378,8 +402,8 @@ public class JpaProjectPropertiesPage private static final Predicate<JpaModel> IS_COMPATIBLE_WITH_JPA_2_0 = new JpaModel.JpaVersionIsCompatibleWith<>(JpaProject2_0.FACET_VERSION_STRING); // ***** metamodel models - private BufferedModifiablePropertyValueModel<String> buildMetamodelSourceFolderModel() { - return new BufferedModifiablePropertyValueModel<>(new MetamodelSourceFolderModel(this.jpaProjectModel), this.trigger); + private Association<ModifiablePropertyValueModel<String>, PropertyValueModel<Boolean>> buildMetamodelSourceFolderModel() { + return PropertyValueModelTools.buffer(new MetamodelSourceFolderModel(this.jpaProjectModel), this.trigger); } private ListValueModel<String> buildJavaSourceFolderChoicesModel() { @@ -865,7 +889,7 @@ public class JpaProjectPropertiesPage @Override protected boolean projectRebuildRequired() { - return this.jpaPlatformConfigModel.isBuffering(); + return this.jpaPlatformConfigModelBufferingFlag.getValue().booleanValue(); } @Override @@ -890,16 +914,17 @@ public class JpaProjectPropertiesPage } @Override - protected BufferedModifiablePropertyValueModel<?>[] buildBufferedModels() { - return new BufferedModifiablePropertyValueModel[] { - this.jpaPlatformConfigModel, - this.connectionModel, - this.userOverrideDefaultCatalogFlagModel, - this.userOverrideDefaultCatalogModel, - this.userOverrideDefaultSchemaFlagModel, - this.userOverrideDefaultSchemaModel, - this.discoverAnnotatedClassesModel, - this.metamodelSourceFolderModel + @SuppressWarnings("unchecked") + protected PropertyValueModel<Boolean>[] buildBufferingFlags() { + return new PropertyValueModel[] { + this.jpaPlatformConfigModelBufferingFlag, + this.connectionModelBufferingFlag, + this.userOverrideDefaultCatalogFlagModelBufferingFlag, + this.userOverrideDefaultCatalogModelBufferingFlag, + this.userOverrideDefaultSchemaFlagModelBufferingFlag, + this.userOverrideDefaultSchemaModelBufferingFlag, + this.discoverAnnotatedClassesModelBufferingFlag, + this.metamodelSourceFolderModelBufferingFlag }; } |