Ignore:
Timestamp:
2010-08-08T13:48:26+02:00 (14 years ago)
Author:
stoecker
Message:

fix #5221 - patch by Upliner - errors in conflict manager

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/osm/DataSetMerger.java

    r3377 r3423  
    77import java.util.HashMap;
    88import java.util.HashSet;
     9import java.util.Iterator;
    910import java.util.LinkedList;
    1011import java.util.List;
     
    4041     */
    4142    private final Set<PrimitiveId> objectsWithChildrenToMerge;
    42     private final Set<OsmPrimitive> deletedObjectsToUnlink;
     43    private final Set<OsmPrimitive> objectsToDelete;
    4344
    4445    /**
     
    5859        mergedMap = new HashMap<PrimitiveId, PrimitiveId>();
    5960        objectsWithChildrenToMerge = new HashSet<PrimitiveId>();
    60         deletedObjectsToUnlink = new HashSet<OsmPrimitive>();
     61        objectsToDelete = new HashSet<OsmPrimitive>();
    6162    }
    6263
     
    162163            }
    163164        }
    164         for (OsmPrimitive source: deletedObjectsToUnlink) {
    165             OsmPrimitive target = getMergeTarget(source);
    166             if (target == null)
    167                 throw new RuntimeException(tr("Missing merge target for object with id {0}", source.getUniqueId()));
    168             targetDataSet.unlinkReferencesToPrimitive(target);
     165
     166        deleteMarkedObjects();
     167    }
     168
     169    /**
     170     * Deleted objects in objectsToDelete set and create conflicts for objects that cannot
     171     * be deleted because they're referenced in the target dataset.
     172     */
     173    protected void deleteMarkedObjects() {
     174        boolean flag;
     175        do {
     176            flag = false;
     177            for (Iterator<OsmPrimitive> it = objectsToDelete.iterator();it.hasNext();) {
     178                OsmPrimitive target = it.next();
     179                OsmPrimitive source = sourceDataSet.getPrimitiveById(target.getPrimitiveId());
     180                if (source == null)
     181                    throw new RuntimeException(tr("Object of type {0} with id {1} was marked to be deleted, but it's missing in the source dataset",
     182                            target.getType(), target.getUniqueId()));
     183
     184                List<OsmPrimitive> referrers = target.getReferrers();
     185                if (referrers.isEmpty()) {
     186                    target.setDeleted(true);
     187                    target.mergeFrom(source);
     188                    it.remove();
     189                    flag = true;
     190                } else {
     191                    for (OsmPrimitive referrer : referrers) {
     192                        // If one of object referrers isn't going to be deleted,
     193                        // add a conflict and don't delete the object
     194                        if (!objectsToDelete.contains(referrer)) {
     195                            conflicts.add(target, source);
     196                            it.remove();
     197                            flag = true;
     198                            break;
     199                        }
     200                    }
     201                }
     202
     203            }
     204        } while (flag);
     205
     206        if (!objectsToDelete.isEmpty()) {
     207            // There are some more objects rest in the objectsToDelete set
     208            // This can be because of cross-referenced relations.
     209            for (OsmPrimitive osm: objectsToDelete) {
     210                if (osm instanceof Way) {
     211                    ((Way) osm).setNodes(null);
     212                } else if (osm instanceof Relation) {
     213                    ((Relation) osm).setMembers(null);
     214                }
     215            }
     216            for (OsmPrimitive osm: objectsToDelete) {
     217                osm.setDeleted(true);
     218                osm.mergeFrom(sourceDataSet.getPrimitiveById(osm.getPrimitiveId()));
     219            }
    169220        }
    170221    }
     
    257308            // take. We take target.
    258309            //
    259         } else if (target.isDeleted() && ! source.isDeleted() && target.getVersion() == source.getVersion()) {
     310        } else if (target.isVisible() != source.isVisible() && target.getVersion() == source.getVersion())
     311            // Same version, but different "visible" attribute. It indicates a serious problem in datasets.
     312            // For example, datasets can be fetched from different OSM servers or badly hand-modified.
     313            // We shouldn't merge that datasets.
     314            throw new DataIntegrityProblemException(tr("Conflict in 'visible' attribute for object of type {0} with id {1}",
     315                    target.getType(), target.getId()));
     316        else if (target.isDeleted() && ! source.isDeleted() && target.getVersion() == source.getVersion()) {
    260317            // same version, but target is deleted. Assume target takes precedence
    261318            // otherwise too many conflicts when refreshing from the server
     
    269326                }
    270327            }
    271         } else if (target.isDeleted() != source.isDeleted()) {
    272             // differences in deleted state have to be resolved manually. This can
    273             // happen if one layer is merged onto another layer
    274             //
    275             conflicts.add(target,source);
     328        } else if (! target.isModified() && source.isDeleted()) {
     329            // target not modified. We can assume that source is the most recent version,
     330            // so mark it to be deleted.
     331            //
     332            objectsToDelete.add(target);
    276333        } else if (! target.isModified() && source.isModified()) {
    277334            // target not modified. We can assume that source is the most recent version.
    278             // clone it into target. But check first, whether source is deleted. if so,
    279             // make sure that target is not referenced any more in myDataSet. If it is there
    280             // is a conflict
    281             if (source.isDeleted()) {
    282                 if (!target.getReferrers().isEmpty()) {
    283                     conflicts.add(target, source);
    284                 }
    285             } else {
    286                 target.mergeFrom(source);
    287                 objectsWithChildrenToMerge.add(source.getPrimitiveId());
    288             }
     335            // clone it into target.
     336            target.mergeFrom(source);
     337            objectsWithChildrenToMerge.add(source.getPrimitiveId());
    289338        } else if (! target.isModified() && !source.isModified() && target.getVersion() == source.getVersion()) {
    290339            // both not modified. Merge nevertheless.
     
    303352                target.setModified(false);
    304353            }
     354        } else if (source.isDeleted() != target.isDeleted()) {
     355            // target is modified and deleted state differs.
     356            // this have to be resolved manually.
     357            //
     358            conflicts.add(target,source);
    305359        } else if (! target.hasEqualSemanticAttributes(source)) {
    306360            // target is modified and is not semantically equal with source. Can't automatically
Note: See TracChangeset for help on using the changeset viewer.