Revision 24267

View differences:

branches/v2_0_0_prep/libraries/libTools/src-test/org/gvsig/tools/observable/BaseObservableTest.java
32 32

  
33 33
import org.easymock.MockControl;
34 34
import org.gvsig.tools.observer.Observer;
35
import org.gvsig.tools.observer.impl.BaseObservable;
35
import org.gvsig.tools.observer.impl.BaseWeakReferencingObservable;
36 36

  
37 37
/**
38 38
 * @author <a href="mailto:cordin@disid.com">C?sar Ordi?ana</a>
39 39
 */
40 40
public class BaseObservableTest extends TestCase {
41 41

  
42
    private BaseObservable observable;
42
    private BaseWeakReferencingObservable observable;
43 43
    private MockControl obsControl;
44 44
    private Observer observer;
45 45

  
46 46
    protected void setUp() throws Exception {
47 47
        super.setUp();
48
        observable = new BaseObservable();
48
        observable = new BaseWeakReferencingObservable();
49 49
        obsControl = MockControl.createStrictControl(Observer.class);
50 50
        observer = (Observer) obsControl.getMock();
51 51
    }
......
56 56

  
57 57
    /**
58 58
     * Test method for
59
     * {@link org.gvsig.tools.observer.impl.BaseObservable#enableNotifications()}
59
     * {@link org.gvsig.tools.observer.impl.BaseWeakReferencingObservable#enableNotifications()}
60 60
     * .
61 61
     */
62 62
    public void testEnableNotifications() {
......
71 71
    }
72 72

  
73 73
    /**
74
     * Test method for {@link org.gvsig.tools.observer.impl.BaseObservable#dis}.
74
     * Test method for {@link org.gvsig.tools.observer.impl.BaseWeakReferencingObservable#dis}.
75 75
     */
76 76
    public void testDisableNotifications() {
77 77
        // The observer must not be notified
......
86 86

  
87 87
    /**
88 88
     * Test method for
89
     * {@link org.gvsig.tools.observer.impl.BaseObservable#isEnabledNotifications()}
89
     * {@link org.gvsig.tools.observer.impl.BaseWeakReferencingObservable#isEnabledNotifications()}
90 90
     * .
91 91
     */
92 92
    public void testIsEnabledNotifications() {
......
101 101

  
102 102
    /**
103 103
     * Test method for
104
     * {@link org.gvsig.tools.observer.impl.BaseObservable#addObserver(org.gvsig.tools.observer.Observer)}
104
     * {@link org.gvsig.tools.observer.impl.BaseWeakReferencingObservable#addObserver(org.gvsig.tools.observer.Observer)}
105 105
     * .
106 106
     */
107 107
    public void testAddObserverObserver() {
......
114 114

  
115 115
    /**
116 116
     * Test method for
117
     * {@link org.gvsig.tools.observer.impl.BaseObservable#addObserver(java.lang.ref.Reference)}
117
     * {@link org.gvsig.tools.observer.impl.BaseWeakReferencingObservable#addObserver(java.lang.ref.Reference)}
118 118
     * .
119 119
     */
120 120
    public void testAddObserverReference() {
......
135 135
    // }
136 136
    /**
137 137
     * Test method for
138
     * {@link org.gvsig.tools.observer.impl.BaseObservable#deleteObserver(org.gvsig.tools.observer.Observer)}
138
     * {@link org.gvsig.tools.observer.impl.BaseWeakReferencingObservable#deleteObserver(org.gvsig.tools.observer.Observer)}
139 139
     * .
140 140
     */
141 141
    public void testDeleteObserverObserver() {
......
147 147

  
148 148
    /**
149 149
     * Test method for
150
     * {@link org.gvsig.tools.observer.impl.BaseObservable#deleteObserver(java.lang.ref.Reference)}
150
     * {@link org.gvsig.tools.observer.impl.BaseWeakReferencingObservable#deleteObserver(java.lang.ref.Reference)}
151 151
     * .
152 152
     */
153 153
    public void testDeleteObserverReference() {
branches/v2_0_0_prep/libraries/libTools/src/org/gvsig/tools/observer/ObservableWithWeakReferences.java
1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 */
22

  
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2008 IVER T.I. S.A.   {{Task}}
26
 */
27
package org.gvsig.tools.observer;
28

  
29

  
30
public interface ObservableWithWeakReferences extends Observable {
31

  
32
}
branches/v2_0_0_prep/libraries/libTools/src/org/gvsig/tools/observer/impl/BaseObservable.java
1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 */
22

  
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2008 IVER T.I. S.A.   {{Task}}
26
 */
27
package org.gvsig.tools.observer.impl;
28

  
29
import java.lang.ref.Reference;
30
import java.lang.ref.WeakReference;
31
import java.util.ArrayList;
32
import java.util.Iterator;
33
import java.util.List;
34

  
35
import org.gvsig.tools.observer.ComplexObservable;
36
import org.gvsig.tools.observer.ObservableWithWeakReferences;
37
import org.gvsig.tools.observer.Observer;
38

  
39
/**
40
 * Implementation for observers based on the use of Reference, instead of direct
41
 * Observer references.
42
 * 
43
 * This way an Observer may be Garbagge collected if its unique reference is the
44
 * one registered into the Observable.
45
 * 
46
 * @author <a href="mailto:josemanuel.vivo@iver.es">Jos? Manuel Viv?</a>
47
 * @author <a href="mailto:cordin@disid.com">C?sar Ordi?ana</a>
48
 */
49
public class BaseObservable implements ComplexObservable {
50

  
51
    private boolean propageNotifications = true;
52
    private boolean inComplex = false;
53
    private ComplexNotification complexNotification = null;
54

  
55
    private boolean changed = false;
56
    private List obs = new ArrayList();
57

  
58
    /**
59
     * Adds an observer to the set of observers for this object, provided that
60
     * it is not the same as some observer already in the set. The order in
61
     * which notifications will be delivered to multiple observers is not
62
     * specified. See the class comment.
63
     * 
64
     * @param observer
65
     *            an observer to be added.
66
     * @throws NullPointerException
67
     *             if the parameter o is null.
68
     */
69
    public void addObserver(Observer observer) {
70
        addObserver(new WeakReference(observer));
71
    }
72

  
73
    public void addObserver(Reference ref) {
74
        if (ref == null || ref.get() == null) {
75
            throw new NullPointerException();
76
        }
77
        Observer observer = (Observer) ref.get();
78
        synchronized (obs) {
79
            if (!contains(observer)) {
80
                obs.add(ref);
81
            }
82
        }
83
    }
84

  
85
    public void addObservers(BaseObservable observable) {
86
        observable.clearDeadReferences();
87
        Iterator iter = observable.obs.iterator();
88
        while (iter.hasNext()) {
89
            addObserver((Reference) iter.next());
90
        }
91

  
92
    }
93

  
94
    /**
95
     * Deletes an observer from the set of observers of this object. Passing
96
     * <CODE>null</CODE> to this method will have no effect.
97
     * 
98
     * @param observer
99
     *            the observer to be deleted.
100
     */
101
    public void deleteObserver(Observer observer) {
102
        deleteObserverReferenced(observer);
103
    }
104

  
105
    public void deleteObserver(Reference ref) {
106
        synchronized (obs) {
107
            obs.remove(ref);
108
        }
109
        deleteObserverReferenced((Observer) ref.get());
110
    }
111

  
112
    /**
113
     * If this object has changed, as indicated by the <code>hasChanged</code>
114
     * method, then notify all of its observers and then call the
115
     * <code>clearChanged</code> method to indicate that this object has no
116
     * longer changed.
117
     * <p>
118
     * Each observer has its <code>update</code> method called with two
119
     * arguments: this observable object and <code>null</code>. In other words,
120
     * this method is equivalent to: <blockquote><tt>
121
     * notifyObservers(null)</tt>
122
     * </blockquote>
123
     * 
124
     * @see java.util.Observable#clearChanged()
125
     * @see java.util.Observable#hasChanged()
126
     * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
127
     */
128
    public void notifyObservers() {
129
        notifyObservers(null);
130
    }
131

  
132
    /**
133
     * If this object has changed, as indicated by the <code>hasChanged</code>
134
     * method, then notify all of its observers and then call the
135
     * <code>clearChanged</code> method to indicate that this object has no
136
     * longer changed.
137
     * <p>
138
     * Each observer has its <code>update</code> method called with two
139
     * arguments: this observable object and the <code>arg</code> argument.
140
     * 
141
     * @param arg
142
     *            any object.
143
     * @see java.util.Observable#clearChanged()
144
     * @see java.util.Observable#hasChanged()
145
     * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
146
     */
147
    public void notifyObservers(Object arg) {
148
        if (!inComplex()) {
149
            setChanged();
150
            notify(this, arg);
151
        } else {
152
            complexNotification.addNotification(arg);
153
        }
154

  
155
    }
156

  
157
    /**
158
     * Clears the observer list so that this object no longer has any observers.
159
     */
160
    public void deleteObservers() {
161
        synchronized (obs) {
162
            obs.clear();
163
        }
164
    }
165

  
166
    /**
167
     * Returns the number of observers of this object.
168
     * 
169
     * @return the number of observers of this object.
170
     */
171
    public int countObservers() {
172
        clearDeadReferences();
173
        synchronized (obs) {
174
            return obs.size();
175
        }
176
    }
177

  
178
    public void enableNotifications() {
179
        clearDeadReferences();
180
        propageNotifications = true;
181
    }
182

  
183
    public void disableNotifications() {
184
        propageNotifications = false;
185
    }
186

  
187
    public boolean isEnabledNotifications() {
188
        return propageNotifications;
189
    }
190

  
191
    public boolean inComplex() {
192
        return inComplex;
193
    }
194

  
195
    public void beginComplexNotification() {
196
        clearDeadReferences();
197
        clearChanged();
198
        inComplex = true;
199
        complexNotification = new ComplexNotification();
200
        complexNotification.clear();
201
    }
202

  
203
    public void endComplexNotification() {
204
        inComplex = false;
205
        setChanged();
206

  
207
        Iterator iter = complexNotification.getIterator();
208
        while (iter.hasNext()) {
209
            notify(this, iter.next());
210
        }
211
        complexNotification = null;
212
    }
213

  
214
    protected void notify(ObservableWithWeakReferences observable, Object object) {
215
        if (!isEnabledNotifications()) {
216
            return;
217
        }
218

  
219
        /*
220
         * a temporary array buffer, used as a snapshot of the state of current
221
         * Observers.
222
         */
223
        Object[] arrLocal;
224

  
225
        synchronized (obs) {
226
            /*
227
             * We don't want the Observer doing callbacks into arbitrary code
228
             * while holding its own Monitor. The code where we extract each
229
             * DefaultObservable from the Vector and store the state of the
230
             * Observer needs synchronization, but notifying observers does not
231
             * (should not). The worst result of any potential race-condition
232
             * here is that: 1) a newly-added Observer will miss a notification
233
             * in progress 2) a recently unregistered Observer will be wrongly
234
             * notified when it doesn't care
235
             */
236
            if (!changed) {
237
                return;
238
            }
239
            arrLocal = obs.toArray();
240
            clearChanged();
241
        }
242

  
243
        // Go through all the registered observers and call update on them.
244
        // If any of the Reference is null, remove it from the list.
245
        for (int i = arrLocal.length - 1; i >= 0; i--) {
246
            Observer observer = (Observer) ((Reference) arrLocal[i]).get();
247
            if (observer == null) {
248
                obs.remove(arrLocal[i]);
249
            } else {
250
                observer.update(observable, object);
251
            }
252
        }
253
    }
254

  
255
    /**
256
     * Tests if this object has changed.
257
     * 
258
     * @return <code>true</code> if and only if the <code>setChanged</code>
259
     *         method has been called more recently than the
260
     *         <code>clearChanged</code> method on this object;
261
     *         <code>false</code> otherwise.
262
     * @see java.util.Observable#clearChanged()
263
     * @see java.util.Observable#setChanged()
264
     */
265
    protected boolean hasChanged() {
266
        return changed;
267
    }
268

  
269
    /**
270
     * Marks this <tt>DefaultObservable</tt> object as having been changed; the
271
     * <tt>hasChanged</tt> method will now return <tt>true</tt>.
272
     */
273
    protected void setChanged() {
274
        changed = true;
275
    }
276

  
277
    /**
278
     * Indicates that this object has no longer changed, or that it has already
279
     * notified all of its observers of its most recent change, so that the
280
     * <tt>hasChanged</tt> method will now return <tt>false</tt>. This method is
281
     * called automatically by the <code>notifyObservers</code> methods.
282
     * 
283
     * @see java.util.Observable#notifyObservers()
284
     * @see java.util.Observable#notifyObservers(java.lang.Object)
285
     */
286
    protected void clearChanged() {
287
        changed = false;
288
    }
289

  
290
    private void clearDeadReferences() {
291
        synchronized (obs) {
292
            Iterator iter = obs.iterator();
293
            while (iter.hasNext()) {
294
                Object obj = iter.next();
295
                if (obj instanceof Reference && ((Reference) obj).get() == null) {
296
                    iter.remove();
297
                }
298
            }
299
        }
300
    }
301

  
302
    private boolean contains(Observer observer) {
303
        synchronized (obs) {
304
            Iterator iter = obs.iterator();
305
            while (iter.hasNext()) {
306
                Object obj = iter.next();
307
                if (obj instanceof Reference) {
308
                    Object value = ((Reference) obj).get();
309
                    if (observer.equals(value)) {
310
                        return true;
311
                    }
312
                }
313
            }
314
        }
315
        return false;
316
    }
317

  
318
    private void deleteObserverReferenced(Observer observer) {
319
        if (observer == null) {
320
            return;
321
        }
322
        synchronized (obs) {
323
            Iterator iter = obs.iterator();
324
            while (iter.hasNext()) {
325
                Object obj = iter.next();
326
                if (obj instanceof Reference) {
327
                    Object value = ((Reference) obj).get();
328
                    if (value == null || observer.equals(value)) {
329
                        iter.remove();
330
                    }
331
                }
332
            }
333
        }
334
    }
335
}
branches/v2_0_0_prep/libraries/libTools/src/org/gvsig/tools/observer/impl/DelegateObservable.java
1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Gobernment (CIT)
5
 * 
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 * 
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 * 
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
19
 * MA  02110-1301, USA.
20
 * 
21
 */
22

  
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2008 {DiSiD Technologies}  {{Task}}
26
 */
27
package org.gvsig.tools.observer.impl;
28

  
29
import org.gvsig.tools.observer.ObservableWithWeakReferences;
30

  
31
/**
32
 * Observer implementation which uses another Observable as the parameter for
33
 * the notification to the registered Observers.
34
 * 
35
 * Most useful to be used as a delegate by Observable clases that can't extend
36
 * the BaseObservable.
37
 * 
38
 * @author <a href="mailto:cordin@disid.com">C?sar Ordi?ana</a>
39
 */
40
public class DelegateObservable extends BaseObservable {
41

  
42
    private ObservableWithWeakReferences delegated;
43

  
44
    /**
45
     * Creates a new DelegateObservable with the Observable to be used to notify
46
     * the Observers.
47
     */
48
    public DelegateObservable(ObservableWithWeakReferences observable) {
49
        delegated = observable;
50
    }
51

  
52
    protected void notify(ObservableWithWeakReferences observable, Object object) {
53
        super.notify(delegated, object);
54
    }
55
}
branches/v2_0_0_prep/libraries/libTools/src/org/gvsig/tools/observer/impl/BaseWeakReferencingObservable.java
1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 */
22

  
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2008 IVER T.I. S.A.   {{Task}}
26
 */
27
package org.gvsig.tools.observer.impl;
28

  
29
import java.lang.ref.Reference;
30
import java.lang.ref.WeakReference;
31
import java.util.ArrayList;
32
import java.util.Iterator;
33
import java.util.List;
34

  
35
import org.gvsig.tools.observer.ComplexWeakReferencingObservable;
36
import org.gvsig.tools.observer.WeakReferencingObservable;
37
import org.gvsig.tools.observer.Observer;
38

  
39
/**
40
 * Implementation for observers based on the use of Reference, instead of direct
41
 * Observer references.
42
 * 
43
 * This way an Observer may be Garbagge collected if its unique reference is the
44
 * one registered into the Observable.
45
 * 
46
 * @author <a href="mailto:josemanuel.vivo@iver.es">Jos? Manuel Viv?</a>
47
 * @author <a href="mailto:cordin@disid.com">C?sar Ordi?ana</a>
48
 */
49
public class BaseWeakReferencingObservable implements ComplexWeakReferencingObservable {
50

  
51
    private boolean propageNotifications = true;
52
    private boolean inComplex = false;
53
    private ComplexNotification complexNotification = null;
54

  
55
    private boolean changed = false;
56
    private List obs = new ArrayList();
57

  
58
    /**
59
     * Adds an observer to the set of observers for this object, provided that
60
     * it is not the same as some observer already in the set. The order in
61
     * which notifications will be delivered to multiple observers is not
62
     * specified. See the class comment.
63
     * 
64
     * @param observer
65
     *            an observer to be added.
66
     * @throws NullPointerException
67
     *             if the parameter o is null.
68
     */
69
    public void addObserver(Observer observer) {
70
        addObserver(new WeakReference(observer));
71
    }
72

  
73
    public void addObserver(Reference ref) {
74
        if (ref == null || ref.get() == null) {
75
            throw new NullPointerException();
76
        }
77
        Observer observer = (Observer) ref.get();
78
        synchronized (obs) {
79
            if (!contains(observer)) {
80
                obs.add(ref);
81
            }
82
        }
83
    }
84

  
85
    public void addObservers(BaseWeakReferencingObservable observable) {
86
        observable.clearDeadReferences();
87
        Iterator iter = observable.obs.iterator();
88
        while (iter.hasNext()) {
89
            addObserver((Reference) iter.next());
90
        }
91

  
92
    }
93

  
94
    /**
95
     * Deletes an observer from the set of observers of this object. Passing
96
     * <CODE>null</CODE> to this method will have no effect.
97
     * 
98
     * @param observer
99
     *            the observer to be deleted.
100
     */
101
    public void deleteObserver(Observer observer) {
102
        deleteObserverReferenced(observer);
103
    }
104

  
105
    public void deleteObserver(Reference ref) {
106
        synchronized (obs) {
107
            obs.remove(ref);
108
        }
109
        deleteObserverReferenced((Observer) ref.get());
110
    }
111

  
112
    /**
113
     * If this object has changed, as indicated by the <code>hasChanged</code>
114
     * method, then notify all of its observers and then call the
115
     * <code>clearChanged</code> method to indicate that this object has no
116
     * longer changed.
117
     * <p>
118
     * Each observer has its <code>update</code> method called with two
119
     * arguments: this observable object and <code>null</code>. In other words,
120
     * this method is equivalent to: <blockquote><tt>
121
     * notifyObservers(null)</tt>
122
     * </blockquote>
123
     * 
124
     * @see java.util.Observable#clearChanged()
125
     * @see java.util.Observable#hasChanged()
126
     * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
127
     */
128
    public void notifyObservers() {
129
        notifyObservers(null);
130
    }
131

  
132
    /**
133
     * If this object has changed, as indicated by the <code>hasChanged</code>
134
     * method, then notify all of its observers and then call the
135
     * <code>clearChanged</code> method to indicate that this object has no
136
     * longer changed.
137
     * <p>
138
     * Each observer has its <code>update</code> method called with two
139
     * arguments: this observable object and the <code>arg</code> argument.
140
     * 
141
     * @param arg
142
     *            any object.
143
     * @see java.util.Observable#clearChanged()
144
     * @see java.util.Observable#hasChanged()
145
     * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
146
     */
147
    public void notifyObservers(Object arg) {
148
        if (!inComplex()) {
149
            setChanged();
150
            notify(this, arg);
151
        } else {
152
            complexNotification.addNotification(arg);
153
        }
154

  
155
    }
156

  
157
    /**
158
     * Clears the observer list so that this object no longer has any observers.
159
     */
160
    public void deleteObservers() {
161
        synchronized (obs) {
162
            obs.clear();
163
        }
164
    }
165

  
166
    /**
167
     * Returns the number of observers of this object.
168
     * 
169
     * @return the number of observers of this object.
170
     */
171
    public int countObservers() {
172
        clearDeadReferences();
173
        synchronized (obs) {
174
            return obs.size();
175
        }
176
    }
177

  
178
    public void enableNotifications() {
179
        clearDeadReferences();
180
        propageNotifications = true;
181
    }
182

  
183
    public void disableNotifications() {
184
        propageNotifications = false;
185
    }
186

  
187
    public boolean isEnabledNotifications() {
188
        return propageNotifications;
189
    }
190

  
191
    public boolean inComplex() {
192
        return inComplex;
193
    }
194

  
195
    public void beginComplexNotification() {
196
        clearDeadReferences();
197
        clearChanged();
198
        inComplex = true;
199
        complexNotification = new ComplexNotification();
200
        complexNotification.clear();
201
    }
202

  
203
    public void endComplexNotification() {
204
        inComplex = false;
205
        setChanged();
206

  
207
        Iterator iter = complexNotification.getIterator();
208
        while (iter.hasNext()) {
209
            notify(this, iter.next());
210
        }
211
        complexNotification = null;
212
    }
213

  
214
    protected void notify(WeakReferencingObservable observable, Object object) {
215
        if (!isEnabledNotifications()) {
216
            return;
217
        }
218

  
219
        /*
220
         * a temporary array buffer, used as a snapshot of the state of current
221
         * Observers.
222
         */
223
        Object[] arrLocal;
224

  
225
        synchronized (obs) {
226
            /*
227
             * We don't want the Observer doing callbacks into arbitrary code
228
             * while holding its own Monitor. The code where we extract each
229
             * DefaultObservable from the Vector and store the state of the
230
             * Observer needs synchronization, but notifying observers does not
231
             * (should not). The worst result of any potential race-condition
232
             * here is that: 1) a newly-added Observer will miss a notification
233
             * in progress 2) a recently unregistered Observer will be wrongly
234
             * notified when it doesn't care
235
             */
236
            if (!changed) {
237
                return;
238
            }
239
            arrLocal = obs.toArray();
240
            clearChanged();
241
        }
242

  
243
        // Go through all the registered observers and call update on them.
244
        // If any of the Reference is null, remove it from the list.
245
        for (int i = arrLocal.length - 1; i >= 0; i--) {
246
            Observer observer = (Observer) ((Reference) arrLocal[i]).get();
247
            if (observer == null) {
248
                obs.remove(arrLocal[i]);
249
            } else {
250
                observer.update(observable, object);
251
            }
252
        }
253
    }
254

  
255
    /**
256
     * Tests if this object has changed.
257
     * 
258
     * @return <code>true</code> if and only if the <code>setChanged</code>
259
     *         method has been called more recently than the
260
     *         <code>clearChanged</code> method on this object;
261
     *         <code>false</code> otherwise.
262
     * @see java.util.Observable#clearChanged()
263
     * @see java.util.Observable#setChanged()
264
     */
265
    protected boolean hasChanged() {
266
        return changed;
267
    }
268

  
269
    /**
270
     * Marks this <tt>DefaultObservable</tt> object as having been changed; the
271
     * <tt>hasChanged</tt> method will now return <tt>true</tt>.
272
     */
273
    protected void setChanged() {
274
        changed = true;
275
    }
276

  
277
    /**
278
     * Indicates that this object has no longer changed, or that it has already
279
     * notified all of its observers of its most recent change, so that the
280
     * <tt>hasChanged</tt> method will now return <tt>false</tt>. This method is
281
     * called automatically by the <code>notifyObservers</code> methods.
282
     * 
283
     * @see java.util.Observable#notifyObservers()
284
     * @see java.util.Observable#notifyObservers(java.lang.Object)
285
     */
286
    protected void clearChanged() {
287
        changed = false;
288
    }
289

  
290
    private void clearDeadReferences() {
291
        synchronized (obs) {
292
            Iterator iter = obs.iterator();
293
            while (iter.hasNext()) {
294
                Object obj = iter.next();
295
                if (obj instanceof Reference && ((Reference) obj).get() == null) {
296
                    iter.remove();
297
                }
298
            }
299
        }
300
    }
301

  
302
    private boolean contains(Observer observer) {
303
        synchronized (obs) {
304
            Iterator iter = obs.iterator();
305
            while (iter.hasNext()) {
306
                Object obj = iter.next();
307
                if (obj instanceof Reference) {
308
                    Object value = ((Reference) obj).get();
309
                    if (observer.equals(value)) {
310
                        return true;
311
                    }
312
                }
313
            }
314
        }
315
        return false;
316
    }
317

  
318
    private void deleteObserverReferenced(Observer observer) {
319
        if (observer == null) {
320
            return;
321
        }
322
        synchronized (obs) {
323
            Iterator iter = obs.iterator();
324
            while (iter.hasNext()) {
325
                Object obj = iter.next();
326
                if (obj instanceof Reference) {
327
                    Object value = ((Reference) obj).get();
328
                    if (value == null || observer.equals(value)) {
329
                        iter.remove();
330
                    }
331
                }
332
            }
333
        }
334
    }
335
}
0 336

  
branches/v2_0_0_prep/libraries/libTools/src/org/gvsig/tools/observer/impl/DelegateWeakReferencingObservable.java
1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Gobernment (CIT)
5
 * 
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 * 
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 * 
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
19
 * MA  02110-1301, USA.
20
 * 
21
 */
22

  
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2008 {DiSiD Technologies}  {{Task}}
26
 */
27
package org.gvsig.tools.observer.impl;
28

  
29
import org.gvsig.tools.observer.WeakReferencingObservable;
30

  
31
/**
32
 * Observer implementation which uses another Observable as the parameter for
33
 * the notification to the registered Observers.
34
 * 
35
 * Most useful to be used as a delegate by Observable clases that can't extend
36
 * the BaseObservable.
37
 * 
38
 * @author <a href="mailto:cordin@disid.com">C?sar Ordi?ana</a>
39
 */
40
public class DelegateWeakReferencingObservable extends BaseWeakReferencingObservable {
41

  
42
    private WeakReferencingObservable delegated;
43

  
44
    /**
45
     * Creates a new DelegateObservable with the Observable to be used to notify
46
     * the Observers.
47
     */
48
    public DelegateWeakReferencingObservable(WeakReferencingObservable observable) {
49
        delegated = observable;
50
    }
51

  
52
    protected void notify(WeakReferencingObservable observable, Object object) {
53
        super.notify(delegated, object);
54
    }
55
}
branches/v2_0_0_prep/libraries/libTools/src/org/gvsig/tools/observer/WeakReferencingObservable.java
1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 */
22

  
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2008 IVER T.I. S.A.   {{Task}}
26
 */
27
package org.gvsig.tools.observer;
28

  
29

  
30
public interface WeakReferencingObservable extends Observable {
31

  
32
}
0 33

  
branches/v2_0_0_prep/libraries/libTools/src/org/gvsig/tools/observer/Observer.java
29 29

  
30 30
public interface Observer {
31 31

  
32
	public void update(ObservableWithWeakReferences observable,Object notification);
32
	public void update(WeakReferencingObservable observable,Object notification);
33 33

  
34 34
}
branches/v2_0_0_prep/libraries/libTools/src/org/gvsig/tools/observer/ComplexObservable.java
1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Gobernment (CIT)
5
 * 
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 * 
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 * 
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
19
 * MA  02110-1301, USA.
20
 * 
21
 */
22

  
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2008 {DiSiD Technologies}  {{Task}}
26
 */
27 1
package org.gvsig.tools.observer;
28 2

  
29
/**
30
 * Adds operations to the Observable to perform complex notifications (a group
31
 * of notifications to be performed in group), and to be able to enable/disable
32
 * notifications.
33
 * 
34
 * @author <a href="mailto:cordin@disid.com">C?sar Ordi?ana</a>
35
 */
36
public interface ComplexObservable extends ObservableWithWeakReferences {
3
public interface ComplexObservable {
37 4

  
38 5
    /**
39
     * Disable the notification of events to registered Observers.
40
     */
41
    void disableNotifications();
6
	 * Disable the notification of events to registered Observers.
7
	 */
8
	void disableNotifications();
42 9

  
43
    /**
44
     * Enable (default) the notification of events to registered Observers.
45
     */
46
    void enableNotifications();
10
	/**
11
	 * Enable (default) the notification of events to registered Observers.
12
	 */
13
	void enableNotifications();
47 14

  
48
    /**
49
     * Sets the Observable in complex notification mode. All notifications must
50
     * be stored, until the mode ends, and then notify all Observers with all
51
     * the notifications.
52
     */
53
    void beginComplexNotification();
15
	/**
16
	 * Sets the Observable in complex notification mode. All notifications must
17
	 * be stored, until the mode ends, and then notify all Observers with all
18
	 * the notifications.
19
	 */
20
	void beginComplexNotification();
54 21

  
55
    /**
56
     * Ends the complex notification mode. All notifications stored while in
57
     * complex notification mode, will be notified to the registered Observers.
58
     */
59
    void endComplexNotification();
22
	/**
23
	 * Ends the complex notification mode. All notifications stored while in
24
	 * complex notification mode, will be notified to the registered Observers.
25
	 */
26
	void endComplexNotification();
60 27
}
61 28

  
branches/v2_0_0_prep/libraries/libTools/src/org/gvsig/tools/observer/ComplexWeakReferencingObservable.java
1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Gobernment (CIT)
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 */
22

  
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2008 {DiSiD Technologies}  {{Task}}
26
 */
27
package org.gvsig.tools.observer;
28

  
29
/**
30
 * Adds operations to the Observable to perform complex notifications (a group
31
 * of notifications to be performed in group), and to be able to enable/disable
32
 * notifications.
33
 *
34
 * @author <a href="mailto:cordin@disid.com">C?sar Ordi?ana</a>
35
 */
36
public interface ComplexWeakReferencingObservable extends ComplexObservable,
37
		WeakReferencingObservable {
38

  
39
}

Also available in: Unified diff