/*
* Copyright (c) 2006 Stiftung Deutsches Elektronen-Synchroton,
* Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
*
* THIS SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "../AS IS" BASIS.
* WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR PARTICULAR PURPOSE AND
* NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
* THE USE OR OTHER DEALINGS IN THE SOFTWARE. SHOULD THE SOFTWARE PROVE DEFECTIVE
* IN ANY RESPECT, THE USER ASSUMES THE COST OF ANY NECESSARY SERVICING, REPAIR OR
* CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE.
* NO USE OF ANY SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
* DESY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
* OR MODIFICATIONS.
* THE FULL LICENSE SPECIFYING FOR THE SOFTWARE THE REDISTRIBUTION, MODIFICATION,
* USAGE AND OTHER RIGHTS AND OBLIGATIONS IS INCLUDED WITH THE DISTRIBUTION OF THIS
* PROJECT IN THE FILE LICENSE.HTML. IF THE LICENSE IS NOT INCLUDED YOU MAY FIND A COPY
* AT HTTP://WWW.DESY.DE/LEGAL/LICENSE.HTM
*/
package org.csstudio.sds.model;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* This class defines a property for SDS widget models.
*
* @author Alexander Will
* @version $Revision: 1.15 $
*
*/
public abstract class WidgetProperty {
/**
* ID of the property.
*/
private String _id;
private AbstractWidgetModel _widgetModel;
private Set<String> _hiddenBy;
/**
* Indicates, whether this property can be used to display dynamic values
* from a control system.
*/
private boolean _dynamicWriteAllowed;
/**
* The registered property change listeners.
*/
private List<IPropertyChangeListener> _changeListeners;
/**
* A textual description of this property.
*/
private String _description;
private String _longDescription;
/**
* The data type of this property.
*/
private PropertyTypesEnum _propertyType;
/**
* Id of the category, this property belongs to.
*/
private WidgetPropertyCategory _category;
/**
* The dynamics descriptor.
*/
private DynamicsDescriptor _dynamicsDescriptor;
/**
* The current value of this property.
*/
private Object _propertyValue;
/**
* The current manual value of this property.
*/
private Object _manualValue;
/**
* The default value of this property.
*/
private Object _defaultValue;
/**
* Standard constructor.
*
* @param description
* A textual description of this property.
* @param category
* the category
* @param propertyType
* the data type of this property.
* @param defaultValue
* the current value of this property.
* @param dynamicsDescriptor
* the dynamics descriptor
*/
public WidgetProperty(final PropertyTypesEnum propertyType,
final String description, String longDescription, final WidgetPropertyCategory category,
final Object defaultValue,
final DynamicsDescriptor dynamicsDescriptor) {
assert propertyType != null;
assert description != null;
assert category != null;
assert defaultValue != null;
_propertyType = propertyType;
_description = description;
_longDescription = longDescription;
_category = category;
_defaultValue = defaultValue;
_propertyValue = defaultValue;
_dynamicsDescriptor = dynamicsDescriptor;
_changeListeners = new CopyOnWriteArrayList<IPropertyChangeListener>();
_dynamicWriteAllowed = true;
_hiddenBy = new HashSet<String>();
}
public WidgetProperty(final PropertyTypesEnum propertyType,
final String description, final WidgetPropertyCategory category,
final Object defaultValue,
final DynamicsDescriptor dynamicsDescriptor) {
this(propertyType, description, null, category, defaultValue, dynamicsDescriptor);
}
public String getId() {
return _id;
}
public void setId(String id) {
_id = id;
}
public AbstractWidgetModel getWidgetModel() {
return _widgetModel;
}
public void setWidgetModel(AbstractWidgetModel widgetModel) {
_widgetModel = widgetModel;
}
public void hide(String masterId) {
_hiddenBy.add(masterId);
}
public void show(String masterId) {
_hiddenBy.remove(masterId);
}
public boolean isVisible() {
return _hiddenBy.isEmpty();
}
/**
* Returns a text representation for tooltips. Should be overridden by
* subclasses to implement customized tooltip texts.
*
* @return a text representation for tooltips
*/
public String getTextForTooltip() {
Object v = getPropertyValue();
return v != null ? v.toString() : "-";
}
/**
* Returns all Java types to which the value of this {@link WidgetProperty}
* is compatible to.
*
* @return an array which contains all Java types, the property value is
* compatible too
*/
public abstract Class[] getCompatibleJavaTypes();
/**
* Subclasses should check the specified value and should as far as possible
* convert it to a value, which can be applied as property value.
*
* If a conversion is not possible, this method should return null to
* indicate, that the specified value is incompatible.
*
* @param value
* the value to check
* @return the original value, a converted value or null, if the original
* value is incompatible
*/
public abstract Object checkValue(Object value);
/**
* Return the current value of this property.
*
* @return The current value of this property.
*/
@SuppressWarnings("unchecked")
public final <E> E getPropertyValue() {
return (E) _propertyValue;
}
/**
* Set the current value of this property.
*
* @param requestedNewValue
* The current value of this property.
*/
public final void setPropertyValue(final Object requestedNewValue) {
// do conversion check
Object newValue = checkValue(requestedNewValue);
if (newValue != null) {
// apply value
Object oldValue = _propertyValue;
_propertyValue = newValue;
firePropertyChangeEvent(oldValue, newValue);
}
}
/**
* Set the manual value of this property.
*
* @param manualValue
* The current value of this property.
*/
public final void setManualValue(final Object manualValue) {
if (_dynamicWriteAllowed) {
_manualValue = manualValue;
fireManualValueChanged();
}
else
throw new IllegalStateException("This method should not be called on a property, which is not enabled for writing dynamic values back to the control system."); //$NON-NLS-1$
}
/**
* set the textual description of this property.
*/
public final void setDescription(String description) {
this._description = description;
}
/**
* Return the textual description of this property.
*
* @return The textual description of this property.
*/
public final String getDescription() {
return _description;
}
public String getLongDescription() {
return _longDescription;
}
/**
* Return the data type of this property.
*
* @return The data type of this property.
*/
public final PropertyTypesEnum getPropertyType() {
return _propertyType;
}
/**
* Return the default value of this property.
*
* @return The default value of this property.
*/
public final Object getDefaultValue() {
return _defaultValue;
}
/**
* Gets the dynamics descriptor.
*
* @return The dynamics descriptor.
*/
public final DynamicsDescriptor getDynamicsDescriptor() {
return _dynamicsDescriptor;
}
/**
* Sets the dynamics descriptor.
*
* @param dynamicsDescriptor
* The dynamics descriptor.
*/
public final void setDynamicsDescriptor(final DynamicsDescriptor dynamicsDescriptor) {
_dynamicsDescriptor = dynamicsDescriptor;
fireDynamicsDescriptorChanged();
}
/**
* Returns the category for this property.
*
* @return the category for this property
*/
public final WidgetPropertyCategory getCategory() {
return _category;
}
/**
* Add a property change listener.
*
* @param listener
* A property change listener.
*/
public final synchronized void addPropertyChangeListener(final IPropertyChangeListener listener) {
_changeListeners.add(listener);
}
/**
* Remove a property change listener.
*
* @param listener
* A property change listener.
*/
public final synchronized void removePropertyChangeListener(final IPropertyChangeListener listener) {
_changeListeners.remove(listener);
}
/**
* Remove all property change listeners.
*/
public final synchronized void removePropertyChangeListeners() {
for (IPropertyChangeListener l : _changeListeners)
removePropertyChangeListener(l);
}
/**
* Notify all registered property change listeners.
*
* @param oldValue
* The old value of the property.
* @param newValue
* The new value of the property.
*/
public final synchronized void firePropertyChangeEvent(final Object oldValue, final Object newValue) {
boolean changed = false;
if (newValue != null) {
if (oldValue == null || !newValue.equals(oldValue))
changed = true;
}
else {
if (oldValue != null)
changed = true;
}
// only fire, if the value really changed
if (changed) {
for (IPropertyChangeListener listener : _changeListeners)
listener.propertyValueChanged(oldValue, newValue);
}
}
/**
* Notify all registered property change listeners, that the dynamics
* descriptor of this property has changed.
*/
protected final synchronized void fireDynamicsDescriptorChanged() {
for (IPropertyChangeListener listener : _changeListeners)
listener.dynamicsDescriptorChanged(_dynamicsDescriptor);
}
/**
* Notify all registered property change listeners, that the manual value of
* this property has changed.
*/
protected final synchronized void fireManualValueChanged() {
for (IPropertyChangeListener listener : _changeListeners)
listener.propertyManualValueChanged(_id, _manualValue);
}
}