source: josm/trunk/src/org/openstreetmap/josm/data/osm/ChangesetCache.java@ 9519

Last change on this file since 9519 was 9519, checked in by simon04, 8 years ago

fix #7090 - Upload dialog allow select another user open changeset

  • Property svn:eol-style set to native
File size: 7.4 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.osm;
3
4import java.util.ArrayList;
5import java.util.Collection;
6import java.util.HashMap;
7import java.util.HashSet;
8import java.util.List;
9import java.util.Map;
10import java.util.Set;
11import java.util.concurrent.CopyOnWriteArrayList;
12
13import org.openstreetmap.josm.Main;
14import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
15import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
16import org.openstreetmap.josm.gui.JosmUserIdentityManager;
17import org.openstreetmap.josm.gui.util.GuiHelper;
18import org.openstreetmap.josm.tools.Predicate;
19import org.openstreetmap.josm.tools.Utils;
20
21/**
22 * ChangesetCache is global in-memory cache for changesets downloaded from
23 * an OSM API server. The unique instance is available as singleton, see
24 * {@link #getInstance()}.
25 *
26 * Clients interested in cache updates can register for {@link ChangesetCacheEvent}s
27 * using {@link #addChangesetCacheListener(ChangesetCacheListener)}. They can use
28 * {@link #removeChangesetCacheListener(ChangesetCacheListener)} to unregister as
29 * cache event listener.
30 *
31 * The cache itself listens to {@link java.util.prefs.PreferenceChangeEvent}s. It
32 * clears itself if the OSM API URL is changed in the preferences.
33 *
34 * {@link ChangesetCacheEvent}s are delivered on the EDT.
35 *
36 */
37public final class ChangesetCache implements PreferenceChangedListener {
38 /** the unique instance */
39 private static final ChangesetCache instance = new ChangesetCache();
40
41 /**
42 * Replies the unique instance of the cache
43 *
44 * @return the unique instance of the cache
45 */
46 public static ChangesetCache getInstance() {
47 return instance;
48 }
49
50 /** the cached changesets */
51 private final Map<Integer, Changeset> cache = new HashMap<>();
52
53 private final CopyOnWriteArrayList<ChangesetCacheListener> listeners = new CopyOnWriteArrayList<>();
54
55 private ChangesetCache() {
56 Main.pref.addPreferenceChangeListener(this);
57 }
58
59 public void addChangesetCacheListener(ChangesetCacheListener listener) {
60 if (listener != null) {
61 listeners.addIfAbsent(listener);
62 }
63 }
64
65 public void removeChangesetCacheListener(ChangesetCacheListener listener) {
66 if (listener != null) {
67 listeners.remove(listener);
68 }
69 }
70
71 protected void fireChangesetCacheEvent(final ChangesetCacheEvent e) {
72 GuiHelper.runInEDT(new Runnable() {
73 @Override public void run() {
74 for (ChangesetCacheListener l: listeners) {
75 l.changesetCacheUpdated(e);
76 }
77 }
78 });
79 }
80
81 protected void update(Changeset cs, DefaultChangesetCacheEvent e) {
82 if (cs == null) return;
83 if (cs.isNew()) return;
84 Changeset inCache = cache.get(cs.getId());
85 if (inCache != null) {
86 inCache.mergeFrom(cs);
87 e.rememberUpdatedChangeset(inCache);
88 } else {
89 e.rememberAddedChangeset(cs);
90 cache.put(cs.getId(), cs);
91 }
92 }
93
94 public void update(Changeset cs) {
95 DefaultChangesetCacheEvent e = new DefaultChangesetCacheEvent(this);
96 update(cs, e);
97 fireChangesetCacheEvent(e);
98 }
99
100 public void update(Collection<Changeset> changesets) {
101 if (changesets == null || changesets.isEmpty()) return;
102 DefaultChangesetCacheEvent e = new DefaultChangesetCacheEvent(this);
103 for (Changeset cs: changesets) {
104 update(cs, e);
105 }
106 fireChangesetCacheEvent(e);
107 }
108
109 public boolean contains(int id) {
110 if (id <= 0) return false;
111 return cache.get(id) != null;
112 }
113
114 public boolean contains(Changeset cs) {
115 if (cs == null) return false;
116 if (cs.isNew()) return false;
117 return contains(cs.getId());
118 }
119
120 public Changeset get(int id) {
121 return cache.get(id);
122 }
123
124 public Set<Changeset> getChangesets() {
125 return new HashSet<>(cache.values());
126 }
127
128 protected void remove(int id, DefaultChangesetCacheEvent e) {
129 if (id <= 0) return;
130 Changeset cs = cache.get(id);
131 if (cs == null) return;
132 cache.remove(id);
133 e.rememberRemovedChangeset(cs);
134 }
135
136 public void remove(int id) {
137 DefaultChangesetCacheEvent e = new DefaultChangesetCacheEvent(this);
138 remove(id, e);
139 if (!e.isEmpty()) {
140 fireChangesetCacheEvent(e);
141 }
142 }
143
144 public void remove(Changeset cs) {
145 if (cs == null) return;
146 if (cs.isNew()) return;
147 remove(cs.getId());
148 }
149
150 /**
151 * Removes the changesets in <code>changesets</code> from the cache. A
152 * {@link ChangesetCacheEvent} is fired.
153 *
154 * @param changesets the changesets to remove. Ignored if null.
155 */
156 public void remove(Collection<Changeset> changesets) {
157 if (changesets == null) return;
158 DefaultChangesetCacheEvent evt = new DefaultChangesetCacheEvent(this);
159 for (Changeset cs : changesets) {
160 if (cs == null || cs.isNew()) {
161 continue;
162 }
163 remove(cs.getId(), evt);
164 }
165 if (!evt.isEmpty()) {
166 fireChangesetCacheEvent(evt);
167 }
168 }
169
170 public int size() {
171 return cache.size();
172 }
173
174 public void clear() {
175 DefaultChangesetCacheEvent e = new DefaultChangesetCacheEvent(this);
176 for (Changeset cs: cache.values()) {
177 e.rememberRemovedChangeset(cs);
178 }
179 cache.clear();
180 fireChangesetCacheEvent(e);
181 }
182
183 /**
184 * Replies the list of open changesets.
185 * @return The list of open changesets
186 */
187 public List<Changeset> getOpenChangesets() {
188 List<Changeset> ret = new ArrayList<>();
189 for (Changeset cs: cache.values()) {
190 if (cs.isOpen()) {
191 ret.add(cs);
192 }
193 }
194 return ret;
195 }
196
197 /**
198 * If the current user {@link JosmUserIdentityManager#isAnonymous() is known}, the {@link #getOpenChangesets() open changesets}
199 * for the {@link JosmUserIdentityManager#isCurrentUser(User) current user} are returned. Otherwise,
200 * the unfiltered {@link #getOpenChangesets() open changesets} are returned.
201 *
202 * @return a list of changesets
203 */
204 public List<Changeset> getOpenChangesetsForCurrentUser() {
205 if (JosmUserIdentityManager.getInstance().isAnonymous()) {
206 return getOpenChangesets();
207 } else {
208 return new ArrayList<>(Utils.filter(getOpenChangesets(), new Predicate<Changeset>() {
209 @Override
210 public boolean evaluate(Changeset object) {
211 return JosmUserIdentityManager.getInstance().isCurrentUser(object.getUser());
212 }
213 }));
214 }
215 }
216
217 /* ------------------------------------------------------------------------- */
218 /* interface PreferenceChangedListener */
219 /* ------------------------------------------------------------------------- */
220 @Override
221 public void preferenceChanged(PreferenceChangeEvent e) {
222 if (e.getKey() == null || !"osm-server.url".equals(e.getKey()))
223 return;
224
225 // clear the cache when the API url changes
226 if (e.getOldValue() == null || e.getNewValue() == null || !e.getOldValue().equals(e.getNewValue())) {
227 clear();
228 }
229 }
230}
Note: See TracBrowser for help on using the repository browser.