Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/ValueAspectAdapter.java')
-rw-r--r--common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/ValueAspectAdapter.java201
1 files changed, 201 insertions, 0 deletions
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/ValueAspectAdapter.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/ValueAspectAdapter.java
new file mode 100644
index 0000000000..5876d5e444
--- /dev/null
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/model/value/ValueAspectAdapter.java
@@ -0,0 +1,201 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2009 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.ChangeSupport;
+import org.eclipse.jpt.common.utility.model.event.PropertyChangeEvent;
+import org.eclipse.jpt.common.utility.model.listener.StateChangeListener;
+import org.eclipse.jpt.common.utility.model.value.WritablePropertyValueModel;
+
+/**
+ * Abstract class that provides support for wrapping a {@link WritablePropertyValueModel}
+ * and listening for changes to <em>aspects</em> of the <em>value</em> contained
+ * by the {@link WritablePropertyValueModel}. Changes to the {@link WritablePropertyValueModel}'s
+ * value are also monitored.
+ * <p>
+ * This is useful if you have a value that may change, but whose aspects can also
+ * change in a fashion that might be of interest to the client.
+ * <p>
+ * <strong>NB:</strong> Clients will need to listen for two different change notifications:
+ * a property change event will be be fired when the <em>value</em> changes;
+ * a state change event will be fired when an <em>aspect</em> of the value changes.
+ * <p>
+ * Subclasses need to override two methods:<ul>
+ * <li>{@link #engageValue_()}<p>
+ * begin listening to the appropriate aspect of the value and call
+ * {@link #valueAspectChanged()} whenever the aspect changes
+ * (this will fire a state change event)
+ * <li>{@link #disengageValue_()}<p>
+ * stop listening to the appropriate aspect of the value
+ * </ul>
+ */
+public abstract class ValueAspectAdapter<V>
+ extends PropertyValueModelWrapper<V>
+ implements WritablePropertyValueModel<V>
+{
+ /** Cache the value so we can disengage. Null until we have a listener*/
+ protected V value;
+
+
+ // ********** constructors/initialization **********
+
+ /**
+ * Constructor - the value holder is required.
+ */
+ protected ValueAspectAdapter(WritablePropertyValueModel<V> valueHolder) {
+ super(valueHolder);
+ this.value = null;
+ }
+
+ /**
+ * Override to allow both property and state change listeners.
+ */
+ @Override
+ protected ChangeSupport buildChangeSupport() {
+ return new ChangeSupport(this);
+ }
+
+
+ // ********** PropertyValueModel implementation **********
+
+ public V getValue() {
+ return this.value;
+ }
+
+
+ // ********** WritablePropertyValueModel implementation **********
+
+ public void setValue(V value) {
+ this.getValueHolder().setValue(value);
+ }
+
+
+ // ********** PropertyValueModelWrapper implementation **********
+
+ @Override
+ protected void valueChanged(PropertyChangeEvent event) {
+ this.disengageValue();
+ this.engageValue();
+ this.firePropertyChanged(event.clone(this));
+ }
+
+
+ // ********** extend change support **********
+
+ /**
+ * Extend to start listening to the underlying model if necessary.
+ */
+ @Override
+ public synchronized void addStateChangeListener(StateChangeListener listener) {
+ if (this.hasNoListeners()) {
+ this.engageModel();
+ }
+ super.addStateChangeListener(listener);
+ }
+
+ /**
+ * Extend to stop listening to the underlying model if necessary.
+ */
+ @Override
+ public synchronized void removeStateChangeListener(StateChangeListener listener) {
+ super.removeStateChangeListener(listener);
+ if (this.hasNoListeners()) {
+ this.disengageModel();
+ }
+ }
+
+
+ // ********** AbstractPropertyValueModel overrides **********
+
+ /**
+ * Extend to check for state change listeners.
+ */
+ @Override
+ protected boolean hasListeners() {
+ return this.hasAnyStateChangeListeners() || super.hasListeners();
+ }
+
+
+ // ********** PropertyValueModelWrapper overrides **********
+
+ /**
+ * Extend to engage an aspect of the value model's value.
+ */
+ @Override
+ protected void engageModel() {
+ super.engageModel();
+ this.engageValue();
+ }
+
+ /**
+ * Extend to disengage an aspect of the value model's value.
+ */
+ @Override
+ protected void disengageModel() {
+ this.disengageValue();
+ super.disengageModel();
+ }
+
+
+ // ********** behavior **********
+
+ /**
+ * Start listening to an aspect of the current value.
+ */
+ protected void engageValue() {
+ this.value = this.valueHolder.getValue();
+ if (this.value != null) {
+ this.engageValue_();
+ }
+ }
+
+ /**
+ * Start listening to some aspect of the current value.
+ * At this point we can be sure the value is not null.
+ */
+ protected abstract void engageValue_();
+
+ /**
+ * Stop listening to an aspect of the current value.
+ */
+ protected void disengageValue() {
+ if (this.value != null) {
+ this.disengageValue_();
+ this.value = null;
+ }
+ }
+
+ /**
+ * Stop listening to an aspect of the current value.
+ * At this point we can be sure the value is not null.
+ */
+ protected abstract void disengageValue_();
+
+ /**
+ * Subclasses should call this method whenever the value's aspect changes.
+ */
+ protected void valueAspectChanged() {
+ this.fireStateChanged();
+ }
+
+ /**
+ * Our constructor accepts only a {@link WritablePropertyValueModel}{@code<V>}.
+ */
+ @SuppressWarnings("unchecked")
+ protected WritablePropertyValueModel<V> getValueHolder() {
+ return (WritablePropertyValueModel<V>) this.valueHolder;
+ }
+
+ @Override
+ public void toString(StringBuilder sb) {
+ sb.append(this.getValue());
+ }
+
+}

Back to the top