source: josm/trunk/src/org/openstreetmap/josm/data/osm/User.java @ 12865

Last change on this file since 12865 was 12865, checked in by Don-vip, 11 months ago

see #11390 - SonarQube - squid:S3824 - "Map.get" and value test should be replaced with single method call

  • Property svn:eol-style set to native
File size: 6.9 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.osm;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.util.ArrayList;
7import java.util.Collection;
8import java.util.HashMap;
9import java.util.LinkedHashSet;
10import java.util.List;
11import java.util.Map;
12import java.util.Objects;
13
14/**
15 * A simple class to keep a list of user names.
16 *
17 * Instead of storing user names as strings with every OSM primitive, we store
18 * a reference to an user object, and make sure that for each username there
19 * is only one user object.
20 *
21 * @since 227
22 */
23public final class User {
24
25    private static long uidCounter;
26
27    /**
28     * the map of known users
29     */
30    private static Map<Long, User> userMap = new HashMap<>();
31
32    /**
33     * The anonymous user is a local user used in places where no user is known.
34     * @see #getAnonymous()
35     */
36    private static final User ANONYMOUS = createLocalUser(tr("<anonymous>"));
37
38    private static long getNextLocalUid() {
39        uidCounter--;
40        return uidCounter;
41    }
42
43    /**
44     * Creates a local user with the given name
45     *
46     * @param name the name
47     * @return a new local user with the given name
48     */
49    public static synchronized User createLocalUser(String name) {
50        for (long i = -1; i >= uidCounter; --i) {
51            User olduser = getById(i);
52            if (olduser != null && olduser.hasName(name))
53                return olduser;
54        }
55        User user = new User(getNextLocalUid(), name);
56        userMap.put(user.getId(), user);
57        return user;
58    }
59
60    private static User lastUser;
61
62    /**
63     * Creates a user known to the OSM server
64     *
65     * @param uid  the user id
66     * @param name the name
67     * @return a new OSM user with the given name and uid
68     */
69    public static synchronized User createOsmUser(long uid, String name) {
70
71        if (lastUser != null && lastUser.getId() == uid) {
72            lastUser.setPreferredName(name);
73            return lastUser;
74        }
75
76        User user = userMap.computeIfAbsent(uid, k -> new User(uid, name));
77        if (name != null) user.addName(name);
78
79        lastUser = user;
80
81        return user;
82    }
83
84    /**
85     * clears the static map of user ids to user objects
86     */
87    public static synchronized void clearUserMap() {
88        userMap.clear();
89        lastUser = null;
90    }
91
92    /**
93     * Returns the user with user id <code>uid</code> or null if this user doesn't exist
94     *
95     * @param uid the user id
96     * @return the user; null, if there is no user with  this id
97     */
98    public static synchronized User getById(long uid) {
99        return userMap.get(uid);
100    }
101
102    /**
103     * Returns the list of users with name <code>name</code> or the empty list if
104     * no such users exist
105     *
106     * @param name the user name
107     * @return the list of users with name <code>name</code> or the empty list if
108     * no such users exist
109     */
110    public static synchronized List<User> getByName(String name) {
111        if (name == null) {
112            name = "";
113        }
114        List<User> ret = new ArrayList<>();
115        for (User user: userMap.values()) {
116            if (user.hasName(name)) {
117                ret.add(user);
118            }
119        }
120        return ret;
121    }
122
123    /**
124     * Replies the anonymous user
125     * @return The anonymous user
126     */
127    public static User getAnonymous() {
128        return ANONYMOUS;
129    }
130
131    /** the user name */
132    private final LinkedHashSet<String> names = new LinkedHashSet<>();
133    /** the user id */
134    private final long uid;
135
136    /**
137     * Replies the user name
138     *
139     * @return the user name. Never <code>null</code>, but may be the empty string
140     * @see #getByName(String)
141     * @see #createOsmUser(long, String)
142     * @see #createLocalUser(String)
143     */
144    public String getName() {
145        return names.isEmpty() ? "" : names.iterator().next();
146    }
147
148    /**
149     * Returns the list of user names
150     *
151     * @return list of names
152     */
153    public List<String> getNames() {
154        return new ArrayList<>(names);
155    }
156
157    /**
158     * Adds a user name to the list if it is not there, yet.
159     *
160     * @param name User name
161     */
162    public void addName(String name) {
163        names.add(name);
164    }
165
166    /**
167     * Sets the preferred user name, i.e., the one that will be returned when calling {@link #getName()}.
168     *
169     * Rationale: A user can change its name multiple times and after reading various (outdated w.r.t. user name)
170     * data files it is unclear which is the up-to-date user name.
171     * @param name the preferred user name to set
172     */
173    public void setPreferredName(String name) {
174        if (names.size() == 1 && names.contains(name)) {
175            return;
176        }
177        final Collection<String> allNames = new LinkedHashSet<>(names);
178        names.clear();
179        names.add(name);
180        names.addAll(allNames);
181    }
182
183    /**
184     * Returns true if the name is in the names list
185     *
186     * @param name User name
187     * @return <code>true</code> if the name is in the names list
188     */
189    public boolean hasName(String name) {
190        return names.contains(name);
191    }
192
193    /**
194     * Replies the user id. If this user is known to the OSM server the positive user id
195     * from the server is replied. Otherwise, a negative local value is replied.
196     *
197     * A negative local is only unique during an editing session. It is lost when the
198     * application is closed and there is no guarantee that a negative local user id is
199     * always bound to a user with the same name.
200     *
201     * @return the user id
202     */
203    public long getId() {
204        return uid;
205    }
206
207    /**
208     * Private constructor, only called from get method.
209     * @param uid user id
210     * @param name user name
211     */
212    private User(long uid, String name) {
213        this.uid = uid;
214        if (name != null) {
215            addName(name);
216        }
217    }
218
219    /**
220     * Determines if this user is known to OSM
221     * @return {@code true} if this user is known to OSM, {@code false} otherwise
222     */
223    public boolean isOsmUser() {
224        return uid > 0;
225    }
226
227    /**
228     * Determines if this user is local
229     * @return {@code true} if this user is local, {@code false} otherwise
230     */
231    public boolean isLocalUser() {
232        return uid < 0;
233    }
234
235    @Override
236    public int hashCode() {
237        return Objects.hash(uid);
238    }
239
240    @Override
241    public boolean equals(Object obj) {
242        if (this == obj) return true;
243        if (obj == null || getClass() != obj.getClass()) return false;
244        User user = (User) obj;
245        return uid == user.uid;
246    }
247
248    @Override
249    public String toString() {
250        StringBuilder s = new StringBuilder();
251        s.append("id:").append(uid);
252        if (names.size() == 1) {
253            s.append(" name:").append(getName());
254        } else if (names.size() > 1) {
255            s.append(String.format(" %d names:%s", names.size(), getName()));
256        }
257        return s.toString();
258    }
259}
Note: See TracBrowser for help on using the repository browser.