/** * Copyright (C) 2015 Valkyrie RCP * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.valkyriercp.binding.value.support; import org.valkyriercp.binding.value.DerivedValueModel; import org.valkyriercp.binding.value.ValueModel; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; /** * Abstract base class for value models that derive their value from one or more * "source" value model. Provides a hook to notify when any of the "source" * value models change. * * @author Oliver Hutchison */ public abstract class AbstractDerivedValueModel extends AbstractValueModel implements DerivedValueModel { private final ValueModel[] sourceValueModels; private final PropertyChangeListener sourceChangeHandler; /** * Create a derivedValueModel based on the given sourceValueModels. When any * of these valueModels has their value changed, the derivedValueModel will * update its value. * * @param sourceValueModels an <code>Array</code> of valueModels that * influence the derived value. */ protected AbstractDerivedValueModel(ValueModel[] sourceValueModels) { this.sourceValueModels = sourceValueModels; this.sourceChangeHandler = new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { sourceValuesChanged(); } }; for (int i = 0; i < sourceValueModels.length; i++) { sourceValueModels[i].addValueChangeListener(sourceChangeHandler); } } public ValueModel[] getSourceValueModels() { return sourceValueModels; } /** * Convenience method to extract values from all sourceValueModels that * influence the derived value. * * @return an <code>Array</code> containing the source values in the same * order as the source valueModels were defined. */ protected Object[] getSourceValues() { Object[] values = new Object[sourceValueModels.length]; for (int i = 0; i < values.length; i++) { values[i] = sourceValueModels[i].getValue(); } return values; } /** * Derive the value from the source values and fire a valueChangeEvent to * notify listeners. */ protected abstract void sourceValuesChanged(); /** * A derived valueModel is always readOnly. * * @see #setValue(Object) */ public boolean isReadOnly() { return true; } /** * A {@link DerivedValueModel}'s value is based on other valueModels, it * cannot be set. Will throw an {@link UnsupportedOperationException} when * used. */ public void setValue(Object newValue) { throw new UnsupportedOperationException("This value model is read only"); } }