001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.data.osm; 003 004import java.util.HashMap; 005import java.util.Iterator; 006import java.util.Map; 007import java.util.Map.Entry; 008import java.util.Set; 009import java.util.stream.Collectors; 010 011import org.openstreetmap.josm.data.osm.history.HistoryOsmPrimitive; 012import org.openstreetmap.josm.tools.CheckParameterUtil; 013 014/** 015 * A ChangesetDataSet holds the content of a changeset. 016 */ 017public class ChangesetDataSet { 018 019 public enum ChangesetModificationType { 020 CREATED, 021 UPDATED, 022 DELETED 023 } 024 025 public interface ChangesetDataSetEntry { 026 ChangesetModificationType getModificationType(); 027 028 HistoryOsmPrimitive getPrimitive(); 029 } 030 031 private final Map<PrimitiveId, HistoryOsmPrimitive> primitives = new HashMap<>(); 032 private final Map<PrimitiveId, ChangesetModificationType> modificationTypes = new HashMap<>(); 033 034 /** 035 * Remembers a history primitive with the given modification type 036 * 037 * @param primitive the primitive. Must not be null. 038 * @param cmt the modification type. Must not be null. 039 * @throws IllegalArgumentException if primitive is null 040 * @throws IllegalArgumentException if cmt is null 041 */ 042 public void put(HistoryOsmPrimitive primitive, ChangesetModificationType cmt) { 043 CheckParameterUtil.ensureParameterNotNull(primitive, "primitive"); 044 CheckParameterUtil.ensureParameterNotNull(cmt, "cmt"); 045 primitives.put(primitive.getPrimitiveId(), primitive); 046 modificationTypes.put(primitive.getPrimitiveId(), cmt); 047 } 048 049 /** 050 * Replies true if the changeset content contains the object with primitive <code>id</code>. 051 * @param id the id. 052 * @return true if the changeset content contains the object with primitive <code>id</code> 053 */ 054 public boolean contains(PrimitiveId id) { 055 if (id == null) return false; 056 return primitives.containsKey(id); 057 } 058 059 /** 060 * Replies the modification type for the object with id <code>id</code>. Replies null, if id is null or 061 * if the object with id <code>id</code> isn't in the changeset content. 062 * 063 * @param id the id 064 * @return the modification type 065 */ 066 public ChangesetModificationType getModificationType(PrimitiveId id) { 067 if (!contains(id)) return null; 068 return modificationTypes.get(id); 069 } 070 071 /** 072 * Replies true if the primitive with id <code>id</code> was created in this 073 * changeset. Replies false, if id is null. 074 * 075 * @param id the id 076 * @return true if the primitive with id <code>id</code> was created in this 077 * changeset. 078 */ 079 public boolean isCreated(PrimitiveId id) { 080 if (!contains(id)) return false; 081 return ChangesetModificationType.CREATED.equals(getModificationType(id)); 082 } 083 084 /** 085 * Replies true if the primitive with id <code>id</code> was updated in this 086 * changeset. Replies false, if id is null. 087 * 088 * @param id the id 089 * @return true if the primitive with id <code>id</code> was updated in this 090 * changeset. 091 */ 092 public boolean isUpdated(PrimitiveId id) { 093 if (!contains(id)) return false; 094 return ChangesetModificationType.UPDATED.equals(getModificationType(id)); 095 } 096 097 /** 098 * Replies true if the primitive with id <code>id</code> was deleted in this 099 * changeset. Replies false, if id is null. 100 * 101 * @param id the id 102 * @return true if the primitive with id <code>id</code> was deleted in this 103 * changeset. 104 */ 105 public boolean isDeleted(PrimitiveId id) { 106 if (!contains(id)) return false; 107 return ChangesetModificationType.DELETED.equals(getModificationType(id)); 108 } 109 110 /** 111 * Replies the set of primitives with a specific modification type 112 * 113 * @param cmt the modification type. Must not be null. 114 * @return the set of primitives 115 * @throws IllegalArgumentException if cmt is null 116 */ 117 public Set<HistoryOsmPrimitive> getPrimitivesByModificationType(ChangesetModificationType cmt) { 118 CheckParameterUtil.ensureParameterNotNull(cmt, "cmt"); 119 return modificationTypes.entrySet().stream() 120 .filter(entry -> entry.getValue().equals(cmt)) 121 .map(entry -> primitives.get(entry.getKey())) 122 .collect(Collectors.toSet()); 123 } 124 125 /** 126 * Replies the number of objects in the dataset 127 * 128 * @return the number of objects in the dataset 129 */ 130 public int size() { 131 return primitives.size(); 132 } 133 134 /** 135 * Replies the {@link HistoryOsmPrimitive} with id <code>id</code> from this 136 * dataset. null, if there is no such primitive in the data set. 137 * 138 * @param id the id 139 * @return the {@link HistoryOsmPrimitive} with id <code>id</code> from this 140 * dataset 141 */ 142 public HistoryOsmPrimitive getPrimitive(PrimitiveId id) { 143 if (id == null) return null; 144 return primitives.get(id); 145 } 146 147 public Iterator<ChangesetDataSetEntry> iterator() { 148 return new DefaultIterator(); 149 } 150 151 private static class DefaultChangesetDataSetEntry implements ChangesetDataSetEntry { 152 private final ChangesetModificationType modificationType; 153 private final HistoryOsmPrimitive primitive; 154 155 DefaultChangesetDataSetEntry(ChangesetModificationType modificationType, HistoryOsmPrimitive primitive) { 156 this.modificationType = modificationType; 157 this.primitive = primitive; 158 } 159 160 @Override 161 public ChangesetModificationType getModificationType() { 162 return modificationType; 163 } 164 165 @Override 166 public HistoryOsmPrimitive getPrimitive() { 167 return primitive; 168 } 169 } 170 171 private class DefaultIterator implements Iterator<ChangesetDataSetEntry> { 172 private final Iterator<Entry<PrimitiveId, ChangesetModificationType>> typeIterator; 173 174 DefaultIterator() { 175 typeIterator = modificationTypes.entrySet().iterator(); 176 } 177 178 @Override 179 public boolean hasNext() { 180 return typeIterator.hasNext(); 181 } 182 183 @Override 184 public ChangesetDataSetEntry next() { 185 Entry<PrimitiveId, ChangesetModificationType> next = typeIterator.next(); 186 ChangesetModificationType type = next.getValue(); 187 HistoryOsmPrimitive primitive = primitives.get(next.getKey()); 188 return new DefaultChangesetDataSetEntry(type, primitive); 189 } 190 191 @Override 192 public void remove() { 193 throw new UnsupportedOperationException(); 194 } 195 } 196}