// License: GPL. For details, see LICENSE file.
package reverter.corehacks;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.openstreetmap.josm.data.osm.PrimitiveId;
import org.openstreetmap.josm.data.osm.history.HistoryOsmPrimitive;
import org.openstreetmap.josm.tools.CheckParameterUtil;
/**
* A ChangesetDataSet holds the content of a changeset.
*/
public class ChangesetDataSet {
public enum ChangesetModificationType {
CREATED,
UPDATED,
DELETED
}
public interface ChangesetDataSetEntry {
ChangesetModificationType getModificationType();
HistoryOsmPrimitive getPrimitive();
int getEarliestVersion();
}
private final Map<PrimitiveId, Integer> earliestVersions = new HashMap<>();
private final Map<PrimitiveId, HistoryOsmPrimitive> primitives = new HashMap<>();
private final Map<PrimitiveId, ChangesetModificationType> modificationTypes = new HashMap<>();
/**
* Remembers a history primitive with the given modification type
*
* @param primitive the primitive. Must not be null.
* @param cmt the modification type. Must not be null.
* @throws IllegalArgumentException thrown if primitive is null
* @throws IllegalArgumentException thrown if cmt is null
*/
public void put(HistoryOsmPrimitive primitive, ChangesetModificationType cmt) throws IllegalArgumentException {
CheckParameterUtil.ensureParameterNotNull(primitive, "primitive");
CheckParameterUtil.ensureParameterNotNull(cmt, "cmt");
PrimitiveId pid = primitive.getPrimitiveId();
if (primitives.containsKey(pid)) {
// Save only latest versions of primitives for reverter
if (primitive.getVersion() < primitives.get(pid).getVersion()) {
Integer earliest = earliestVersions.get(pid);
if (earliest == null || primitive.getVersion() < earliest) {
earliestVersions.put(pid, (int) primitive.getVersion());
if (cmt == ChangesetModificationType.CREATED)
modificationTypes.put(pid, cmt);
}
return;
} else {
if (modificationTypes.get(pid) == ChangesetModificationType.CREATED) {
cmt = ChangesetModificationType.CREATED;
}
if (earliestVersions.get(pid) == null) {
earliestVersions.put(pid, (int) primitives.get(pid).getVersion());
}
}
}
primitives.put(pid, primitive);
modificationTypes.put(pid, cmt);
}
/**
* Replies true if the changeset content contains the object with primitive <code>id</code>.
* @param id the id.
* @return true if the changeset content contains the object with primitive <code>id</code>
*/
public boolean contains(PrimitiveId id) {
if (id == null) return false;
return primitives.containsKey(id);
}
/**
* Replies the modification type for the object with id <code>id</code>. Replies null, if id is null or
* if the object with id <code>id</code> isn't in the changeset content.
*
* @param id the id
* @return the modification type
*/
public ChangesetModificationType getModificationType(PrimitiveId id) {
if (!contains(id)) return null;
return modificationTypes.get(id);
}
public int getEarliestVersion(PrimitiveId id) {
Integer earliestVersion = earliestVersions.get(id);
if (earliestVersion == null) earliestVersion = (int) primitives.get(id).getVersion();
return earliestVersion;
}
/**
* Replies true if the primitive with id <code>id</code> was created in this
* changeset. Replies false, if id is null.
*
* @param id the id
* @return true if the primitive with id <code>id</code> was created in this
* changeset.
*/
public boolean isCreated(PrimitiveId id) {
if (!contains(id)) return false;
return ChangesetModificationType.CREATED.equals(getModificationType(id));
}
/**
* Replies true if the primitive with id <code>id</code> was updated in this
* changeset. Replies false, if id is null.
*
* @param id the id
* @return true if the primitive with id <code>id</code> was updated in this
* changeset.
*/
public boolean isUpdated(PrimitiveId id) {
if (!contains(id)) return false;
return ChangesetModificationType.UPDATED.equals(getModificationType(id));
}
/**
* Replies true if the primitive with id <code>id</code> was deleted in this
* changeset. Replies false, if id is null.
*
* @param id the id
* @return true if the primitive with id <code>id</code> was deleted in this
* changeset.
*/
public boolean isDeleted(PrimitiveId id) {
if (!contains(id)) return false;
return ChangesetModificationType.DELETED.equals(getModificationType(id));
}
/**
* Replies the set of primitives with a specific modification type
*
* @param cmt the modification type. Must not be null.
* @return the set of primitives
* @throws IllegalArgumentException thrown if cmt is null
*/
public Set<HistoryOsmPrimitive> getPrimitivesByModificationType(ChangesetModificationType cmt) throws IllegalArgumentException {
CheckParameterUtil.ensureParameterNotNull(cmt, "cmt");
HashSet<HistoryOsmPrimitive> ret = new HashSet<>();
for (Entry<PrimitiveId, ChangesetModificationType> entry: modificationTypes.entrySet()) {
if (entry.getValue().equals(cmt)) {
ret.add(primitives.get(entry.getKey()));
}
}
return ret;
}
/**
* Replies the number of objects in the dataset
*
* @return the number of objects in the dataset
*/
public int size() {
return primitives.size();
}
/**
* Replies the {@see HistoryOsmPrimitive} with id <code>id</code> from this
* dataset. null, if there is no such primitive in the data set.
*
* @param id the id
* @return the {@see HistoryOsmPrimitive} with id <code>id</code> from this
* dataset
*/
public HistoryOsmPrimitive getPrimitive(PrimitiveId id) {
if (id == null) return null;
return primitives.get(id);
}
public Iterator<ChangesetDataSetEntry> iterator() {
return new DefaultIterator();
}
private static class DefaultChangesetDataSetEntry implements ChangesetDataSetEntry {
private final ChangesetModificationType modificationType;
private final HistoryOsmPrimitive primitive;
private final int earliestVersion;
DefaultChangesetDataSetEntry(ChangesetModificationType modificationType, HistoryOsmPrimitive primitive, int earliestVersion) {
this.modificationType = modificationType;
this.primitive = primitive;
this.earliestVersion = earliestVersion;
}
@Override
public ChangesetModificationType getModificationType() {
return modificationType;
}
@Override
public HistoryOsmPrimitive getPrimitive() {
return primitive;
}
@Override
public int getEarliestVersion() {
return earliestVersion;
}
}
private class DefaultIterator implements Iterator<ChangesetDataSetEntry> {
private final Iterator<Entry<PrimitiveId, ChangesetModificationType>> typeIterator;
DefaultIterator() {
typeIterator = modificationTypes.entrySet().iterator();
}
@Override
public boolean hasNext() {
return typeIterator.hasNext();
}
@Override
public ChangesetDataSetEntry next() {
Entry<PrimitiveId, ChangesetModificationType> next = typeIterator.next();
ChangesetModificationType type = next.getValue();
HistoryOsmPrimitive primitive = primitives.get(next.getKey());
Integer earliestVersion = earliestVersions.get(next.getKey());
if (earliestVersion == null) earliestVersion = (int) primitive.getVersion();
return new DefaultChangesetDataSetEntry(type, primitive, earliestVersion);
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
}