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

Last change on this file since 18208 was 18208, checked in by Don-vip, 3 years ago

global use of Utils.isEmpty/isBlank

  • Property svn:eol-style set to native
File size: 8.6 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;
12import java.util.stream.Collectors;
13
14import org.openstreetmap.josm.data.UserIdentityManager;
15import org.openstreetmap.josm.spi.preferences.Config;
16import org.openstreetmap.josm.spi.preferences.PreferenceChangeEvent;
17import org.openstreetmap.josm.spi.preferences.PreferenceChangedListener;
18import org.openstreetmap.josm.tools.SubclassFilteredCollection;
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 */
35public final class ChangesetCache implements PreferenceChangedListener {
36 /** the unique instance */
37 private static final ChangesetCache INSTANCE = new ChangesetCache();
38
39 /** the cached changesets */
40 private final Map<Integer, Changeset> cache = new HashMap<>();
41
42 final CopyOnWriteArrayList<ChangesetCacheListener> listeners = new CopyOnWriteArrayList<>();
43
44 /**
45 * Constructs a new {@code ChangesetCache}.
46 */
47 private ChangesetCache() {
48 Config.getPref().addPreferenceChangeListener(this);
49 }
50
51 /**
52 * Replies the unique instance of the cache
53 * @return the unique instance of the cache
54 */
55 public static ChangesetCache getInstance() {
56 return INSTANCE;
57 }
58
59 /**
60 * Add a changeset cache listener.
61 * @param listener changeset cache listener to add
62 */
63 public void addChangesetCacheListener(ChangesetCacheListener listener) {
64 if (listener != null) {
65 listeners.addIfAbsent(listener);
66 }
67 }
68
69 /**
70 * Remove a changeset cache listener.
71 * @param listener changeset cache listener to remove
72 */
73 public void removeChangesetCacheListener(ChangesetCacheListener listener) {
74 if (listener != null) {
75 listeners.remove(listener);
76 }
77 }
78
79 private void fireChangesetCacheEvent(final ChangesetCacheEvent e) {
80 for (ChangesetCacheListener l: listeners) {
81 l.changesetCacheUpdated(e);
82 }
83 }
84
85 private void update(Changeset cs, DefaultChangesetCacheEvent e) {
86 if (cs == null) return;
87 if (cs.isNew()) return;
88 Changeset inCache = cache.get(cs.getId());
89 if (inCache != null) {
90 inCache.mergeFrom(cs);
91 e.rememberUpdatedChangeset(inCache);
92 } else {
93 e.rememberAddedChangeset(cs);
94 cache.put(cs.getId(), cs);
95 }
96 }
97
98 /**
99 * Update a single changeset.
100 * @param cs changeset to update
101 */
102 public void update(Changeset cs) {
103 DefaultChangesetCacheEvent e = new DefaultChangesetCacheEvent(this);
104 update(cs, e);
105 fireChangesetCacheEvent(e);
106 }
107
108 /**
109 * Update a collection of changesets.
110 * @param changesets changesets to update
111 */
112 public void update(Collection<Changeset> changesets) {
113 if (Utils.isEmpty(changesets)) return;
114 DefaultChangesetCacheEvent e = new DefaultChangesetCacheEvent(this);
115 for (Changeset cs: changesets) {
116 update(cs, e);
117 }
118 fireChangesetCacheEvent(e);
119 }
120
121 /**
122 * Determines if the cache contains an entry for given changeset identifier.
123 * @param id changeset id
124 * @return {@code true} if the cache contains an entry for {@code id}
125 */
126 public boolean contains(int id) {
127 if (id <= 0) return false;
128 return cache.get(id) != null;
129 }
130
131 /**
132 * Determines if the cache contains an entry for given changeset.
133 * @param cs changeset
134 * @return {@code true} if the cache contains an entry for {@code cs}
135 */
136 public boolean contains(Changeset cs) {
137 if (cs == null) return false;
138 if (cs.isNew()) return false;
139 return contains(cs.getId());
140 }
141
142 /**
143 * Returns the entry for given changeset identifier.
144 * @param id changeset id
145 * @return the entry for given changeset identifier, or null
146 */
147 public Changeset get(int id) {
148 return cache.get(id);
149 }
150
151 /**
152 * Returns the list of changesets contained in the cache.
153 * @return the list of changesets contained in the cache
154 */
155 public Set<Changeset> getChangesets() {
156 return new HashSet<>(cache.values());
157 }
158
159 private void remove(int id, DefaultChangesetCacheEvent e) {
160 if (id <= 0) return;
161 Changeset cs = cache.get(id);
162 if (cs == null) return;
163 cache.remove(id);
164 e.rememberRemovedChangeset(cs);
165 }
166
167 /**
168 * Remove the entry for the given changeset identifier.
169 * A {@link ChangesetCacheEvent} is fired.
170 * @param id changeset id
171 */
172 public void remove(int id) {
173 DefaultChangesetCacheEvent e = new DefaultChangesetCacheEvent(this);
174 remove(id, e);
175 if (!e.isEmpty()) {
176 fireChangesetCacheEvent(e);
177 }
178 }
179
180 /**
181 * Remove the entry for the given changeset.
182 * A {@link ChangesetCacheEvent} is fired.
183 * @param cs changeset
184 */
185 public void remove(Changeset cs) {
186 if (cs == null) return;
187 if (cs.isNew()) return;
188 remove(cs.getId());
189 }
190
191 /**
192 * Removes the changesets in <code>changesets</code> from the cache.
193 * A {@link ChangesetCacheEvent} is fired.
194 *
195 * @param changesets the changesets to remove. Ignored if null.
196 */
197 public void remove(Collection<Changeset> changesets) {
198 if (changesets == null) return;
199 DefaultChangesetCacheEvent evt = new DefaultChangesetCacheEvent(this);
200 for (Changeset cs : changesets) {
201 if (cs == null || cs.isNew()) {
202 continue;
203 }
204 remove(cs.getId(), evt);
205 }
206 if (!evt.isEmpty()) {
207 fireChangesetCacheEvent(evt);
208 }
209 }
210
211 /**
212 * Returns the number of changesets contained in the cache.
213 * @return the number of changesets contained in the cache
214 */
215 public int size() {
216 return cache.size();
217 }
218
219 /**
220 * Clears the cache.
221 */
222 public void clear() {
223 DefaultChangesetCacheEvent e = new DefaultChangesetCacheEvent(this);
224 for (Changeset cs: cache.values()) {
225 e.rememberRemovedChangeset(cs);
226 }
227 cache.clear();
228 fireChangesetCacheEvent(e);
229 }
230
231 /**
232 * Replies the list of open changesets.
233 * @return The list of open changesets
234 */
235 public List<Changeset> getOpenChangesets() {
236 return cache.values().stream()
237 .filter(Changeset::isOpen)
238 .collect(Collectors.toList());
239 }
240
241 /**
242 * If the current user {@link UserIdentityManager#isAnonymous() is known}, the {@link #getOpenChangesets() open changesets}
243 * for the {@link UserIdentityManager#isCurrentUser(User) current user} are returned. Otherwise,
244 * the unfiltered {@link #getOpenChangesets() open changesets} are returned.
245 *
246 * @return a list of changesets
247 */
248 public List<Changeset> getOpenChangesetsForCurrentUser() {
249 if (UserIdentityManager.getInstance().isAnonymous()) {
250 return getOpenChangesets();
251 } else {
252 return new ArrayList<>(SubclassFilteredCollection.filter(getOpenChangesets(),
253 object -> UserIdentityManager.getInstance().isCurrentUser(object.getUser())));
254 }
255 }
256
257 /* ------------------------------------------------------------------------- */
258 /* interface PreferenceChangedListener */
259 /* ------------------------------------------------------------------------- */
260 @Override
261 public void preferenceChanged(PreferenceChangeEvent e) {
262 if (e.getKey() == null || !"osm-server.url".equals(e.getKey()))
263 return;
264
265 // clear the cache when the API url changes
266 if (e.getOldValue() == null || e.getNewValue() == null || !e.getOldValue().equals(e.getNewValue())) {
267 clear();
268 }
269 }
270}
Note: See TracBrowser for help on using the repository browser.