OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 73 | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 73 Rev 182
Line 1... Line 1...
1
/*
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 * 
3
 * 
4
 * Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
4
 * Copyright 2011-2019 OpenConcerto, by ILM Informatique. All rights reserved.
5
 * 
5
 * 
6
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
6
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
7
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
7
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
8
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
8
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
9
 * language governing permissions and limitations under the License.
9
 * language governing permissions and limitations under the License.
Line 19... Line 19...
19
import java.util.Iterator;
19
import java.util.Iterator;
20
import java.util.List;
20
import java.util.List;
21
 
21
 
22
/**
22
/**
23
 * A class that wraps a list, to detect every change made to it. The changes are available with
23
 * A class that wraps a list, to detect every change made to it. The changes are available with
24
 * {@link #getRecipe()}.
24
 * {@link #getRecipe()}. Thread-safe if the delegate is itself thread-safe and not keeping history.
25
 * 
25
 *
26
 * @author Sylvain
26
 * @author Sylvain
27
 * 
27
 *
28
 * @param <E> type of items.
28
 * @param <E> type of items.
29
 */
29
 */
30
public class ListChangeRecorder<E> extends AbstractList<E> {
30
public class ListChangeRecorder<E> extends AbstractList<E> {
31
 
31
 
32
    private final List<E> delegate;
32
    private final List<E> delegate;
33
    private final ListChangeRecipe<E> recipe;
33
    private final ListChangeRecipe<E> recipe;
34
 
34
 
35
    public ListChangeRecorder(List<E> delegate) {
35
    public ListChangeRecorder(final List<E> delegate) {
36
        this(delegate, false);
36
        this(delegate, false);
37
    }
37
    }
38
 
38
 
39
    public ListChangeRecorder(List<E> delegate, final boolean keepHistory) {
39
    public ListChangeRecorder(final List<E> delegate, final boolean keepHistory) {
40
        super();
40
        super();
41
        this.delegate = delegate;
41
        this.delegate = delegate;
42
        this.recipe = new ListChangeRecipe<E>(keepHistory);
42
        this.recipe = new ListChangeRecipe<E>(keepHistory);
43
    }
43
    }
44
 
44
 
Line 50... Line 50...
50
    // they only call regular methods of this class, so every change made through them is recorded
50
    // they only call regular methods of this class, so every change made through them is recorded
51
    // overload a maximum of methods to keep the original behaviour/optimization of our delegate
51
    // overload a maximum of methods to keep the original behaviour/optimization of our delegate
52
 
52
 
53
    // ** read only
53
    // ** read only
54
 
54
 
-
 
55
    @Override
55
    public E get(int index) {
56
    public E get(final int index) {
56
        return this.delegate.get(index);
57
        return this.delegate.get(index);
57
    }
58
    }
58
 
59
 
-
 
60
    @Override
59
    public int size() {
61
    public int size() {
60
        return this.delegate.size();
62
        return this.delegate.size();
61
    }
63
    }
62
 
64
 
-
 
65
    @Override
63
    public Object[] toArray() {
66
    public Object[] toArray() {
64
        return this.delegate.toArray();
67
        return this.delegate.toArray();
65
    }
68
    }
66
 
69
 
-
 
70
    @Override
67
    public <T> T[] toArray(T[] a) {
71
    public <T> T[] toArray(final T[] a) {
68
        return this.delegate.toArray(a);
72
        return this.delegate.toArray(a);
69
    }
73
    }
70
 
74
 
-
 
75
    @Override
71
    public boolean contains(Object o) {
76
    public boolean contains(final Object o) {
72
        return this.delegate.contains(o);
77
        return this.delegate.contains(o);
73
    }
78
    }
74
 
79
 
-
 
80
    @Override
75
    public boolean containsAll(Collection<?> c) {
81
    public boolean containsAll(final Collection<?> c) {
76
        return this.delegate.containsAll(c);
82
        return this.delegate.containsAll(c);
77
    }
83
    }
78
 
84
 
-
 
85
    @Override
79
    public boolean equals(Object o) {
86
    public boolean equals(final Object o) {
80
        return this.delegate.equals(o);
87
        return this.delegate.equals(o);
81
    }
88
    }
82
 
89
 
-
 
90
    @Override
83
    public int hashCode() {
91
    public int hashCode() {
84
        return this.delegate.hashCode();
92
        return this.delegate.hashCode();
85
    }
93
    }
86
 
94
 
-
 
95
    @Override
87
    public int indexOf(Object o) {
96
    public int indexOf(final Object o) {
88
        return this.delegate.indexOf(o);
97
        return this.delegate.indexOf(o);
89
    }
98
    }
90
 
99
 
-
 
100
    @Override
91
    public boolean isEmpty() {
101
    public boolean isEmpty() {
92
        return this.delegate.isEmpty();
102
        return this.delegate.isEmpty();
93
    }
103
    }
94
 
104
 
-
 
105
    @Override
95
    public int lastIndexOf(Object o) {
106
    public int lastIndexOf(final Object o) {
96
        return this.delegate.lastIndexOf(o);
107
        return this.delegate.lastIndexOf(o);
97
    }
108
    }
98
 
109
 
99
    // ** write, always change the delegate before notifying the recipe
110
    // ** write, always change the delegate before notifying the recipe
100
    // otherwise the listeners will be told of the changes before they even happened
111
    // otherwise the listeners will be told of the changes before they even happened
101
 
112
 
-
 
113
    @Override
102
    public boolean add(E e) {
114
    public synchronized boolean add(final E e) {
103
        final boolean res = this.delegate.add(e);
115
        final boolean res = this.delegate.add(e);
104
        // -1 since this just grew by one
116
        // -1 since this just grew by one
105
        this.recipe.add(this.size() - 1, Collections.singleton(e));
117
        this.recipe.add(this.size() - 1, Collections.singleton(e));
106
        return res;
118
        return res;
107
    }
119
    }
108
 
120
 
-
 
121
    @Override
109
    public void add(int index, E e) {
122
    public synchronized void add(final int index, final E e) {
110
        this.delegate.add(index, e);
123
        this.delegate.add(index, e);
111
        this.recipe.add(index, Collections.singleton(e));
124
        this.recipe.add(index, Collections.singleton(e));
112
    }
125
    }
113
 
126
 
-
 
127
    @Override
114
    public boolean addAll(Collection<? extends E> c) {
128
    public synchronized boolean addAll(final Collection<? extends E> c) {
115
        final int size = this.size();
129
        final int size = this.size();
116
        final boolean res = this.delegate.addAll(c);
130
        final boolean res = this.delegate.addAll(c);
117
        this.recipe.add(size, c);
131
        this.recipe.add(size, c);
118
        return res;
132
        return res;
119
    }
133
    }
120
 
134
 
-
 
135
    @Override
121
    public boolean addAll(int index, Collection<? extends E> c) {
136
    public synchronized boolean addAll(final int index, final Collection<? extends E> c) {
122
        final boolean res = this.delegate.addAll(index, c);
137
        final boolean res = this.delegate.addAll(index, c);
123
        this.recipe.add(index, c);
138
        this.recipe.add(index, c);
124
        return res;
139
        return res;
125
    }
140
    }
126
 
141
 
-
 
142
    @Override
127
    public void clear() {
143
    public synchronized void clear() {
128
        final List<E> copy = (List<E>) ListChangeIndex.copy(this);
144
        final List<E> copy = (List<E>) ListChangeIndex.copy(this);
129
        this.delegate.clear();
145
        this.delegate.clear();
130
        this.recipe.remove(0, copy.size() - 1, copy);
146
        this.recipe.remove(0, copy.size() - 1, copy);
131
    }
147
    }
132
 
148
 
-
 
149
    @Override
133
    public E set(int index, E element) {
150
    public synchronized E set(final int index, final E element) {
134
        final E res = this.delegate.set(index, element);
151
        final E res = this.delegate.set(index, element);
135
        this.recipe.set(index, res, element);
152
        this.recipe.set(index, res, element);
136
        return res;
153
        return res;
137
    }
154
    }
138
 
155
 
-
 
156
    @Override
139
    public E remove(int index) {
157
    public synchronized E remove(final int index) {
140
        final E res = this.delegate.remove(index);
158
        final E res = this.delegate.remove(index);
141
        this.recipe.remove(index, index, Collections.singletonList(res));
159
        this.recipe.remove(index, index, Collections.singletonList(res));
142
        return res;
160
        return res;
143
    }
161
    }
144
 
162
 
145
    // objects
163
    // objects
146
 
164
 
-
 
165
    @Override
147
    public boolean remove(Object o) {
166
    public synchronized boolean remove(final Object o) {
148
        final int index = this.indexOf(o);
167
        final int index = this.indexOf(o);
149
        if (index < 0)
168
        if (index < 0)
150
            return false;
169
            return false;
151
        else {
170
        else {
152
            this.remove(index);
171
            this.remove(index);
153
            return true;
172
            return true;
154
        }
173
        }
155
    }
174
    }
156
 
175
 
-
 
176
    @Override
157
    public boolean removeAll(Collection<?> c) {
177
    public boolean removeAll(final Collection<?> c) {
158
        return this.changeAll(c, true);
178
        return this.changeAll(c, true);
159
    }
179
    }
160
 
180
 
-
 
181
    @Override
161
    public boolean retainAll(Collection<?> c) {
182
    public boolean retainAll(final Collection<?> c) {
162
        return this.changeAll(c, false);
183
        return this.changeAll(c, false);
163
    }
184
    }
164
 
185
 
165
    private boolean changeAll(Collection<?> c, boolean remove) {
186
    private synchronized boolean changeAll(final Collection<?> c, final boolean remove) {
166
        boolean modified = false;
187
        boolean modified = false;
167
        Iterator<?> e = iterator();
188
        final Iterator<?> e = iterator();
168
        while (e.hasNext()) {
189
        while (e.hasNext()) {
169
            if (c.contains(e.next()) == remove) {
190
            if (c.contains(e.next()) == remove) {
170
                e.remove();
191
                e.remove();
171
                modified = true;
192
                modified = true;
172
            }
193
            }