Ticket #19898: 19898.2.patch

File 19898.2.patch, 5.2 KB (added by GerdP, 5 years ago)
  • src/org/openstreetmap/josm/data/osm/DataSetMerger.java

     
    55
    66import java.awt.geom.Area;
    77import java.util.ArrayList;
    8 import java.util.Collection;
     8import java.util.Arrays;
    99import java.util.HashMap;
    1010import java.util.HashSet;
    1111import java.util.Iterator;
     
    1313import java.util.List;
    1414import java.util.Map;
    1515import java.util.Set;
     16import java.util.stream.Collectors;
    1617
    1718import org.openstreetmap.josm.data.DataSource;
    1819import org.openstreetmap.josm.data.conflict.Conflict;
     
    7879     * my primitive.
    7980     *
    8081     * @param source the primitive to merge
    81      * @param candidates a set of possible candidates for a new primitive
     82     * @param mergeNewHelper a class that manages possible candidates for a new primitive
    8283     */
    83     protected void mergePrimitive(OsmPrimitive source, Collection<? extends OsmPrimitive> candidates) {
     84    private void mergePrimitive(OsmPrimitive source, MergeNewHelper mergeNewHelper) {
    8485        if (!source.isNew()) {
    8586            // try to merge onto a matching primitive with the same defined id
    8687            //
     
    9394            // try to merge onto a primitive  which has no id assigned
    9495            // yet but which is equal in its semantic attributes
    9596            //
    96             for (OsmPrimitive target : candidates) {
     97            for (OsmPrimitive target : mergeNewHelper.getCandidates(source)) {
    9798                if (!target.isNew() || target.isDeleted()) {
    98                     continue;
     99                    continue; // should not happen
    99100                }
    100101                if (target.hasEqualSemanticAttributes(source)) {
    101102                    mergedMap.put(source.getPrimitiveId(), target.getPrimitiveId());
     
    423424        if (progressMonitor != null) {
    424425            progressMonitor.beginTask(tr("Merging data..."), sourceDataSet.allPrimitives().size());
    425426        }
     427
    426428        targetDataSet.update(() -> {
    427             List<? extends OsmPrimitive> candidates = null;
    428             for (Node node: sourceDataSet.getNodes()) {
    429                 // lazy initialisation to improve performance, see #19898
    430                 if (candidates == null) {
    431                     candidates = new ArrayList<>(targetDataSet.getNodes());
     429            for (Class<? extends OsmPrimitive> clazz : Arrays.asList(Node.class, Way.class, Relation.class)) {
     430                MergeNewHelper mergeNewHelper = new MergeNewHelper(targetDataSet);
     431                for (OsmPrimitive source: sourceDataSet.getPrimitives(clazz::isInstance)) {
     432                    mergePrimitive(source, mergeNewHelper);
     433                    if (progressMonitor != null) {
     434                        progressMonitor.worked(1);
     435                    }
    432436                }
    433                 mergePrimitive(node, candidates);
    434                 if (progressMonitor != null) {
    435                     progressMonitor.worked(1);
    436                 }
    437437            }
    438             candidates = null;
    439             for (Way way: sourceDataSet.getWays()) {
    440                 // lazy initialisation to improve performance
    441                 if (candidates == null) {
    442                     candidates = new ArrayList<>(targetDataSet.getWays());
    443                 }
    444                 mergePrimitive(way, candidates);
    445                 if (progressMonitor != null) {
    446                     progressMonitor.worked(1);
    447                 }
    448             }
    449             candidates = null;
    450             for (Relation relation: sourceDataSet.getRelations()) {
    451                 // lazy initialisation to improve performance
    452                 if (candidates == null) {
    453                     candidates = new ArrayList<>(targetDataSet.getRelations());
    454                 }
    455                 mergePrimitive(relation, candidates);
    456                 if (progressMonitor != null) {
    457                     progressMonitor.worked(1);
    458                 }
    459             }
    460             candidates = null;
    461438            fixReferences();
    462439
    463440            Area a = targetDataSet.getDataSourceArea();
     
    512489    public ConflictCollection getConflicts() {
    513490        return conflicts;
    514491    }
     492
     493    /**
     494     * Helper class to avoid unnecessary calculation of the candidates list for new primitives.
     495     *
     496     * @author Gerd Petermann
     497     *
     498     */
     499    private static class MergeNewHelper {
     500        private final DataSet target;
     501        private List<OsmPrimitive> candidates;
     502
     503        MergeNewHelper(DataSet target) {
     504            this.target = target;
     505        }
     506
     507        /**
     508         * Get possible merge candidates for a new primitive.
     509         * @param primitive the new primitive
     510         * @return a list of new and undeleted objects of the same type already existing in the target dataset. Might be empty but it not null.
     511         */
     512        public List<OsmPrimitive> getCandidates(OsmPrimitive primitive) {
     513            if (candidates == null) {
     514                candidates = target.getPrimitives(primitive.getClass()::isInstance).stream()
     515                        .filter(p -> p.isNew() && !p.isDeleted()).collect(Collectors.toList());
     516            }
     517            return candidates;
     518        }
     519
     520    }
    515521}