Skip to main content
summaryrefslogtreecommitdiffstats
blob: 5e201d0e2edcc953ff580601924b851444b6ee73 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/*******************************************************************************
 * 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.utility.internal.model.value;

import org.eclipse.jpt.utility.Filter;
import org.eclipse.jpt.utility.model.event.PropertyChangeEvent;
import org.eclipse.jpt.utility.model.value.PropertyValueModel;

/**
 * A <code>FilteringPropertyValueModel</code> wraps another
 * {@link PropertyValueModel} and uses a {@link Filter}
 * to determine when the wrapped value is to be returned by calls
 * to {@link #getValue()}.
 * <p>
 * As an alternative to building a {@link Filter}, a subclass
 * can override {@link #accept(T)}.
 * <p>
 * One, possibly undesirable, side-effect of using this value model is that
 * it must return *something* as the value. The default behavior is
 * to return <code>null</code> whenever the wrapped value is not "accepted",
 * which can be configured and/or overridden ({@link #getDefaultValue()}).
 */
public class FilteringPropertyValueModel<T>
	extends PropertyValueModelWrapper<T>
	implements PropertyValueModel<T>
{
	protected final Filter<T> filter;
	protected final T defaultValue;


	// ********** constructors **********

	/**
	 * Construct a filtering property value model with the specified nested
	 * property value model and a disabled filter.
	 * Use this constructor if you want to override {@link #accept(T)}
	 * instead of building a {@link Filter}.
	 * The default value will be <code>null</code>.
	 */
	public FilteringPropertyValueModel(PropertyValueModel<? extends T> valueHolder) {
		this(valueHolder, Filter.Disabled.<T>instance(), null);
	}

	/**
	 * Construct a filtering property value model with the specified nested
	 * property value model, specified default value, and a disabled filter.
	 * Use this constructor if you want to override {@link #accept(T)}
	 * instead of building a {@link Filter}
	 * <em>and</em> you need to specify
	 * a default value other than <code>null</code>.
	 */
	public FilteringPropertyValueModel(PropertyValueModel<? extends T> valueHolder, T defaultValue) {
		this(valueHolder, Filter.Disabled.<T>instance(), defaultValue);
	}

	/**
	 * Construct a filtering property value model with the specified nested
	 * property value model and filter.
	 * The default value will be <code>null</code>.
	 */
	public FilteringPropertyValueModel(PropertyValueModel<? extends T> valueHolder, Filter<T> filter) {
		this(valueHolder, filter, null);
	}

	/**
	 * Construct a filtering property value model with the specified nested
	 * property value model, filter, and default value.
	 */
	public FilteringPropertyValueModel(PropertyValueModel<? extends T> valueHolder, Filter<T> filter, T defaultValue) {
		super(valueHolder);
		this.filter = filter;
		this.defaultValue = defaultValue;
	}


	// ********** PropertyValueModel implementation **********

	public T getValue() {
		return this.filterValue(this.valueHolder.getValue());
	}


	// ********** PropertyValueModelWrapper implementation **********

	@Override
	protected void valueChanged(PropertyChangeEvent event) {
		// filter the values before propagating the change event
		@SuppressWarnings("unchecked")
		T eventOldValue = (T) event.getOldValue();
		Object oldValue = this.filterValue(eventOldValue);
		@SuppressWarnings("unchecked")
		T eventNewValue = (T) event.getNewValue();
		Object newValue = this.filterValue(eventNewValue);
		this.firePropertyChanged(VALUE, oldValue, newValue);
	}


	// ********** queries **********

	/**
	 * If the specified value is "accepted" simply return it,
	 * otherwise return the default value.
	 */
	protected T filterValue(T value) {
		return this.accept(value) ? value : this.getDefaultValue();
	}

	/**
	 * Return whether the filtering property value model should
	 * return the specified value from a call to
	 * {@link #getValue()}; the value came
	 * from the nested property value model
	 * <p>
	 * This method can be overridden by a subclass as an
	 * alternative to building a {@link Filter}.
	 */
	protected boolean accept(T value) {
		return this.filter.accept(value);
	}

	/**
	 * Return the object that should be returned if
	 * the nested value was rejected by the filter.
	 * The default is <code>null</code>.
	 */
	protected T getDefaultValue() {
		return this.defaultValue;
	}

	@Override
	public void toString(StringBuilder sb) {
		sb.append(this.getValue());
	}

}

Back to the top