001package jmri.beans; 002 003import java.beans.IndexedPropertyChangeEvent; 004import java.beans.PropertyChangeEvent; 005import java.beans.PropertyVetoException; 006import java.beans.VetoableChangeListener; 007import java.beans.VetoableChangeSupport; 008 009/** 010 * A Bean with support for {@link java.beans.VetoableChangeListener}s. 011 * 012 * @author Randall Wood 013 */ 014public abstract class ConstrainedBean extends Bean implements VetoableChangeProvider { 015 016 protected final VetoableChangeSupport vetoableChangeSupport = new VetoableChangeSupport(this); 017 018 @Override 019 public void setProperty(String key, Object value) { 020 try { 021 this.fireVetoableChange(key, getProperty(key), value); 022 super.setProperty(key, value); 023 } catch (PropertyVetoException ex) { 024 // fire a property change that does not have the new value to indicate 025 // to any other listeners that the property was "reset" back to its 026 // original value as a result of the veto 027 this.firePropertyChange(key, getProperty(key), getProperty(key)); 028 } 029 } 030 031 @Override 032 public void setIndexedProperty(String key, int index, Object value) { 033 try { 034 Object old = this.getIndexedPropertyOrNull(key, index); 035 this.fireVetoableChange(new IndexedPropertyChangeEvent(this, key, old, value, index)); 036 super.setIndexedProperty(key, index, value); 037 } catch (PropertyVetoException ex) { 038 // fire a property change that does not have the new value to indicate 039 // to any other listeners that the property was "reset" back to its 040 // original value as a result of the veto 041 this.fireIndexedPropertyChange(key, index, getProperty(key), getProperty(key)); 042 } 043 } 044 045 @Override 046 public void addVetoableChangeListener(VetoableChangeListener listener) { 047 this.vetoableChangeSupport.addVetoableChangeListener(listener); 048 } 049 050 @Override 051 public void addVetoableChangeListener(String propertyName, VetoableChangeListener listener) { 052 this.vetoableChangeSupport.addVetoableChangeListener(propertyName, listener); 053 } 054 055 @Override 056 public VetoableChangeListener[] getVetoableChangeListeners() { 057 return this.vetoableChangeSupport.getVetoableChangeListeners(); 058 } 059 060 @Override 061 public VetoableChangeListener[] getVetoableChangeListeners(String propertyName) { 062 return this.vetoableChangeSupport.getVetoableChangeListeners(propertyName); 063 } 064 065 @Override 066 public void removeVetoableChangeListener(VetoableChangeListener listener) { 067 this.vetoableChangeSupport.removeVetoableChangeListener(listener); 068 } 069 070 @Override 071 public void removeVetoableChangeListener(String propertyName, VetoableChangeListener listener) { 072 this.vetoableChangeSupport.removeVetoableChangeListener(propertyName, listener); 073 } 074 075 /** 076 * Fire a vetoable property change on the current thread. Use 077 * {@link java.beans.VetoableChangeSupport#fireVetoableChange(java.beans.PropertyChangeEvent)} 078 * directly to fire this notification on another thread. If a 079 * PropertyVetoException is thrown, ensure the property change does not 080 * complete. 081 * 082 * @param event {@link PropertyChangeEvent} to be fired 083 * @throws PropertyVetoException if property update vetoed 084 */ 085 public void fireVetoableChange(PropertyChangeEvent event) throws PropertyVetoException { 086 this.vetoableChangeSupport.fireVetoableChange(event); 087 } 088 089 /** 090 * Fire a vetoable property change on the current thread. Use 091 * {@link java.beans.VetoableChangeSupport#fireVetoableChange(java.lang.String, java.lang.Object, java.lang.Object)} 092 * directly to fire this notification on another thread. If a 093 * PropertyVetoException is thrown, ensure the property change does not 094 * complete. 095 * 096 * @param propertyName property that is about to change 097 * @param oldValue old value of the property 098 * @param newValue new value of the property 099 * @throws PropertyVetoException if property update vetoed 100 */ 101 public void fireVetoableChange(String propertyName, Object oldValue, Object newValue) throws PropertyVetoException { 102 this.vetoableChangeSupport.fireVetoableChange(propertyName, oldValue, newValue); 103 } 104 105 /** 106 * Fire a vetoable property change on the current thread. Use 107 * {@link java.beans.VetoableChangeSupport#fireVetoableChange(java.lang.String, int, int)} 108 * directly to fire this notification on another thread. If a 109 * PropertyVetoException is thrown, ensure the property change does not 110 * complete. 111 * 112 * @param propertyName property that is about to change 113 * @param oldValue old value of the property 114 * @param newValue new value of the property 115 * @throws PropertyVetoException if property update vetoed 116 */ 117 public void fireVetoableChange(String propertyName, int oldValue, int newValue) throws PropertyVetoException { 118 this.vetoableChangeSupport.fireVetoableChange(propertyName, oldValue, newValue); 119 } 120 121 /** 122 * Fire a vetoable property change on the current thread. Use 123 * {@link java.beans.VetoableChangeSupport#fireVetoableChange(java.lang.String, boolean, boolean)} 124 * directly to fire this notification on another thread. If a 125 * PropertyVetoException is thrown, ensure the property change does not 126 * complete. 127 * 128 * @param propertyName property that is about to change 129 * @param oldValue old value of the property 130 * @param newValue new value of the property 131 * @throws PropertyVetoException if property update vetoed 132 */ 133 public void fireVetoableChange(String propertyName, boolean oldValue, boolean newValue) 134 throws PropertyVetoException { 135 this.vetoableChangeSupport.fireVetoableChange(propertyName, oldValue, newValue); 136 } 137 138 /** 139 * Get the indexed property or return null if the index is invalid. Used to 140 * get the old value when setting an indexed property where the index may 141 * not previously have been set. 142 * 143 * @param key the property name 144 * @param index the index 145 * @return the value at index or null 146 */ 147 protected Object getIndexedPropertyOrNull(String key, int index) { 148 try { 149 return this.getIndexedProperty(key, index); 150 } catch (IndexOutOfBoundsException ex) { 151 return null; 152 } 153 154 } 155}