001    // License: GPL. For details, see LICENSE file.
002    package org.openstreetmap.josm.data.osm;
003    
004    import java.util.HashMap;
005    import java.util.HashSet;
006    import java.util.Iterator;
007    import java.util.Map;
008    import java.util.Set;
009    import java.util.Map.Entry;
010    
011    import org.openstreetmap.josm.data.osm.history.HistoryOsmPrimitive;
012    import org.openstreetmap.josm.tools.CheckParameterUtil;
013    
014    /**
015     * A ChangesetDataSet holds the content of a changeset.
016     */
017    public 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        final private Map<PrimitiveId, HistoryOsmPrimitive> primitives = new HashMap<PrimitiveId, HistoryOsmPrimitive>();
031        final private Map<PrimitiveId, ChangesetModificationType> modificationTypes = new HashMap<PrimitiveId, ChangesetModificationType>();
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<HistoryOsmPrimitive>();
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            public ChangesetModificationType getModificationType() {
163                return modificationType;
164            }
165    
166            public HistoryOsmPrimitive getPrimitive() {
167                return primitive;
168            }
169        }
170    
171        private class DefaultIterator implements Iterator<ChangesetDataSetEntry> {
172            private Iterator<Entry<PrimitiveId, ChangesetModificationType>> typeIterator;
173    
174            public DefaultIterator() {
175                typeIterator = modificationTypes.entrySet().iterator();
176            }
177    
178            public boolean hasNext() {
179                return typeIterator.hasNext();
180            }
181    
182            public ChangesetDataSetEntry next() {
183                Entry<PrimitiveId, ChangesetModificationType> next = typeIterator.next();
184                ChangesetModificationType type = next.getValue();
185                HistoryOsmPrimitive primitive = primitives.get(next.getKey());
186                return new DefaultChangesetDataSetEntry(type, primitive);
187            }
188    
189            public void remove() {
190                throw new UnsupportedOperationException();
191            }
192        }
193    }