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