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

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

fix #11657 - User.createOsmUser() memory optimization

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