Ignore:
Timestamp:
2013-04-17T23:02:35+02:00 (12 years ago)
Author:
donvip
Message:

[josm_terracer] fix #josm8597 - Data loss when joining address node into building

Location:
applications/editors/josm/plugins/terracer/src/terracer
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/terracer/src/terracer/HouseNumberInputHandler.java

    r29035 r29509  
    2727import org.openstreetmap.josm.Main;
    2828import org.openstreetmap.josm.actions.JosmAction;
     29import org.openstreetmap.josm.corrector.UserCancelException;
    2930import org.openstreetmap.josm.data.osm.Node;
    3031import org.openstreetmap.josm.data.osm.Relation;
     
    304305                    saveValues();
    305306
    306                     terracerAction.terraceBuilding(
    307                         outline,
    308                         init,
    309                         street,
    310                         associatedStreet,
    311                         segments(),
    312                         dialog.lo.getText(),
    313                         dialog.hi.getText(),
    314                         stepSize(),
    315                         housenumbers,
    316                         streetName(),
    317                         doHandleRelation(),
    318                         doDeleteOutline());
     307                    try {
     308                        terracerAction.terraceBuilding(
     309                            outline,
     310                            init,
     311                            street,
     312                            associatedStreet,
     313                            segments(),
     314                            dialog.lo.getText(),
     315                            dialog.hi.getText(),
     316                            stepSize(),
     317                            housenumbers,
     318                            streetName(),
     319                            doHandleRelation(),
     320                            doDeleteOutline());
     321                    } catch (UserCancelException ex) {
     322                        // Ignore
     323                    }
    319324
    320325                    this.dialog.dispose();
  • applications/editors/josm/plugins/terracer/src/terracer/TerracerAction.java

    r29050 r29509  
    1414import java.awt.event.KeyEvent;
    1515import java.util.ArrayList;
     16import java.util.Arrays;
    1617import java.util.Collection;
    1718import java.util.Collections;
     
    2122import java.util.LinkedList;
    2223import java.util.List;
    23 import java.util.Map.Entry;
    2424import java.util.Set;
    2525import java.util.regex.Matcher;
     
    3636import org.openstreetmap.josm.command.DeleteCommand;
    3737import org.openstreetmap.josm.command.SequenceCommand;
     38import org.openstreetmap.josm.corrector.UserCancelException;
    3839import org.openstreetmap.josm.data.osm.Node;
    3940import org.openstreetmap.josm.data.osm.OsmPrimitive;
    4041import org.openstreetmap.josm.data.osm.Relation;
    4142import org.openstreetmap.josm.data.osm.RelationMember;
     43import org.openstreetmap.josm.data.osm.Tag;
    4244import org.openstreetmap.josm.data.osm.TagCollection;
    4345import org.openstreetmap.josm.data.osm.Way;
    4446import org.openstreetmap.josm.gui.ExtendedDialog;
     47import org.openstreetmap.josm.gui.conflict.tags.CombinePrimitiveResolverDialog;
    4548import org.openstreetmap.josm.tools.Pair;
    4649import org.openstreetmap.josm.tools.Shortcut;
     
    216219        if (housenumbers.size() == 1) {
    217220            // Special case of one outline and one address node.
    218             // Don't open the dialogue
    219             terraceBuilding(outline, init, street, associatedStreet, 0, null, null, 0, housenumbers, streetname, associatedStreet != null, false);
     221            // Don't open the dialog
     222            try {
     223                terraceBuilding(outline, init, street, associatedStreet, 0, null, null, 0, housenumbers, streetname, associatedStreet != null, false);
     224            } catch (UserCancelException ex) {
     225                // Ignore
     226            } finally {
     227                this.commands.clear();
     228                this.commands = null;
     229            }
    220230        } else {
    221             String title = trn("Change {0} object", "Change {0} objects", sel
    222                     .size(), sel.size());
     231            String title = trn("Change {0} object", "Change {0} objects", sel.size(), sel.size());
    223232            // show input dialog.
    224233            new HouseNumberInputHandler(this, outline, init, street, streetname,
     
    303312     *        existing relation
    304313     * @param deleteOutline If the outline way should be deleted when done
     314     * @throws UserCancelException
    305315     */
    306316    public void terraceBuilding(Way outline,
     
    315325                String streetName,
    316326                boolean handleRelations,
    317                 boolean deleteOutline) {
     327                boolean deleteOutline) throws UserCancelException {
    318328        final int nb;
    319329        Integer to = null, from = null;
     
    386396                // add the tags of the outline to each building (e.g. source=*)
    387397                TagCollection.from(outline).applyTo(terr);
    388 
    389                 String number = null;
    390                 Set<Entry<String, String>> additionalKeys = null;
    391                 if (housenumbers.isEmpty()) {
    392                     if (from != null) {
    393                         // only, if the user has specified house numbers
    394                         number = Integer.toString(from + i * step);
    395                     }
    396                 } else {
    397                     number = housenumbers.get(i).get("addr:housenumber");
    398                     additionalKeys = housenumbers.get(i).getKeys().entrySet();
    399                 }
    400 
    401                 addressBuilding(terr, street, streetName, number, additionalKeys, associatedStreet);
    402 
    403                 ways.add(terr);
     398                ways.add(addressBuilding(terr, street, streetName, associatedStreet, housenumbers, i,
     399                        from != null ? Integer.toString(from + i * step) : null));
     400               
    404401                this.commands.add(new AddCommand(terr));
    405402            }
     
    420417        } else {
    421418            // Single building, just add the address details
    422             String number = null;
    423             if (housenumbers == null || housenumbers.isEmpty()) {
    424                 number = From;
    425             } else {
    426                 Node firstHouseNum = housenumbers.iterator().next();
    427                 if (firstHouseNum != null) {
    428                     number = firstHouseNum.get("addr:housenumber");
    429                 }
    430             }
    431             addressBuilding(outline, street, streetName, number, null, associatedStreet);
    432             ways.add(outline);
     419            ways.add(addressBuilding(outline, street, streetName, associatedStreet, housenumbers, 0, From));
    433420        }
    434421
     
    478465        }
    479466    }
    480 
     467   
    481468    /**
    482469     * Adds address details to a single building
     
    485472     * @param street The street, the buildings belong to (may be null)
    486473     * @param streetName the name of a street (may be null). Used if not null and street is null.
    487      * @param number The house number
    488      * @param additionalKeys More keys to be copied onto the new outline
    489474     * @param associatedStreet The associated street. Used to determine if addr:street should be set or not.
    490      */
    491     private void addressBuilding(Way outline, Way street, String streetName,
    492             String number, Set<Entry<String, String>> additionalKeys, Relation associatedStreet) {
    493         if (number != null) {
    494             // only, if the user has specified house numbers
    495             this.commands.add(new ChangePropertyCommand(outline, "addr:housenumber", number));
    496         }
     475     * @return {@code outline}
     476     * @throws UserCancelException
     477     */
     478    private Way addressBuilding(Way outline, Way street, String streetName, Relation associatedStreet, ArrayList<Node> housenumbers, int i, String defaultNumber) throws UserCancelException {
     479        Node houseNum = (housenumbers != null && i >= 0 && i < housenumbers.size()) ? housenumbers.get(i) : null;
    497480        boolean buildingAdded = false;
    498         if (additionalKeys != null) {
    499             for (Entry<String, String> entry : additionalKeys) {
    500                 String key = entry.getKey();
    501                 if ("building".equals(key)) {
    502                     buildingAdded = true;
    503                 }
    504                 this.commands.add(new ChangePropertyCommand(outline, key, entry.getValue()));
    505             }
     481        boolean numberAdded = false;
     482        if (houseNum != null) {
     483            Collection<OsmPrimitive> primitives = Arrays.asList(new OsmPrimitive[]{houseNum, outline});
     484           
     485            TagCollection tagsToCopy = TagCollection.unionOfAllPrimitives(primitives).getTagsFor(houseNum.keySet());
     486            TagCollection tagsInConflict = tagsToCopy.getTagsFor(tagsToCopy.getKeysWithMultipleValues());
     487            tagsToCopy = tagsToCopy.minus(tagsInConflict).minus(TagCollection.from(outline));
     488           
     489            for (Tag tag : tagsToCopy) {
     490                this.commands.add(new ChangePropertyCommand(outline, tag.getKey(), tag.getValue()));
     491            }
     492           
     493            this.commands.addAll(CombinePrimitiveResolverDialog.launchIfNecessary(
     494                    tagsInConflict, primitives, Collections.singleton(outline)));
     495           
     496            buildingAdded = houseNum.hasKey("building");
     497            numberAdded = houseNum.hasKey("addr:housenumber");
    506498        }
    507499        if (!outline.hasKey("building") && !buildingAdded) {
    508500            this.commands.add(new ChangePropertyCommand(outline, "building", "yes"));
     501        }
     502        if (defaultNumber != null && !numberAdded) {
     503            this.commands.add(new ChangePropertyCommand(outline, "addr:housenumber", defaultNumber));
    509504        }
    510505        // Only put addr:street if no relation exists or if it has no name
     
    516511            }
    517512        }
     513        return outline;
    518514    }
    519515
Note: See TracChangeset for help on using the changeset viewer.