- Timestamp:
- 2019-04-01T07:46:58+02:00 (6 years ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/osm/ChangesetDataSet.java
r14214 r14946 1 1 // License: GPL. For details, see LICENSE file. 2 2 package org.openstreetmap.josm.data.osm; 3 3 import static org.openstreetmap.josm.tools.I18n.tr; 4 5 import java.util.Collections; 4 6 import java.util.HashMap; 5 7 import java.util.Iterator; … … 7 9 import java.util.Map.Entry; 8 10 import java.util.Set; 9 import java.util.stream.Collectors;10 11 11 12 import org.openstreetmap.josm.data.osm.history.HistoryOsmPrimitive; 12 13 import org.openstreetmap.josm.tools.CheckParameterUtil; 14 import org.openstreetmap.josm.tools.Logging; 13 15 14 16 /** 15 * A ChangesetDataSet holds the content of a changeset. 17 * A ChangesetDataSet holds the content of a changeset. Typically, a primitive is modified only once in a changeset, 18 * but if there are multiple modifications, the first and last are kept. Further intermediate versions are not kept. 16 19 */ 17 20 public class ChangesetDataSet { … … 47 50 } 48 51 49 private final Map<PrimitiveId, HistoryOsmPrimitive> primitives = new HashMap<>();50 private final Map<PrimitiveId, ChangesetModificationType> modificationTypes= new HashMap<>();52 /** maps an id to either one {@link ChangesetDataSetEntry} or an array of {@link ChangesetDataSetEntry} */ 53 private final Map<PrimitiveId, Object> entryMap = new HashMap<>(); 51 54 52 55 /** … … 57 60 * @throws IllegalArgumentException if primitive is null 58 61 * @throws IllegalArgumentException if cmt is null 62 * @throws IllegalArgumentException if the same primitive was already stored with a higher or equal version 59 63 */ 60 64 public void put(HistoryOsmPrimitive primitive, ChangesetModificationType cmt) { 61 65 CheckParameterUtil.ensureParameterNotNull(primitive, "primitive"); 62 66 CheckParameterUtil.ensureParameterNotNull(cmt, "cmt"); 63 primitives.put(primitive.getPrimitiveId(), primitive); 64 modificationTypes.put(primitive.getPrimitiveId(), cmt); 67 DefaultChangesetDataSetEntry csEntry = new DefaultChangesetDataSetEntry(cmt, primitive); 68 Object val = entryMap.get(primitive.getPrimitiveId()); 69 ChangesetDataSetEntry[] entries; 70 if (val == null) { 71 entryMap.put(primitive.getPrimitiveId(), csEntry); 72 return; 73 } 74 if (val instanceof ChangesetDataSetEntry) { 75 entries = new ChangesetDataSetEntry[2]; 76 entries[0] = (ChangesetDataSetEntry) val; 77 if (primitive.getVersion() <= entries[0].getPrimitive().getVersion()) { 78 throw new IllegalArgumentException( 79 tr("Changeset {0}: Unexpected order of versions for {1}: v{2} is not higher than v{3}", 80 String.valueOf(primitive.getChangesetId()), primitive.getPrimitiveId(), 81 primitive.getVersion(), entries[0].getPrimitive().getVersion())); 82 } 83 } else { 84 entries = (ChangesetDataSetEntry[]) val; 85 } 86 if (entries[1] != null) { 87 Logging.info("Changeset {0}: Change of {1} v{2} is replaced by version v{3}", 88 String.valueOf(primitive.getChangesetId()), primitive.getPrimitiveId(), 89 entries[1].getPrimitive().getVersion(), primitive.getVersion()); 90 } 91 entries[1] = csEntry; 92 entryMap.put(primitive.getPrimitiveId(), entries); 65 93 } 66 94 … … 72 100 public boolean contains(PrimitiveId id) { 73 101 if (id == null) return false; 74 return primitives.containsKey(id);75 } 76 77 /** 78 * Replies the modification type for the object with id <code>id</code>. Replies null, if id is null or102 return entryMap.containsKey(id); 103 } 104 105 /** 106 * Replies the last modification type for the object with id <code>id</code>. Replies null, if id is null or 79 107 * if the object with id <code>id</code> isn't in the changeset content. 80 108 * 81 109 * @param id the id 82 * @return the modification type110 * @return the last modification type or null 83 111 */ 84 112 public ChangesetModificationType getModificationType(PrimitiveId id) { 85 if (!contains(id)) return null;86 return modificationTypes.get(id);113 ChangesetDataSetEntry e = getLastEntry(id); 114 return e != null ? e.getModificationType() : null; 87 115 } 88 116 89 117 /** 90 118 * Replies true if the primitive with id <code>id</code> was created in this 91 * changeset. Replies false, if id is null .119 * changeset. Replies false, if id is null or not in the dataset. 92 120 * 93 121 * @param id the id … … 96 124 */ 97 125 public boolean isCreated(PrimitiveId id) { 98 if (!contains(id)) return false;99 return ChangesetModificationType.CREATED == getModificationType(id);126 ChangesetDataSetEntry e = getFirstEntry(id); 127 return e != null && e.getModificationType() == ChangesetModificationType.CREATED; 100 128 } 101 129 102 130 /** 103 131 * Replies true if the primitive with id <code>id</code> was updated in this 104 * changeset. Replies false, if id is null .132 * changeset. Replies false, if id is null or not in the dataset. 105 133 * 106 134 * @param id the id … … 109 137 */ 110 138 public boolean isUpdated(PrimitiveId id) { 111 if (!contains(id)) return false;112 return ChangesetModificationType.UPDATED == getModificationType(id);139 ChangesetDataSetEntry e = getLastEntry(id); 140 return e != null && e.getModificationType() == ChangesetModificationType.UPDATED; 113 141 } 114 142 115 143 /** 116 144 * Replies true if the primitive with id <code>id</code> was deleted in this 117 * changeset. Replies false, if id is null .145 * changeset. Replies false, if id is null or not in the dataset. 118 146 * 119 147 * @param id the id … … 122 150 */ 123 151 public boolean isDeleted(PrimitiveId id) { 124 if (!contains(id)) return false; 125 return ChangesetModificationType.DELETED == getModificationType(id); 126 } 127 128 /** 129 * Replies the set of primitives with a specific modification type 130 * 131 * @param cmt the modification type. Must not be null. 132 * @return the set of primitives 133 * @throws IllegalArgumentException if cmt is null 134 */ 135 public Set<HistoryOsmPrimitive> getPrimitivesByModificationType(ChangesetModificationType cmt) { 136 CheckParameterUtil.ensureParameterNotNull(cmt, "cmt"); 137 return modificationTypes.entrySet().stream() 138 .filter(entry -> entry.getValue() == cmt) 139 .map(entry -> primitives.get(entry.getKey())) 140 .collect(Collectors.toSet()); 141 } 142 143 /** 144 * Replies the number of objects in the dataset 145 * 146 * @return the number of objects in the dataset 152 ChangesetDataSetEntry e = getLastEntry(id); 153 return e != null && e.getModificationType() == ChangesetModificationType.DELETED; 154 } 155 156 /** 157 * Replies the number of primitives in the dataset. 158 * 159 * @return the number of primitives in the dataset. 147 160 */ 148 161 public int size() { 149 return primitives.size();162 return entryMap.size(); 150 163 } 151 164 152 165 /** 153 166 * Replies the {@link HistoryOsmPrimitive} with id <code>id</code> from this dataset. 167 * null, if there is no such primitive in the data set. If the primitive was modified 168 * multiple times, the last version is returned. 169 * 170 * @param id the id 171 * @return the {@link HistoryOsmPrimitive} with id <code>id</code> from this dataset 172 */ 173 public HistoryOsmPrimitive getPrimitive(PrimitiveId id) { 174 ChangesetDataSetEntry e = getLastEntry(id); 175 return e != null ? e.getPrimitive() : null; 176 } 177 178 /** 179 * @return an unmodifiable set of all primitives in this dataset. 180 * @since 14946 181 */ 182 public Set<PrimitiveId> getIds() { 183 return Collections.unmodifiableSet(entryMap.keySet()); 184 } 185 186 /** 187 * Replies the first {@link ChangesetDataSetEntry} with id <code>id</code> from this dataset. 154 188 * null, if there is no such primitive in the data set. 155 * 156 * @param id the id 157 * @return the {@link HistoryOsmPrimitive} with id <code>id</code> from this dataset 158 */ 159 public HistoryOsmPrimitive getPrimitive(PrimitiveId id) { 160 if (id == null) return null; 161 return primitives.get(id); 162 } 163 164 /** 165 * Returns an iterator over dataset entries. 166 * @return an iterator over dataset entries 189 * @param id the id 190 * @return the first {@link ChangesetDataSetEntry} with id <code>id</code> from this dataset or null. 191 * @since 14946 192 */ 193 public ChangesetDataSetEntry getFirstEntry(PrimitiveId id) { 194 if (id == null) 195 return null; 196 Object val = entryMap.get(id); 197 if (val == null) 198 return null; 199 if (val instanceof ChangesetDataSetEntry[]) { 200 ChangesetDataSetEntry[] entries = (ChangesetDataSetEntry[]) val; 201 return entries[0]; 202 } else { 203 return (ChangesetDataSetEntry) val; 204 } 205 } 206 207 /** 208 * Replies the last {@link ChangesetDataSetEntry} with id <code>id</code> from this dataset. 209 * null, if there is no such primitive in the data set. 210 * @param id the id 211 * @return the last {@link ChangesetDataSetEntry} with id <code>id</code> from this dataset or null. 212 * @since 14946 213 */ 214 public ChangesetDataSetEntry getLastEntry(PrimitiveId id) { 215 if (id == null) 216 return null; 217 Object val = entryMap.get(id); 218 if (val == null) 219 return null; 220 if (val instanceof ChangesetDataSetEntry[]) { 221 ChangesetDataSetEntry[] entries = (ChangesetDataSetEntry[]) val; 222 return entries[1]; 223 } else { 224 return (ChangesetDataSetEntry) val; 225 } 226 } 227 228 /** 229 * Returns an iterator over dataset entries. The elements are returned in no particular order. 230 * @return an iterator over dataset entries. If a primitive was changed multiple times, only the last entry is returned. 167 231 */ 168 232 public Iterator<ChangesetDataSetEntry> iterator() { … … 170 234 } 171 235 172 private static class DefaultChangesetDataSetEntry implements ChangesetDataSetEntry { 236 /** 237 * Class to keep one entry of a changeset: the combination of modification type and primitive. 238 */ 239 public static class DefaultChangesetDataSetEntry implements ChangesetDataSetEntry { 173 240 private final ChangesetModificationType modificationType; 174 241 private final HistoryOsmPrimitive primitive; 175 242 176 DefaultChangesetDataSetEntry(ChangesetModificationType modificationType, HistoryOsmPrimitive primitive) { 243 /** 244 * Construct new entry. 245 * @param modificationType the modification type 246 * @param primitive the primitive 247 */ 248 public DefaultChangesetDataSetEntry(ChangesetModificationType modificationType, HistoryOsmPrimitive primitive) { 177 249 this.modificationType = modificationType; 178 250 this.primitive = primitive; … … 188 260 return primitive; 189 261 } 262 263 @Override 264 public String toString() { 265 return modificationType.toString() + " " + primitive.toString(); 266 } 190 267 } 191 268 192 269 private class DefaultIterator implements Iterator<ChangesetDataSetEntry> { 193 private final Iterator<Entry<PrimitiveId, ChangesetModificationType>> typeIterator;270 private final Iterator<Entry<PrimitiveId, Object>> typeIterator; 194 271 195 272 DefaultIterator() { 196 typeIterator = modificationTypes.entrySet().iterator();273 typeIterator = entryMap.entrySet().iterator(); 197 274 } 198 275 … … 204 281 @Override 205 282 public ChangesetDataSetEntry next() { 206 Entry<PrimitiveId, ChangesetModificationType> next = typeIterator.next(); 207 return new DefaultChangesetDataSetEntry(next.getValue(), primitives.get(next.getKey())); 283 Entry<PrimitiveId, Object> next = typeIterator.next(); 284 // get last entry 285 Object val = next.getValue(); 286 ChangesetDataSetEntry last; 287 if (val instanceof ChangesetDataSetEntry[]) { 288 ChangesetDataSetEntry[] entries = (ChangesetDataSetEntry[]) val; 289 last = entries[1]; 290 } else { 291 last = (ChangesetDataSetEntry) val; 292 } 293 return new DefaultChangesetDataSetEntry(last.getModificationType(), last.getPrimitive()); 208 294 } 209 295 -
trunk/src/org/openstreetmap/josm/io/AbstractParser.java
r14214 r14946 29 29 protected HistoryOsmPrimitive currentPrimitive; 30 30 protected Locator locator; 31 /** if true, replace user information in input by anonymous user */ 32 protected boolean useAnonymousUser; 31 33 32 34 @Override … … 112 114 boolean visible = getMandatoryAttributeBoolean(atts, "visible"); 113 115 114 Long uid = getAttributeLong(atts, "uid"); 115 String userStr = atts.getValue("user"); 116 User user; 117 if (userStr != null) { 118 if (uid != null) { 119 user = User.createOsmUser(uid, userStr); 120 user.setPreferredName(userStr); 121 } else { 122 user = User.createLocalUser(userStr); 116 User user = null; 117 if (!useAnonymousUser) { 118 Long uid = getAttributeLong(atts, "uid"); 119 String userStr = atts.getValue("user"); 120 if (userStr != null) { 121 if (uid != null) { 122 user = User.createOsmUser(uid, userStr); 123 user.setPreferredName(userStr); 124 } else { 125 user = User.createLocalUser(userStr); 126 } 123 127 } 124 } else { 128 } 129 if (user == null) { 125 130 user = User.getAnonymous(); 126 131 } -
trunk/src/org/openstreetmap/josm/io/OsmChangesetContentParser.java
r13901 r14946 35 35 36 36 private class Parser extends AbstractParser { 37 Parser(boolean useAnonymousUser) { 38 this.useAnonymousUser = useAnonymousUser; 39 } 37 40 38 41 /** the current change modification type */ … … 121 124 * @throws IllegalArgumentException if source is {@code null}. 122 125 */ 123 @SuppressWarnings("resource")124 126 public OsmChangesetContentParser(InputStream source) { 125 127 CheckParameterUtil.ensureParameterNotNull(source, "source"); … … 147 149 */ 148 150 public ChangesetDataSet parse(ProgressMonitor progressMonitor) throws XmlParsingException { 151 return parse(progressMonitor, false); 152 } 153 154 /** 155 * Parses the content. 156 * 157 * @param progressMonitor the progress monitor. Set to {@link NullProgressMonitor#INSTANCE} if null 158 * @param useAnonymousUser if true, replace all user information with the anonymous user 159 * @return the parsed data 160 * @throws XmlParsingException if something went wrong. Check for chained 161 * exceptions. 162 * @since 14946 163 */ 164 public ChangesetDataSet parse(ProgressMonitor progressMonitor, boolean useAnonymousUser) throws XmlParsingException { 149 165 if (progressMonitor == null) { 150 166 progressMonitor = NullProgressMonitor.INSTANCE; … … 153 169 progressMonitor.beginTask(""); 154 170 progressMonitor.indeterminateSubTask(tr("Parsing changeset content ...")); 155 XmlUtils.parseSafeSAX(source, new Parser( ));171 XmlUtils.parseSafeSAX(source, new Parser(useAnonymousUser)); 156 172 } catch (XmlParsingException e) { 157 173 throw e; … … 172 188 */ 173 189 public ChangesetDataSet parse() throws XmlParsingException { 174 return parse(null );190 return parse(null, false); 175 191 } 176 192 } -
trunk/src/org/openstreetmap/josm/io/OsmServerChangesetReader.java
r13761 r14946 27 27 */ 28 28 public class OsmServerChangesetReader extends OsmServerReader { 29 final boolean useAnonymousUser; 30 31 /** 32 * Constructs a new {@code OsmServerChangesetReader} with default settings. 33 */ 34 public OsmServerChangesetReader() { 35 this(false); 36 } 37 38 /** 39 * Constructs a new {@code OsmServerChangesetReader} 40 * @param useAnonymousUser if true, replace all user information with the anonymous user 41 * @since 14946 42 */ 43 public OsmServerChangesetReader(boolean useAnonymousUser) { 44 super(); 45 this.useAnonymousUser = useAnonymousUser; 46 } 29 47 30 48 /** … … 199 217 monitor.setCustomText(tr("Downloading content for changeset {0} ...", id)); 200 218 OsmChangesetContentParser parser = new OsmChangesetContentParser(in); 201 result = parser.parse(monitor.createSubTaskMonitor(1, true) );219 result = parser.parse(monitor.createSubTaskMonitor(1, true), useAnonymousUser); 202 220 } catch (IOException e) { 203 221 Logging.warn(e);
Note:
See TracChangeset
for help on using the changeset viewer.