Ik ben weer eens bezig gegaan met wat changesupport om oa wat makkelijk gui aan te sluiten op modellen door oa berichtgeving mbt veranderingen te vereenvoudigen.
Dit is trouwens nog gebaseerd op de ideeen van de PropertyChangeSupport van Sun, maar ik vind daar een aantal dingen aan vervelend.
1) je kan geen mem leaks overhouden doordat je listeners vergeet te verwijderen. Dit heb ik opgelost (optioneel) met een WeakReference.
2) een foutmelding als support voor een bepaalde property niet bestaat.
3) optimalisatie als er geen change is. Dit zou eventueel ook afgevangen kunnen worden op lager nivo, maar meestal krijg je daar dan onnodig onoverzichtelijke code.
Ik hoor graag jullie commentaar erover (tis nog niet helemaal klaar trouwens).
Ik ben op dit moment ook bezig met een nieuwe List,Map,Tree ChangeSupport waar je ook eenvoudig gui op aan kan sluitens zoals tables en trees.
Naast dit 'ouderwetse' gebeuren ga ik straks ook weer bezig met mijn 'basis' domein objecten waardoor nog veel meer van dit soort zaken op de achtergrond kunnen draaien.
Dit is trouwens nog gebaseerd op de ideeen van de PropertyChangeSupport van Sun, maar ik vind daar een aantal dingen aan vervelend.
1) je kan geen mem leaks overhouden doordat je listeners vergeet te verwijderen. Dit heb ik opgelost (optioneel) met een WeakReference.
2) een foutmelding als support voor een bepaalde property niet bestaat.
3) optimalisatie als er geen change is. Dit zou eventueel ook afgevangen kunnen worden op lager nivo, maar meestal krijg je daar dan onnodig onoverzichtelijke code.
Ik hoor graag jullie commentaar erover (tis nog niet helemaal klaar trouwens).
Ik ben op dit moment ook bezig met een nieuwe List,Map,Tree ChangeSupport waar je ook eenvoudig gui op aan kan sluitens zoals tables en trees.
Naast dit 'ouderwetse' gebeuren ga ik straks ook weer bezig met mijn 'basis' domein objecten waardoor nog veel meer van dit soort zaken op de achtergrond kunnen draaien.
code:
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
| public interface ListenerList<E extends EventListener>{
public void add(E l);
public boolean remove(E l);
public void removeAll();
public List<E> listeners();
}
public final class NormalRefListenerList<E extends EventListener> implements ListenerList<E>{
private List<E> _listeners = new LinkedList<E>();
public NormalRefListenerList(){}
synchronized public void add(E l){
if(l == null)
throw new NullPointerException("l can`t be null");
if(_listeners.contains(l))
throw new IllegalArgumentException();
_listeners.add(l);
}
synchronized public boolean remove(E l){
if(l == null)
throw new NullPointerException("l can`t be null");
return _listeners.remove(l);
}
synchronized public void removeAll(){
_listeners.clear();
}
synchronized public List<E> listeners(){
return new LinkedList(_listeners);
}
}
public final class WeakRefListenerList<E extends EventListener> implements ListenerList<E>{
private List<WeakReference<E>> _listenerList = new LinkedList<WeakReference<E>>();
public WeakRefListenerList(){}
synchronized public void add(E l){
if(l == null)
throw new NullPointerException("l can`t be null");
if(contains(l))
throw new IllegalArgumentException("listener: "+l+" already is listener");
_listenerList.add(new WeakReference<E>(l));
}
synchronized public boolean remove(E l){
if(l == null)
throw new NullPointerException("l can`t be null");
return _listenerList.remove(l);
}
synchronized public void removeAll(){
_listenerList.clear();
}
synchronized public List<E> listeners(){
List<E> result = new LinkedList<E>();
for(ListIterator<WeakReference<E>> itt = _listenerList.listIterator();itt.hasNext();){
E ref = itt.next().get();
if(ref!=null)
result.add(ref);
else
itt.remove();
}
return result;
}
private boolean contains(E l){
assert l!=null:"l can`t be null";
for(Iterator<WeakReference<E>> itt = _listenerList.iterator();itt.hasNext();){
if(l.equals(itt.next().get()))
return true;
}
return false;
}
}
public class PropertyChangeSupport<S>{
private final S _source;
private final boolean _weakRefs;
private Map<String,ListenerList<PropertyChangeListener>> _listenerListMap =
new HashMap<String,ListenerList<PropertyChangeListener>>();
public PropertyChangeSupport(S source, boolean weakRefs){
if(source == null)
throw new NullPointerException("source can`t be null");
_source = source;
_weakRefs = weakRefs;
}
public PropertyChangeSupport(S source, boolean weakRefs, String[] properties){
this(source,weakRefs);
if(properties == null)
throw new NullPointerException("properties can`t be null");
for(int k=0;k<properties.length;k++)
addSupport(properties[k]);
}
/**
* Creates support for property
*
* @param property a String
*
*/
synchronized public void addSupport(String property){
if(hasSupport(property))
throw new IllegalArgumentException("property: "+property+" already is supported");
ListenerList<PropertyChangeListener> list = null;
if(_weakRefs)
list = new WeakRefListenerList<PropertyChangeListener>();
else
list = new NormalRefListenerList<PropertyChangeListener>();
_listenerListMap.put(property,list);
}
/**
* Removes support for property
*
* @param property a String
*
*/
synchronized public void removeSupport(String property){
if(!hasSupport(property))
throw new IllegalArgumentException("property: "+property+" is not supported");
_listenerListMap.remove(property);
}
/**
* Checks if there is Support for property
*
* @param property a String
*
* @return a boolean
*
*/
synchronized public boolean hasSupport(String property){
if(property == null)
throw new NullPointerException("property can`t be null");
return _listenerListMap.containsKey(property);
}
/**
* Retuns an array of all Supported Properties
*
* @return a String[]
*
*/
synchronized public String[] supports(){
return (String[])_listenerListMap.keySet().toArray();
}
synchronized public void addPropertyChangeListener(PropertyChangeListener l){
throw new UnsupportedOperationException();
}
synchronized public void addPropetyChangeListener(PropertyChangeListener l, String property){
get(property).add(l);
}
synchronized public void removePropertyChangeListener(PropertyChangeListener l){
throw new UnsupportedOperationException();
}
synchronized public void removePropertyChangeListener(PropertyChangeListener l, String property){
get(property).remove(l);
}
synchronized public void removePropertyChangeListeners(){
for(Iterator<ListenerList<PropertyChangeListener>> itt = _listenerListMap.values().iterator();itt.hasNext();){
itt.next().removeAll();
}
}
synchronized public void removePropertyChangeListeners(String property){
get(property).removeAll();
}
public S getSource(){return _source;}
public void firePropertyChange(String property, int oldValue, int newValue){
if(oldValue == newValue)
return;
fireInternally(property,new Integer(oldValue),new Integer(newValue));
}
public void firePropertyChange(String property, boolean oldValue, boolean newValue){
if(oldValue == newValue)
return;
fireInternally(property,new Boolean(oldValue),new Boolean(newValue));
}
public void firePropertyChange(String property, float oldValue, float newValue){
if(oldValue == newValue)
return;
fireInternally(property,new Float(oldValue),new Float(newValue));
}
public void firePropertyChange(String property, char oldValue, char newValue){
if(oldValue == newValue)
return;
fireInternally(property,new Character(oldValue),new Character(newValue));
}
public void firePropertyChange(String property, Object oldValue, Object newValue){
if(oldValue!=null){
if(oldValue.equals(newValue))
return;
}
fireInternally(property,oldValue,newValue);
}
private void fireInternally(String property, Object oldValue, Object newValue){
ListenerList<PropertyChangeListener> l=get(property);
//send event.
PropertyChangeEvent pce = new PropertyChangeEvent(_source,property,oldValue,newValue);
for(Iterator<PropertyChangeListener> itt = l.listeners().iterator();itt.hasNext();){
itt.next().propertyChange(pce);
}
}
private ListenerList<PropertyChangeListener> get(String property){
if(property == null)
throw new NullPointerException("property can`t be null");
ListenerList<PropertyChangeListener> result = _listenerListMap.get(property);
if(result == null)
throw new IllegalArgumentException("property: "+property+" is not supported");
return result;
}
} |
[ Voor 5% gewijzigd door Alarmnummer op 13-12-2002 12:31 ]