Changeset 32395 in osm for applications


Ignore:
Timestamp:
2016-06-24T09:10:57+02:00 (8 years ago)
Author:
donvip
Message:

checkstyle, update to JOSM 10279

Location:
applications/editors/josm/plugins/reltoolbox
Files:
2 added
35 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/reltoolbox/.project

    r32286 r32395  
    1616                        </arguments>
    1717                </buildCommand>
     18                <buildCommand>
     19                        <name>net.sf.eclipsecs.core.CheckstyleBuilder</name>
     20                        <arguments>
     21                        </arguments>
     22                </buildCommand>
    1823        </buildSpec>
    1924        <natures>
    2025                <nature>org.eclipse.jdt.core.javanature</nature>
     26                <nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
    2127        </natures>
    2228</projectDescription>
  • applications/editors/josm/plugins/reltoolbox/build.xml

    r31923 r32395  
    44    <property name="commit.message" value="RelToolbox: make natural sort for relation and find relation lists"/>
    55    <!-- enter the *lowest* JOSM version this plugin is currently compatible with -->
    6     <property name="plugin.main.version" value="7392"/>
     6    <property name="plugin.main.version" value="10279"/>
    77
    88    <property name="plugin.author" value="Ilya Zverev"/>
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/ChosenRelation.java

    r30841 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext;
    23
    3 import java.awt.*;
     4import java.awt.AlphaComposite;
     5import java.awt.BasicStroke;
     6import java.awt.Color;
     7import java.awt.Composite;
     8import java.awt.Graphics2D;
     9import java.awt.Point;
     10import java.awt.Stroke;
    411import java.awt.geom.GeneralPath;
    5 import java.util.*;
     12import java.util.HashSet;
     13import java.util.Set;
     14
    615import org.openstreetmap.josm.Main;
    716import org.openstreetmap.josm.data.Bounds;
    8 import org.openstreetmap.josm.data.osm.*;
    9 import org.openstreetmap.josm.data.osm.event.*;
     17import org.openstreetmap.josm.data.osm.Node;
     18import org.openstreetmap.josm.data.osm.OsmPrimitive;
     19import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
     20import org.openstreetmap.josm.data.osm.Relation;
     21import org.openstreetmap.josm.data.osm.Way;
     22import org.openstreetmap.josm.data.osm.event.AbstractDatasetChangedEvent;
     23import org.openstreetmap.josm.data.osm.event.DataChangedEvent;
     24import org.openstreetmap.josm.data.osm.event.DataSetListener;
     25import org.openstreetmap.josm.data.osm.event.NodeMovedEvent;
     26import org.openstreetmap.josm.data.osm.event.PrimitivesAddedEvent;
     27import org.openstreetmap.josm.data.osm.event.PrimitivesRemovedEvent;
     28import org.openstreetmap.josm.data.osm.event.RelationMembersChangedEvent;
     29import org.openstreetmap.josm.data.osm.event.TagsChangedEvent;
     30import org.openstreetmap.josm.data.osm.event.WayNodesChangedEvent;
    1031import org.openstreetmap.josm.gui.MapView;
    11 import org.openstreetmap.josm.gui.MapView.EditLayerChangeListener;
     32import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeEvent;
     33import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeListener;
    1234import org.openstreetmap.josm.gui.layer.MapViewPaintable;
    1335import org.openstreetmap.josm.gui.layer.OsmDataLayer;
     
    1840 * @author Zverik
    1941 */
    20 public class ChosenRelation implements EditLayerChangeListener, MapViewPaintable, DataSetListener {
     42public class ChosenRelation implements ActiveLayerChangeListener, MapViewPaintable, DataSetListener {
    2143    protected Relation chosenRelation = null;
    2244    private Set<ChosenRelationListener> chosenRelationListeners = new HashSet<>();
    2345
    24     public void set( Relation rel ) {
    25         if( rel == chosenRelation || (rel != null && chosenRelation != null && rel.equals(chosenRelation)) ) {
     46    public void set(Relation rel) {
     47        if (rel == chosenRelation || (rel != null && chosenRelation != null && rel.equals(chosenRelation)))
    2648            return; // new is the same as old
    27         }
    2849        Relation oldRel = chosenRelation;
    2950        chosenRelation = rel;
     
    3354    }
    3455
    35     protected void fireRelationChanged( Relation oldRel ) {
    36         for( ChosenRelationListener listener : chosenRelationListeners )
     56    protected void fireRelationChanged(Relation oldRel) {
     57        for (ChosenRelationListener listener : chosenRelationListeners) {
    3758            listener.chosenRelationChanged(oldRel, chosenRelation);
     59        }
    3860    }
    3961
     
    4668    }
    4769
    48     public boolean isSame( Object r ) {
    49         if( r == null )
     70    public boolean isSame(Object r) {
     71        if (r == null )
    5072            return chosenRelation == null;
    51         else if( !(r instanceof Relation) )
     73        else if (!(r instanceof Relation) )
    5274            return false;
    5375        else
    5476            return chosenRelation != null && r.equals(chosenRelation);
    5577    }
    56    
    57     private final static String[] MULTIPOLYGON_TYPES = new String[] {
    58         "multipolygon", "boundary"
     78
     79    private static final String[] MULTIPOLYGON_TYPES = new String[] {
     80            "multipolygon", "boundary"
    5981    };
    6082
     
    6688    }
    6789
    68     public static boolean isMultipolygon( Relation r ) {
    69         if( r == null )
     90    public static boolean isMultipolygon(Relation r) {
     91        if (r == null )
    7092            return false;
    7193        String type = r.get("type");
    72         if( type == null )
     94        if (type == null )
    7395            return false;
    74         for( String t : MULTIPOLYGON_TYPES )
    75             if( t.equals(type) )
     96        for (String t : MULTIPOLYGON_TYPES )
     97            if (t.equals(type) )
    7698                return true;
    7799        return false;
     
    90112    }
    91113
    92     public void addChosenRelationListener( ChosenRelationListener listener ) {
     114    public void addChosenRelationListener(ChosenRelationListener listener) {
    93115        chosenRelationListeners.add(listener);
    94116    }
    95117
    96     public void removeChosenRelationListener( ChosenRelationListener listener ) {
     118    public void removeChosenRelationListener(ChosenRelationListener listener) {
    97119        chosenRelationListeners.remove(listener);
    98120    }
    99121
    100     public void editLayerChanged( OsmDataLayer oldLayer, OsmDataLayer newLayer ) {
     122    @Override
     123    public void activeOrEditLayerChanged(ActiveLayerChangeEvent e) {
    101124        // todo: dim chosen relation when changing layer
    102125        // todo: check this WTF!
     126        OsmDataLayer newLayer = Main.getLayerManager().getEditLayer();
    103127        clear();
    104         if( newLayer != null && oldLayer == null ) {
     128        if (newLayer != null && e.getPreviousEditLayer() == null) {
    105129            Main.map.mapView.addTemporaryLayer(this);
    106         } else if( newLayer == null ) {
     130        } else if (newLayer == null) {
    107131            Main.map.mapView.removeTemporaryLayer(this);
    108132        }
    109133    }
    110134
    111     public void paint( Graphics2D g, MapView mv, Bounds bbox ) {
    112         if( chosenRelation == null ) {
     135    @Override
     136    public void paint(Graphics2D g, MapView mv, Bounds bbox) {
     137        if (chosenRelation == null)
    113138            return;
    114         }
    115139
    116140        OsmDataLayer dataLayer = mv.getEditLayer();
    117141        float opacity = dataLayer == null ? 0.0f : !dataLayer.isVisible() ? 0.0f : (float)dataLayer.getOpacity();
    118         if( opacity < 0.01 )
     142        if (opacity < 0.01 )
    119143            return;
    120        
     144
    121145        Composite oldComposite = g.getComposite();
    122146        Stroke oldStroke = g.getStroke();
     
    124148        g.setColor(Color.yellow);
    125149        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f * opacity));
    126        
     150
    127151        drawRelations(g, mv, bbox, chosenRelation);
    128        
     152
    129153        g.setComposite(oldComposite);
    130154        g.setStroke(oldStroke);
    131        
    132     }
     155
     156    }
     157
    133158    private void drawRelations(Graphics2D g, MapView mv, Bounds bbox, Relation rel) {
    134         for( OsmPrimitive element : rel.getMemberPrimitives() ) {
    135             if( element.getType() == OsmPrimitiveType.NODE ) {
     159        for (OsmPrimitive element : rel.getMemberPrimitives()) {
     160            if (element.getType() == OsmPrimitiveType.NODE) {
    136161                Node node = (Node)element;
    137162                Point center = mv.getPoint(node);
    138163                g.drawOval(center.x - 4, center.y - 4, 9, 9);
    139             } else if( element.getType() == OsmPrimitiveType.WAY ) {
     164            } else if (element.getType() == OsmPrimitiveType.WAY) {
    140165                Way way = (Way)element;
    141                 if( way.getNodesCount() >= 2 ) {
     166                if (way.getNodesCount() >= 2) {
    142167                    GeneralPath b = new GeneralPath();
    143168                    Point p = mv.getPoint(way.getNode(0));
    144169                    b.moveTo(p.x, p.y);
    145                     for( int i = 1; i < way.getNodesCount(); i++ ) {
     170                    for (int i = 1; i < way.getNodesCount(); i++) {
    146171                        p = mv.getPoint(way.getNode(i));
    147172                        b.lineTo(p.x, p.y);
     
    149174                    g.draw(b);
    150175                }
    151             } else if( element.getType() == OsmPrimitiveType.RELATION ) {
     176            } else if (element.getType() == OsmPrimitiveType.RELATION) {
    152177                Color oldColor = g.getColor();
    153178                g.setColor(Color.magenta);
     
    159184    }
    160185
    161     public void relationMembersChanged( RelationMembersChangedEvent event ) {
    162         if( chosenRelation != null && event.getRelation().equals(chosenRelation) )
     186    @Override
     187    public void relationMembersChanged(RelationMembersChangedEvent event) {
     188        if (chosenRelation != null && event.getRelation().equals(chosenRelation) ) {
    163189            fireRelationChanged(chosenRelation);
    164     }
    165    
    166     public void tagsChanged( TagsChangedEvent event ) {
    167         if( chosenRelation != null && event.getPrimitive().equals(chosenRelation) )
     190        }
     191    }
     192
     193    @Override
     194    public void tagsChanged(TagsChangedEvent event) {
     195        if (chosenRelation != null && event.getPrimitive().equals(chosenRelation) ) {
    168196            fireRelationChanged(chosenRelation);
    169     }
    170 
    171     public void dataChanged( DataChangedEvent event ) {
    172         if( chosenRelation != null )
     197        }
     198    }
     199
     200    @Override
     201    public void dataChanged(DataChangedEvent event) {
     202        if (chosenRelation != null ) {
    173203            fireRelationChanged(chosenRelation);
    174     }
    175 
    176     public void primitivesRemoved( PrimitivesRemovedEvent event ) {
    177         if( chosenRelation != null && event.getPrimitives().contains(chosenRelation) )
     204        }
     205    }
     206
     207    @Override
     208    public void primitivesRemoved(PrimitivesRemovedEvent event) {
     209        if (chosenRelation != null && event.getPrimitives().contains(chosenRelation) ) {
    178210            clear();
    179     }
    180 
    181     public void wayNodesChanged( WayNodesChangedEvent event ) {
    182         if( chosenRelation != null )
     211        }
     212    }
     213
     214    @Override
     215    public void wayNodesChanged(WayNodesChangedEvent event) {
     216        if (chosenRelation != null )
     217        {
    183218            fireRelationChanged(chosenRelation); // download incomplete primitives doesn't cause dataChanged event
    184     }
    185 
    186     public void primitivesAdded( PrimitivesAddedEvent event ) {}
    187     public void nodeMoved( NodeMovedEvent event ) {}
    188     public void otherDatasetChange( AbstractDatasetChangedEvent event ) {}
     219        }
     220    }
     221
     222    @Override
     223    public void primitivesAdded(PrimitivesAddedEvent event) {}
     224    @Override
     225    public void nodeMoved(NodeMovedEvent event) {}
     226    @Override
     227    public void otherDatasetChange(AbstractDatasetChangedEvent event) {}
    189228}
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/ChosenRelationComponent.java

    r30841 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext;
    23
     
    1819    public ChosenRelationComponent(ChosenRelation rel) {
    1920        super("");
    20 /*        setBackground(Color.white);
     21        /*        setBackground(Color.white);
    2122        setOpaque(true);
    2223        setBorder(new LineBorder(Color.black, 1, true));*/
     
    2526    }
    2627
    27     public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) {
     28    @Override
     29    public void chosenRelationChanged(Relation oldRelation, Relation newRelation) {
    2830        setText(prepareText(newRelation));
    2931        repaint();
    3032    }
    31    
     33
    3234    private final static String[] TYPE_KEYS = new String[] {
    33         "natural", "landuse", "place", "waterway", "leisure", "amenity", "restriction", "public_transport", "route", "enforcement"
     35            "natural", "landuse", "place", "waterway", "leisure", "amenity", "restriction", "public_transport", "route", "enforcement"
    3436    };
    3537
    3638    private final static String[] NAMING_TAGS = new String[] {
    37         "name", "place_name", "ref", "destination", "note"
     39            "name", "place_name", "ref", "destination", "note"
    3840    };
    3941
    40     protected String prepareText( Relation rel ) {
    41         if( rel == null )
     42    protected String prepareText(Relation rel) {
     43        if (rel == null )
    4244            return "";
    4345
    4446        String type = rel.get("type");
    45         if( type == null || type.length() == 0 )
     47        if (type == null || type.length() == 0 ) {
    4648            type = "-";
     49        }
    4750
    4851        String tag = null;
    49         for( int i = 0; i < TYPE_KEYS.length && tag == null; i++ )
    50             if( rel.hasKey(TYPE_KEYS[i]))
     52        for (int i = 0; i < TYPE_KEYS.length && tag == null; i++ )
     53            if (rel.hasKey(TYPE_KEYS[i])) {
    5154                tag = TYPE_KEYS[i];
    52         if( tag != null )
     55            }
     56        if (tag != null ) {
    5357            tag = tag.substring(0, 2) + "=" + rel.get(tag);
     58        }
    5459
    5560        String name = null;
    56         for( int i = 0; i < NAMING_TAGS.length && name == null; i++ )
    57             if( rel.hasKey(NAMING_TAGS[i]) )
     61        for (int i = 0; i < NAMING_TAGS.length && name == null; i++ )
     62            if (rel.hasKey(NAMING_TAGS[i]) ) {
    5863                name = rel.get(NAMING_TAGS[i]);
     64            }
    5965
    6066        StringBuilder sb = new StringBuilder();
    6167        sb.append(type.substring(0, 1));
    62         if( type.equals("boundary") && rel.hasKey("admin_level") )
     68        if (type.equals("boundary") && rel.hasKey("admin_level") ) {
    6369            sb.append(rel.get("admin_level"));
    64         if( name != null )
     70        }
     71        if (name != null ) {
    6572            sb.append(" \"").append(name).append('"');
    66         if( tag != null )
     73        }
     74        if (tag != null ) {
    6775            sb.append("; ").append(tag);
     76        }
    6877        sb.append(" (").append(rel.getMembersCount()).append(')');
    6978
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/ChosenRelationListener.java

    r30841 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext;
    23
     
    910 */
    1011public interface ChosenRelationListener {
    11     void chosenRelationChanged( Relation oldRelation, Relation newRelation );
     12    void chosenRelationChanged(Relation oldRelation, Relation newRelation);
    1213}
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/ExtraNameFormatHook.java

    r30841 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext;
    23
     
    89/**
    910 * Formatter hook for some tags that Dirk does not want to support.
    10  * 
     11 *
    1112 * @author Zverik
    1213 */
    1314public class ExtraNameFormatHook implements NameFormatterHook {
    1415
    15     public String checkRelationTypeName( IRelation relation, String defaultName ) {
    16     return null;
     16    @Override
     17    public String checkRelationTypeName(IRelation relation, String defaultName) {
     18        return null;
    1719    }
    1820
    19     public String checkFormat( INode node, String defaultName ) {
    20     return null;
     21    @Override
     22    public String checkFormat(INode node, String defaultName) {
     23        return null;
    2124    }
    2225
    23     public String checkFormat( IWay way, String defaultName ) {
    24     if( way.get("place") != null && way.get("name") == null && way.get("place_name") != null )
    25         return way.get("place_name") + " " + defaultName;
    26     return null;
     26    @Override
     27    public String checkFormat(IWay way, String defaultName) {
     28        if (way.get("place") != null && way.get("name") == null && way.get("place_name") != null )
     29            return way.get("place_name") + " " + defaultName;
     30        return null;
    2731    }
    2832
    29     public String checkFormat( IRelation relation, String defaultName ) {
    30     String type = relation.get("type");
    31     if( type != null ) {
    32         String name = relation.get("destination");
    33         if( type.equals("destination_sign") && name != null ) {
    34         if( relation.get("distance") != null )
    35             name += " " + relation.get("distance");
    36         if( defaultName.indexOf('"') < 0 )
    37             return '"' + name + "\" " + defaultName;
    38         else
    39             return defaultName.replaceFirst("\".?+\"", '"'+name+'"');
     33    @Override
     34    public String checkFormat(IRelation relation, String defaultName) {
     35        String type = relation.get("type");
     36        if (type != null) {
     37            String name = relation.get("destination");
     38            if (type.equals("destination_sign") && name != null) {
     39                if (relation.get("distance") != null ) {
     40                    name += " " + relation.get("distance");
     41                }
     42                if (defaultName.indexOf('"') < 0 )
     43                    return '"' + name + "\" " + defaultName;
     44                else
     45                    return defaultName.replaceFirst("\".?+\"", '"'+name+'"');
     46            }
    4047        }
    41     }
    42     return null;
     48        return null;
    4349    }
    4450}
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/RelContextDialog.java

    r30841 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext;
    23
     
    103104public class RelContextDialog extends ToggleDialog implements EditLayerChangeListener, ChosenRelationListener, SelectionChangedListener {
    104105
    105     public final static String PREF_PREFIX = "reltoolbox";
     106    public static final String PREF_PREFIX = "reltoolbox";
    106107
    107108    private final DefaultTableModel relationsData;
     
    124125        chosenRelation = new ChosenRelation();
    125126        chosenRelation.addChosenRelationListener(this);
    126         MapView.addEditLayerChangeListener(chosenRelation);
     127        Main.getLayerManager().addActiveLayerChangeListener(chosenRelation);
    127128
    128129        popupMenu = new ChosenRelationPopupMenu(chosenRelation);
     
    144145        roleBox.addItemListener(new ItemListener() {
    145146            @Override
    146             public void itemStateChanged( ItemEvent e ) {
    147                 if( e.getStateChange() == ItemEvent.DESELECTED ) return;
     147            public void itemStateChanged(ItemEvent e) {
     148                if (e.getStateChange() == ItemEvent.DESELECTED ) return;
    148149                String memberRole = roleBoxModel.getSelectedMembersRole();
    149150                String selectedRole = roleBoxModel.isAnotherRoleSelected() ? askForRoleName() : roleBoxModel.getSelectedRole();
    150                 if( memberRole != null && selectedRole != null && !memberRole.equals(selectedRole) ) {
     151                if (memberRole != null && selectedRole != null && !memberRole.equals(selectedRole)) {
    151152                    applyRoleToSelection(selectedRole.trim());
    152153                }
     
    177178        roleBox.addPropertyChangeListener("enabled", new PropertyChangeListener() {
    178179            @Override
    179             public void propertyChange( PropertyChangeEvent evt ) {
     180            public void propertyChange(PropertyChangeEvent evt) {
    180181                boolean showRoleBox = roleBox.isEnabled();
    181182                roleBox.setVisible(showRoleBox);
     
    186187        sortAndFixAction.addPropertyChangeListener(new PropertyChangeListener() {
    187188            @Override
    188             public void propertyChange( PropertyChangeEvent evt ) {
     189            public void propertyChange(PropertyChangeEvent evt) {
    189190                sortAndFixButton.setVisible(sortAndFixAction.isEnabled());
    190191            }
     
    194195        downloadChosenRelationAction.addPropertyChangeListener(new PropertyChangeListener() {
    195196            @Override
    196             public void propertyChange( PropertyChangeEvent evt ) {
     197            public void propertyChange(PropertyChangeEvent evt) {
    197198                downloadButton.setVisible(downloadChosenRelationAction.isEnabled());
    198199            }
    199200        });
    200201        downloadButton.setVisible(false);
    201         if( Main.pref.getBoolean(PREF_PREFIX + ".hidetopline", false) )
     202        if (Main.pref.getBoolean(PREF_PREFIX + ".hidetopline", false) ) {
    202203            chosenRelationPanel.setVisible(false);
     204        }
    203205
    204206        // [+][Multi] [X]Adm [X]Tags [X]1
     
    209211        final JButton multipolygonButton = new JButton(createMultipolygonAction);
    210212        bottomLine.add(multipolygonButton, GBC.std());
    211 //        bottomLine.add(sizeButton(new JButton(new MultipolygonSettingsAction()), 16, 0), GBC.std().fill(GBC.VERTICAL));
     213        //        bottomLine.add(sizeButton(new JButton(new MultipolygonSettingsAction()), 16, 0), GBC.std().fill(GBC.VERTICAL));
    212214        bottomLine.add(Box.createHorizontalGlue(), GBC.std().fill());
    213215        findRelationAction = new FindRelationAction(chosenRelation);
     
    217219        multipolygonButton.addMouseListener(new MouseAdapter() {
    218220            @Override
    219             public void mousePressed( MouseEvent e ) {
     221            public void mousePressed(MouseEvent e) {
    220222                checkPopup(e);
    221223            }
    222224
    223225            @Override
    224             public void mouseReleased( MouseEvent e ) {
     226            public void mouseReleased(MouseEvent e) {
    225227                checkPopup(e);
    226228            }
    227229
    228             private void checkPopup( MouseEvent e ) {
    229                 if( e.isPopupTrigger() )
     230            private void checkPopup(MouseEvent e) {
     231                if (e.isPopupTrigger() ) {
    230232                    multiPopupMenu.show(e.getComponent(), e.getX(), e.getY());
     233                }
    231234            }
    232235        });
     
    237240    private static final Color CHOSEN_RELATION_COLOR = new Color(255, 255, 128);
    238241
    239     private void configureRelationsTable( final JTable relationsTable ) {
     242    private void configureRelationsTable(final JTable relationsTable) {
    240243        relationsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    241244        relationsTable.setTableHeader(null);
    242245        relationsTable.addMouseListener(new MouseAdapter() {
    243246            @Override
    244             public void mouseClicked( MouseEvent e ) {
     247            public void mouseClicked(MouseEvent e) {
    245248                Point p = e.getPoint();
    246249                int row = relationsTable.rowAtPoint(p);
    247                 if( SwingUtilities.isLeftMouseButton(e) && row >= 0 ) {
     250                if (SwingUtilities.isLeftMouseButton(e) && row >= 0) {
    248251                    Relation relation = (Relation)relationsData.getValueAt(row, 0);
    249                     if( e.getClickCount() > 1 ) {
     252                    if (e.getClickCount() > 1) {
    250253                        Main.main.getEditLayer().data.setSelected(relation);
    251254                    }
     
    254257
    255258            @Override
    256             public void mousePressed( MouseEvent e ) {
     259            public void mousePressed(MouseEvent e) {
    257260                checkPopup(e);
    258261            }
    259262
    260263            @Override
    261             public void mouseReleased( MouseEvent e ) {
     264            public void mouseReleased(MouseEvent e) {
    262265                checkPopup(e);
    263266            }
    264267
    265             public void checkPopup( MouseEvent e ) {
    266                 if( e.isPopupTrigger() ) {
     268            public void checkPopup(MouseEvent e) {
     269                if (e.isPopupTrigger()) {
    267270                    Point p = e.getPoint();
    268271                    int row = relationsTable.rowAtPoint(p);
     
    280283        columns.getColumn(0).setCellRenderer(new OsmPrimitivRenderer() {
    281284            @Override
    282             protected String getComponentToolTipText( OsmPrimitive value ) {
     285            protected String getComponentToolTipText(OsmPrimitive value) {
    283286                return null;
    284287            }
    285288
    286289            @Override
    287             public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column ) {
     290            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
    288291                Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
    289                 if( !isSelected && value instanceof Relation && chosenRelation.isSame(value) )
     292                if (!isSelected && value instanceof Relation && chosenRelation.isSame(value) ) {
    290293                    c.setBackground(CHOSEN_RELATION_COLOR);
    291                 else
     294                } else {
    292295                    c.setBackground(table.getBackground());
     296                }
    293297                return c;
    294298            }
     
    297301        columns.getColumn(1).setCellRenderer(new DefaultTableCellRenderer() {
    298302            @Override
    299             public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column ) {
     303            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
    300304                Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
    301                 if( !isSelected && chosenRelation.isSame(table.getValueAt(row, 0)) )
     305                if (!isSelected && chosenRelation.isSame(table.getValueAt(row, 0)) ) {
    302306                    c.setBackground(CHOSEN_RELATION_COLOR);
    303                 else
     307                } else {
    304308                    c.setBackground(table.getBackground());
     309                }
    305310                return c;
    306311            }
     
    310315        relationsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
    311316            @Override
    312             public void valueChanged( ListSelectionEvent e ) {
     317            public void valueChanged(ListSelectionEvent e) {
    313318                int selectedRow = relationsTable.getSelectedRow();
    314                 if( selectedRow >= 0 ) {
     319                if (selectedRow >= 0) {
    315320                    chosenRelation.set((Relation)relationsData.getValueAt(selectedRow, 0));
    316321                    relationsTable.clearSelection();
     
    320325    }
    321326
    322     private JComponent sizeButton( JComponent b, int width, int height ) {
     327    private JComponent sizeButton(JComponent b, int width, int height) {
    323328        Dimension pref = b.getPreferredSize();
    324329        b.setPreferredSize(new Dimension(width <= 0 ? pref.width : width, height <= 0 ? pref.height : height));
     
    346351
    347352    @Override
    348     public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) {
    349         if( chosenRelationPanel != null && Main.pref.getBoolean(PREF_PREFIX + ".hidetopline", false) )
     353    public void chosenRelationChanged(Relation oldRelation, Relation newRelation) {
     354        if (chosenRelationPanel != null && Main.pref.getBoolean(PREF_PREFIX + ".hidetopline", false) ) {
    350355            chosenRelationPanel.setVisible(newRelation != null);
    351         if( Main.main.getCurrentDataSet() != null )
     356        }
     357        if (Main.main.getCurrentDataSet() != null ) {
    352358            selectionChanged(Main.main.getCurrentDataSet().getSelected());
     359        }
    353360        roleBoxModel.update();
    354361        // ?
     
    356363
    357364    @Override
    358     public void selectionChanged( Collection<? extends OsmPrimitive> newSelection ) {
    359         if( !isVisible() || relationsData == null )
     365    public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
     366        if (!isVisible() || relationsData == null )
    360367            return;
    361368        roleBoxModel.update();
     
    363370        relationsData.setRowCount(0);
    364371        sortAndFixAction.chosenRelationChanged(chosenRelation.get(), chosenRelation.get());
    365         if( newSelection == null )
     372        if (newSelection == null )
    366373            return;
    367374
    368375        Set<Relation> relations = new TreeSet<>(
    369376                DefaultNameFormatter.getInstance().getRelationComparator());
    370         for( OsmPrimitive element : newSelection ) {
    371             for( OsmPrimitive ref : element.getReferrers() ) {
    372                 if( ref instanceof Relation && !ref.isIncomplete() && !ref.isDeleted() ) {
     377        for (OsmPrimitive element : newSelection) {
     378            for (OsmPrimitive ref : element.getReferrers()) {
     379                if (ref instanceof Relation && !ref.isIncomplete() && !ref.isDeleted()) {
    373380                    relations.add((Relation) ref);
    374381                }
     
    376383        }
    377384
    378         for( Relation rel : relations ) {
     385        for (Relation rel : relations) {
    379386            String role = null;
    380             for( RelationMember m : rel.getMembers() ) {
    381                 for( OsmPrimitive element : newSelection ) {
    382                     if( m.getMember().equals(element) ) {
    383                         if( role == null )
     387            for (RelationMember m : rel.getMembers()) {
     388                for (OsmPrimitive element : newSelection) {
     389                    if (m.getMember().equals(element)) {
     390                        if (role == null ) {
    384391                            role = m.getRole();
    385                         else if( !role.equals(m.getRole()) ) {
     392                        } else if (!role.equals(m.getRole())) {
    386393                            role = tr("<different>");
    387394                            break;
     
    392399            relationsData.addRow(new Object[] {rel, role == null ? "" : role});
    393400        }
    394         for( OsmPrimitive element : newSelection )
    395             if( element instanceof Relation && !chosenRelation.isSame(element) )
     401        for (OsmPrimitive element : newSelection )
     402            if (element instanceof Relation && !chosenRelation.isSame(element) ) {
    396403                relationsData.addRow(new Object[] {element, ""});
     404            }
    397405    }
    398406
     
    406414
    407415    @Override
    408     public void editLayerChanged( OsmDataLayer oldLayer, OsmDataLayer newLayer ) {
     416    public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
    409417        updateSelection();
    410418    }
     
    428436        ClassLoader classLoader = RelContextDialog.class.getClassLoader();
    429437        try (
    430             InputStream possibleRolesStream = classLoader.getResourceAsStream(POSSIBLE_ROLES_FILE);
    431             BufferedReader r = new BufferedReader(new InputStreamReader(possibleRolesStream));
    432         ) {
    433             while( r.ready() ) {
     438                InputStream possibleRolesStream = classLoader.getResourceAsStream(POSSIBLE_ROLES_FILE);
     439                BufferedReader r = new BufferedReader(new InputStreamReader(possibleRolesStream));
     440                ) {
     441            while(r.ready()) {
    434442                String line = r.readLine();
    435443                StringTokenizer t = new StringTokenizer(line, " ,;:\"");
    436                 if( t.hasMoreTokens() ) {
     444                if (t.hasMoreTokens()) {
    437445                    String type = t.nextToken();
    438446                    List<String> roles = new ArrayList<>();
    439                     while( t.hasMoreTokens() )
     447                    while(t.hasMoreTokens() ) {
    440448                        roles.add(t.nextToken());
     449                    }
    441450                    result.put(type, roles);
    442451                }
    443452            }
    444         } catch( Exception e ) {
     453        } catch(Exception e) {
    445454            Main.error("[RelToolbox] Error reading possible roles file.");
    446455            Main.error(e);
     
    453462
    454463        List<String> items = new ArrayList<>();
    455         for( String role : roleBoxModel.getRoles() ) {
    456             if( role.length() > 1 )
     464        for (String role : roleBoxModel.getRoles()) {
     465            if (role.length() > 1 ) {
    457466                items.add(role);
     467            }
    458468        }
    459469        final AutoCompletingComboBox role = new AutoCompletingComboBox();
     
    477487        role.getEditor().addActionListener(new ActionListener() {
    478488            @Override
    479             public void actionPerformed( ActionEvent e ) {
     489            public void actionPerformed(ActionEvent e) {
    480490                dlg.setVisible(false);
    481491                optionPane.setValue(JOptionPane.OK_OPTION);
     
    486496
    487497        Object answer = optionPane.getValue();
    488         if( answer == null || answer == JOptionPane.UNINITIALIZED_VALUE
    489                 || (answer instanceof Integer && (Integer)answer != JOptionPane.OK_OPTION) ) {
     498        if (answer == null || answer == JOptionPane.UNINITIALIZED_VALUE
     499                || (answer instanceof Integer && (Integer)answer != JOptionPane.OK_OPTION))
    490500            return null;
    491         }
    492501
    493502        return role.getEditor().getItem().toString().trim();
     
    496505    private class ChosenRelationMouseAdapter extends MouseAdapter {
    497506        @Override
    498         public void mouseClicked( MouseEvent e ) {
    499             if( e.isControlDown() || !(e.getComponent() instanceof JComboBox ) ) // do not use left click handler on combo box
    500             if( SwingUtilities.isLeftMouseButton(e) && chosenRelation.get() != null && Main.main.getEditLayer() != null ) {
    501                 Main.main.getEditLayer().data.setSelected(chosenRelation.get());
    502             }
    503         }
    504 
    505         @Override
    506         public void mousePressed( MouseEvent e ) {
     507        public void mouseClicked(MouseEvent e) {
     508            if (e.isControlDown() || !(e.getComponent() instanceof JComboBox ) ) // do not use left click handler on combo box
     509                if (SwingUtilities.isLeftMouseButton(e) && chosenRelation.get() != null && Main.main.getEditLayer() != null) {
     510                    Main.main.getEditLayer().data.setSelected(chosenRelation.get());
     511                }
     512        }
     513
     514        @Override
     515        public void mousePressed(MouseEvent e) {
    507516            checkPopup(e);
    508517        }
    509518
    510519        @Override
    511         public void mouseReleased( MouseEvent e ) {
     520        public void mouseReleased(MouseEvent e) {
    512521            checkPopup(e);
    513522        }
    514523
    515         private void checkPopup( MouseEvent e ) {
    516             if( e.isPopupTrigger() && chosenRelation.get() != null ) {
     524        private void checkPopup(MouseEvent e) {
     525            if (e.isPopupTrigger() && chosenRelation.get() != null) {
    517526                popupMenu.show(e.getComponent(), e.getX(), e.getY() - 5);
    518527            }
     
    521530
    522531    private class ChosenRelationPopupMenu extends JPopupMenu {
    523         public ChosenRelationPopupMenu( ChosenRelation chosenRelation ) {
     532        public ChosenRelationPopupMenu(ChosenRelation chosenRelation) {
    524533            add(new SelectMembersAction(chosenRelation));
    525534            add(new SelectRelationAction(chosenRelation));
     
    535544    }
    536545
    537     protected void applyRoleToSelection( String role ) {
    538         if( chosenRelation != null && chosenRelation.get() != null && Main.main.getCurrentDataSet() != null && !Main.main.getCurrentDataSet().selectionEmpty() ) {
     546    protected void applyRoleToSelection(String role) {
     547        if (chosenRelation != null && chosenRelation.get() != null && Main.main.getCurrentDataSet() != null && !Main.main.getCurrentDataSet().selectionEmpty()) {
    539548            Collection<OsmPrimitive> selected = Main.main.getCurrentDataSet().getSelected();
    540549            Relation r = chosenRelation.get();
    541550            List<Command> commands = new ArrayList<>();
    542             for( int i = 0; i < r.getMembersCount(); i++ ) {
     551            for (int i = 0; i < r.getMembersCount(); i++) {
    543552                RelationMember m = r.getMember(i);
    544                 if( selected.contains(m.getMember()) ) {
    545                     if( !role.equals(m.getRole()) ) {
    546 //                        r.setMember(i, new RelationMember(role, m.getMember()));
     553                if (selected.contains(m.getMember())) {
     554                    if (!role.equals(m.getRole())) {
     555                        //                        r.setMember(i, new RelationMember(role, m.getMember()));
    547556                        commands.add(new ChangeRelationMemberRoleCommand(r, i, role));
    548557                    }
    549558                }
    550559            }
    551             if( !commands.isEmpty() ) {
    552 //                Main.main.undoRedo.add(new ChangeCommand(chosenRelation.get(), r));
     560            if (!commands.isEmpty()) {
     561                //                Main.main.undoRedo.add(new ChangeCommand(chosenRelation.get(), r));
    553562                Main.main.undoRedo.add(new SequenceCommand(tr("Change relation member roles to {0}", role), commands));
    554563            }
     
    567576        }
    568577    }
    569 /*
     578    /*
    570579    private class MultipolygonSettingsAction extends AbstractAction {
    571580        public MultipolygonSettingsAction() {
     
    575584        }
    576585
    577         public void actionPerformed( ActionEvent e ) {
     586        public void actionPerformed(ActionEvent e) {
    578587            Component c = e.getSource() instanceof Component ? (Component)e.getSource() : Main.parent;
    579588            multiPopupMenu.show(c, 0, 0);
     
    591600        }
    592601
    593         protected final JCheckBoxMenuItem addMenuItem( String property, String title ) {
     602        protected final JCheckBoxMenuItem addMenuItem(String property, String title) {
    594603            String fullProperty = PREF_PREFIX + ".multipolygon." + property;
    595604            JCheckBoxMenuItem item = new JCheckBoxMenuItem(tr(title));
     
    602611
    603612        @Override
    604         public void actionPerformed( ActionEvent e ) {
     613        public void actionPerformed(ActionEvent e) {
    605614            String property = e.getActionCommand();
    606             if( property != null && property.length() > 0 && e.getSource() instanceof JCheckBoxMenuItem ) {
     615            if (property != null && property.length() > 0 && e.getSource() instanceof JCheckBoxMenuItem) {
    607616                boolean value = ((JCheckBoxMenuItem)e.getSource()).isSelected();
    608617                Main.pref.put(property, value);
     
    617626            super(tr("Change role"), (String)null, tr("Enter role for selected members"),
    618627                    Shortcut.registerShortcut("reltoolbox:changerole", tr("Relation Toolbox: {0}", tr("Enter role for selected members")),
    619                     KeyEvent.VK_R, Shortcut.ALT_CTRL), false, "relcontext/enterrole", true);
     628                            KeyEvent.VK_R, Shortcut.ALT_CTRL), false, "relcontext/enterrole", true);
    620629            chosenRelation.addChosenRelationListener(this);
    621630            updateEnabledState();
     
    623632
    624633        @Override
    625         public void actionPerformed( ActionEvent e ) {
    626             if( roleBoxModel.membersRole != null ) {
     634        public void actionPerformed(ActionEvent e) {
     635            if (roleBoxModel.membersRole != null) {
    627636                String role = askForRoleName();
    628                 if( role != null )
     637                if (role != null ) {
    629638                    applyRoleToSelection(role);
    630             }
    631         }
    632 
    633         @Override
    634         public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) {
     639                }
     640            }
     641        }
     642
     643        @Override
     644        public void chosenRelationChanged(Relation oldRelation, Relation newRelation) {
    635645            setEnabled(newRelation != null);
    636646        }
     
    645655        private final String ANOTHER_ROLE = tr("another...");
    646656
    647         public RoleComboBoxModel( JComboBox<String> combobox ) {
     657        public RoleComboBoxModel(JComboBox<String> combobox) {
    648658            super();
    649659            this.combobox = combobox;
     
    653663        public void update() {
    654664            membersRole = getSelectedMembersRoleIntl();
    655             if( membersRole == null ) {
    656                 if( combobox.isEnabled() )
     665            if (membersRole == null) {
     666                if (combobox.isEnabled() ) {
    657667                    combobox.setEnabled(false);
     668                }
    658669                return;
    659670            }
    660             if( !combobox.isEnabled() )
     671            if (!combobox.isEnabled() ) {
    661672                combobox.setEnabled(true);
     673            }
    662674
    663675            List<String> items = new ArrayList<>();
    664             if( chosenRelation != null && chosenRelation.get() != null ) {
    665                 if( chosenRelation.isMultipolygon() ) {
     676            if (chosenRelation != null && chosenRelation.get() != null) {
     677                if (chosenRelation.isMultipolygon()) {
    666678                    items.add("outer");
    667679                    items.add("inner");
    668680                }
    669                 if( chosenRelation.get().get("type") != null ) {
     681                if (chosenRelation.get().get("type") != null) {
    670682                    List<String> values = possibleRoles.get(chosenRelation.get().get("type"));
    671                     if( values != null )
     683                    if (values != null ) {
    672684                        items.addAll(values);
    673                 }
    674                 for( RelationMember m : chosenRelation.get().getMembers() )
    675                     if( m.getRole().length() > 0 && !items.contains(m.getRole()) )
     685                    }
     686                }
     687                for (RelationMember m : chosenRelation.get().getMembers() )
     688                    if (m.getRole().length() > 0 && !items.contains(m.getRole()) ) {
    676689                        items.add(m.getRole());
     690                    }
    677691            }
    678692            items.add(EMPTY_ROLE);
    679             if( !items.contains(membersRole) )
     693            if (!items.contains(membersRole) ) {
    680694                items.add(0, membersRole);
     695            }
    681696            items.add(ANOTHER_ROLE);
    682697            roles = Collections.unmodifiableList(items);
    683698
    684             if( membersRole != null )
     699            if (membersRole != null ) {
    685700                setSelectedItem(membersRole);
    686             else
     701            } else {
    687702                fireContentsChanged(this, -1, -1);
     703            }
    688704            combobox.repaint();
    689705        }
     
    699715        private String getSelectedMembersRoleIntl() {
    700716            String role = null;
    701             if( chosenRelation != null && chosenRelation.get() != null && Main.main.getCurrentDataSet() != null && !Main.main.getCurrentDataSet().selectionEmpty() ) {
     717            if (chosenRelation != null && chosenRelation.get() != null && Main.main.getCurrentDataSet() != null && !Main.main.getCurrentDataSet().selectionEmpty()) {
    702718                Collection<OsmPrimitive> selected = Main.main.getCurrentDataSet().getSelected();
    703                 for( RelationMember m : chosenRelation.get().getMembers() ) {
    704                     if( selected.contains(m.getMember()) ) {
    705                         if( role == null )
     719                for (RelationMember m : chosenRelation.get().getMembers()) {
     720                    if (selected.contains(m.getMember())) {
     721                        if (role == null ) {
    706722                            role = m.getRole();
    707                         else if( m.getRole() != null && !role.equals(m.getRole()) ) {
     723                        } else if (m.getRole() != null && !role.equals(m.getRole())) {
    708724                            role = tr("<different>");
    709725                            break;
     
    725741
    726742        @Override
    727         public String getElementAt( int index ) {
     743        public String getElementAt(int index) {
    728744            return getRole(index);
    729745        }
    730746
    731         public String getRole( int index ) {
     747        public String getRole(int index) {
    732748            return roles.get(index);
    733749        }
    734750
    735751        @Override
    736         public void setSelectedItem( Object anItem ) {
     752        public void setSelectedItem(Object anItem) {
    737753            int newIndex = anItem == null ? -1 : roles.indexOf(anItem);
    738             if( newIndex != selectedIndex ) {
     754            if (newIndex != selectedIndex) {
    739755                selectedIndex = newIndex;
    740756                fireContentsChanged(this, -1, -1);
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/RelContextPlugin.java

    r30841 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext;
    23
     
    910    private RelContextDialog dialog;
    1011
    11     public RelContextPlugin( PluginInformation info ) {
     12    public RelContextPlugin(PluginInformation info) {
    1213        super(info);
    13     DefaultNameFormatter.registerFormatHook(new ExtraNameFormatHook());
     14        DefaultNameFormatter.registerFormatHook(new ExtraNameFormatHook());
    1415    }
    1516
    1617    @Override
    17     public void mapFrameInitialized( MapFrame oldFrame, MapFrame newFrame ) {
    18         if( oldFrame == null && newFrame != null ) {
    19 //            if (dialog!=null) dialog.destroy();
     18    public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
     19        if (oldFrame == null && newFrame != null) {
     20            //            if (dialog!=null) dialog.destroy();
    2021            dialog = new RelContextDialog();
    2122            newFrame.addToggleDialog(dialog);
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/StaticChosenRelation.java

    r30841 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext;
    23
     
    1011public class StaticChosenRelation extends ChosenRelation {
    1112
    12     public StaticChosenRelation( Relation rel ) {
     13    public StaticChosenRelation(Relation rel) {
    1314        chosenRelation = rel;
    1415        analyse();
     
    1617
    1718    @Override
    18     public void set( Relation rel ) {
    19 //        throw new UnsupportedOperationException("Changing static relation is not supported.");
     19    public void set(Relation rel) {
     20        //        throw new UnsupportedOperationException("Changing static relation is not supported.");
    2021    }
    2122}
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/AddRemoveMemberAction.java

    r31662 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext.actions;
    23
     
    3637    private SortAndFixAction sortAndFix;
    3738
    38     public AddRemoveMemberAction( ChosenRelation rel, SortAndFixAction sortAndFix ) {
     39    public AddRemoveMemberAction(ChosenRelation rel, SortAndFixAction sortAndFix) {
    3940        super(null, "relcontext/addremove", tr("Add/remove members from the chosen relation"),
    4041                Shortcut.registerShortcut("reltoolbox:addremove", tr("Relation Toolbox: {0}", tr("Add/remove members from the chosen relation")),
    41                 KeyEvent.VK_EQUALS, Shortcut.DIRECT), false);
     42                        KeyEvent.VK_EQUALS, Shortcut.DIRECT), false);
    4243        this.rel = rel;
    4344        this.sortAndFix = sortAndFix;
     
    4647    }
    4748
    48     public void actionPerformed( ActionEvent e ) {
    49         if( rel.get() == null )
     49    @Override
     50    public void actionPerformed(ActionEvent e) {
     51        if (rel.get() == null )
    5052            return;
    5153
     
    6365
    6466        // 2. add all new members
    65         for( OsmPrimitive p : toAdd ) {
     67        for (OsmPrimitive p : toAdd) {
    6668            int pos = -1; //p instanceof Way ? findAdjacentMember(p, r) : -1;
    67             if( pos < 0 )
     69            if (pos < 0 ) {
    6870                r.addMember(new RelationMember("", p));
    69             else
     71            } else {
    7072                r.addMember(pos, new RelationMember("", p));
     73            }
    7174        }
    7275
    7376        // 3. check for roles again (temporary)
    7477        Command roleFix = !isBroken && sortAndFix.needsFixing(r) ? sortAndFix.fixRelation(r) : null;
    75         if( roleFix != null )
     78        if (roleFix != null ) {
    7679            roleFix.executeCommand();
     80        }
    7781
    78         if( !r.getMemberPrimitives().equals(rel.get().getMemberPrimitives()) )
     82        if (!r.getMemberPrimitives().equals(rel.get().getMemberPrimitives()) ) {
    7983            Main.main.undoRedo.add(new ChangeCommand(rel.get(), r));
     84        }
    8085    }
    8186
     
    8489     * @see org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel#determineDirection
    8590     */
    86     protected int findAdjacentMember( Way w, Relation r ) {
     91    protected int findAdjacentMember(Way w, Relation r) {
    8792        Node firstNode = w.firstNode();
    8893        Node lastNode = w.lastNode();
    8994
    90         if( firstNode != null && !firstNode.equals(lastNode) ) {
    91             for( int i = 0; i < r.getMembersCount(); i++ ) {
    92                 if( r.getMember(i).getType().equals(OsmPrimitiveType.WAY) ) {
     95        if (firstNode != null && !firstNode.equals(lastNode)) {
     96            for (int i = 0; i < r.getMembersCount(); i++) {
     97                if (r.getMember(i).getType().equals(OsmPrimitiveType.WAY)) {
    9398                    Way rw = (Way)r.getMember(i).getMember();
    9499                    Node firstNodeR = rw.firstNode();
    95100                    Node lastNodeR = rw.lastNode();
    96                     if( firstNode.equals(firstNodeR) || firstNode.equals(lastNodeR) || lastNode.equals(firstNodeR) || lastNode.equals(lastNodeR) )
     101                    if (firstNode.equals(firstNodeR) || firstNode.equals(lastNodeR) || lastNode.equals(firstNodeR) || lastNode.equals(lastNodeR) )
    97102                        return i + 1;
    98103                }
     
    102107    }
    103108
    104     public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) {
     109    @Override
     110    public void chosenRelationChanged(Relation oldRelation, Relation newRelation) {
    105111        updateEnabledState();
    106112    }
     
    112118
    113119    @Override
    114     protected void updateEnabledState( Collection<? extends OsmPrimitive> selection ) {
     120    protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) {
    115121        updateIcon();
    116         if( rel == null || rel.get() == null || selection == null || selection.isEmpty() ) {
     122        if (rel == null || rel.get() == null || selection == null || selection.isEmpty()) {
    117123            setEnabled(false);
    118124            return;
    119125        }
    120         if( selection.size() == 1 && selection.contains(rel.get()) ) {
     126        if (selection.size() == 1 && selection.contains(rel.get())) {
    121127            setEnabled(false);
    122128            return;
     
    128134        // todo: change icon based on selection
    129135        final int state; // 0=unknown, 1=add, 2=remove, 3=both
    130         if( getCurrentDataSet() == null || getCurrentDataSet().getSelected() == null
    131                 || getCurrentDataSet().getSelected().isEmpty() || rel == null || rel.get() == null )
     136        if (getCurrentDataSet() == null || getCurrentDataSet().getSelected() == null
     137                || getCurrentDataSet().getSelected().isEmpty() || rel == null || rel.get() == null ) {
    132138            state = 0;
    133         else {
     139        } else {
    134140            Collection<OsmPrimitive> toAdd = new ArrayList<>(getCurrentDataSet().getSelected());
    135141            toAdd.remove(rel.get());
    136142            int selectedSize = toAdd.size();
    137             if( selectedSize == 0 )
     143            if (selectedSize == 0 ) {
    138144                state = 0;
    139             else {
     145            } else {
    140146                toAdd.removeAll(rel.get().getMemberPrimitives());
    141                 if( toAdd.isEmpty() )
     147                if (toAdd.isEmpty() ) {
    142148                    state = 2;
    143                 else if( toAdd.size() < selectedSize )
     149                } else if (toAdd.size() < selectedSize ) {
    144150                    state = 3;
    145                 else
     151                } else {
    146152                    state = 1;
     153                }
    147154            }
    148155        }
     
    150157            @Override
    151158            public void run() {
    152 //        String name = state == 0 ? "?" : state == 1 ? "+" : state == 2 ? "-" : "±";
    153 //        putValue(Action.NAME, name);
     159                //        String name = state == 0 ? "?" : state == 1 ? "+" : state == 2 ? "-" : "±";
     160                //        putValue(Action.NAME, name);
    154161                if (state == 0) {
    155 //            putValue(NAME, "?");
     162                    //            putValue(NAME, "?");
    156163                    putValue(LARGE_ICON_KEY, ImageProvider.get("relcontext", "addremove"));
    157164                } else {
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/ClearChosenRelationAction.java

    r25695 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext.actions;
    23
     4import static org.openstreetmap.josm.tools.I18n.tr;
     5
    36import java.awt.event.ActionEvent;
     7
    48import javax.swing.AbstractAction;
    59import javax.swing.Action;
    6 import static org.openstreetmap.josm.tools.I18n.tr;
     10
    711import org.openstreetmap.josm.data.osm.Relation;
    812import org.openstreetmap.josm.tools.ImageProvider;
     13
    914import relcontext.ChosenRelation;
    1015import relcontext.ChosenRelationListener;
     
    1318    private ChosenRelation rel;
    1419
    15     public ClearChosenRelationAction( ChosenRelation rel ) {
     20    public ClearChosenRelationAction(ChosenRelation rel) {
    1621        super();
    17 //        putValue(Action.NAME, "X");
     22        //        putValue(Action.NAME, "X");
    1823        putValue(Action.SMALL_ICON, ImageProvider.get("relcontext", "clear"));
    1924        putValue(Action.SHORT_DESCRIPTION, tr("Clear the chosen relation"));
     
    2328    }
    2429
    25     public void actionPerformed( ActionEvent e ) {
     30    @Override
     31    public void actionPerformed(ActionEvent e) {
    2632        rel.clear();
    2733    }
    2834
    29     public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) {
     35    @Override
     36    public void chosenRelationChanged(Relation oldRelation, Relation newRelation) {
    3037        setEnabled(newRelation != null);
    3138    }
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/CreateMultipolygonAction.java

    r30738 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext.actions;
     3
     4import static org.openstreetmap.josm.tools.I18n.tr;
    25
    36import java.awt.Dialog.ModalityType;
    47import java.awt.GridBagLayout;
    5 import static org.openstreetmap.josm.tools.I18n.tr;
    68import java.awt.event.ActionEvent;
    79import java.awt.event.ActionListener;
    810import java.awt.event.KeyEvent;
    9 import java.util.*;
    10 import javax.swing.*;
     11import java.util.ArrayList;
     12import java.util.Arrays;
     13import java.util.Collection;
     14import java.util.HashMap;
     15import java.util.HashSet;
     16import java.util.List;
     17import java.util.Map;
     18import java.util.Set;
     19import java.util.TreeSet;
     20
     21import javax.swing.Box;
     22import javax.swing.JDialog;
     23import javax.swing.JLabel;
     24import javax.swing.JOptionPane;
     25import javax.swing.JPanel;
     26import javax.swing.JTextField;
     27
    1128import org.openstreetmap.josm.Main;
    1229import org.openstreetmap.josm.actions.JosmAction;
    13 import org.openstreetmap.josm.command.*;
    14 import org.openstreetmap.josm.data.osm.*;
     30import org.openstreetmap.josm.command.AddCommand;
     31import org.openstreetmap.josm.command.ChangeCommand;
     32import org.openstreetmap.josm.command.ChangePropertyCommand;
     33import org.openstreetmap.josm.command.Command;
     34import org.openstreetmap.josm.command.SequenceCommand;
     35import org.openstreetmap.josm.data.osm.MultipolygonBuilder;
     36import org.openstreetmap.josm.data.osm.Node;
     37import org.openstreetmap.josm.data.osm.OsmPrimitive;
     38import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
     39import org.openstreetmap.josm.data.osm.Relation;
     40import org.openstreetmap.josm.data.osm.RelationMember;
     41import org.openstreetmap.josm.data.osm.Way;
    1542import org.openstreetmap.josm.tools.GBC;
    1643import org.openstreetmap.josm.tools.Shortcut;
     44
    1745import relcontext.ChosenRelation;
    1846
     
    2755    protected ChosenRelation chRel;
    2856
    29     public CreateMultipolygonAction( ChosenRelation chRel ) {
    30     super("Multi", "data/multipolygon", tr("Create a multipolygon from selected objects"),
    31         Shortcut.registerShortcut("reltoolbox:multipolygon", tr("Relation Toolbox: {0}", tr("Create multipolygon")),
    32         KeyEvent.VK_A, Shortcut.ALT_CTRL), false);
    33     this.chRel = chRel;
    34     updateEnabledState();
     57    public CreateMultipolygonAction(ChosenRelation chRel) {
     58        super("Multi", "data/multipolygon", tr("Create a multipolygon from selected objects"),
     59                Shortcut.registerShortcut("reltoolbox:multipolygon", tr("Relation Toolbox: {0}", tr("Create multipolygon")),
     60                        KeyEvent.VK_A, Shortcut.ALT_CTRL), false);
     61        this.chRel = chRel;
     62        updateEnabledState();
    3563    }
    3664
    3765    public CreateMultipolygonAction() {
    38     this(null);
    39     }
    40 
    41     public static boolean getDefaultPropertyValue( String property ) {
    42     if( property.equals("boundary") )
    43         return false;
    44     else if( property.equals("boundaryways") )
    45         return true;
    46     else if( property.equals("tags") )
    47         return true;
    48     else if( property.equals("alltags") )
    49         return false;
    50     else if( property.equals("single") )
    51         return true;
    52     else if( property.equals("allowsplit") )
    53         return false;
    54     throw new IllegalArgumentException(property);
    55     }
    56 
    57     private boolean getPref( String property ) {
    58     return Main.pref.getBoolean(PREF_MULTIPOLY + property, getDefaultPropertyValue(property));
    59     }
    60 
    61     public void actionPerformed( ActionEvent e ) {
    62     boolean isBoundary = getPref("boundary");
    63     Collection<Way> selectedWays = getCurrentDataSet().getSelectedWays();
    64     if( !isBoundary && getPref("tags") ) {
    65         List<Relation> rels = null;
    66         if( getPref("allowsplit") || selectedWays.size() == 1 ) {
    67         if( SplittingMultipolygons.canProcess(selectedWays) )
    68             rels = SplittingMultipolygons.process(getCurrentDataSet().getSelectedWays());
     66        this(null);
     67    }
     68
     69    public static boolean getDefaultPropertyValue(String property) {
     70        if (property.equals("boundary") )
     71            return false;
     72        else if (property.equals("boundaryways") )
     73            return true;
     74        else if (property.equals("tags") )
     75            return true;
     76        else if (property.equals("alltags") )
     77            return false;
     78        else if (property.equals("single") )
     79            return true;
     80        else if (property.equals("allowsplit") )
     81            return false;
     82        throw new IllegalArgumentException(property);
     83    }
     84
     85    private boolean getPref(String property) {
     86        return Main.pref.getBoolean(PREF_MULTIPOLY + property, getDefaultPropertyValue(property));
     87    }
     88
     89    @Override
     90    public void actionPerformed(ActionEvent e) {
     91        boolean isBoundary = getPref("boundary");
     92        Collection<Way> selectedWays = getCurrentDataSet().getSelectedWays();
     93        if (!isBoundary && getPref("tags")) {
     94            List<Relation> rels = null;
     95            if (getPref("allowsplit") || selectedWays.size() == 1) {
     96                if (SplittingMultipolygons.canProcess(selectedWays) ) {
     97                    rels = SplittingMultipolygons.process(getCurrentDataSet().getSelectedWays());
     98                }
     99            } else {
     100                if (TheRing.areAllOfThoseRings(selectedWays)) {
     101                    List<Command> commands = new ArrayList<>();
     102                    rels = TheRing.makeManySimpleMultipolygons(getCurrentDataSet().getSelectedWays(), commands);
     103                    if (!commands.isEmpty() ) {
     104                        Main.main.undoRedo.add(new SequenceCommand(tr("Create multipolygons from rings"), commands));
     105                    }
     106                }
     107            }
     108            if (rels != null && !rels.isEmpty()) {
     109                if (chRel != null ) {
     110                    chRel.set(rels.size() == 1 ? rels.get(0) : null);
     111                }
     112                if (rels.size() == 1 ) {
     113                    getCurrentDataSet().setSelected(rels);
     114                } else {
     115                    getCurrentDataSet().clearSelection();
     116                }
     117                return;
     118            }
     119        }
     120
     121        // for now, just copying standard action
     122        MultipolygonBuilder mpc = new MultipolygonBuilder();
     123        String error = mpc.makeFromWays(getCurrentDataSet().getSelectedWays());
     124        if (error != null) {
     125            JOptionPane.showMessageDialog(Main.parent, error);
     126            return;
     127        }
     128        Relation rel = new Relation();
     129        if (isBoundary) {
     130            rel.put("type", "boundary");
     131            rel.put("boundary", "administrative");
    69132        } else {
    70         if( TheRing.areAllOfThoseRings(selectedWays) ) {
    71             List<Command> commands = new ArrayList<>();
    72             rels = TheRing.makeManySimpleMultipolygons(getCurrentDataSet().getSelectedWays(), commands);
    73             if( !commands.isEmpty() )
    74             Main.main.undoRedo.add(new SequenceCommand(tr("Create multipolygons from rings"), commands));
    75         }
    76         }
    77         if( rels != null && !rels.isEmpty() ) {
    78         if( chRel != null )
    79             chRel.set(rels.size() == 1 ? rels.get(0) : null);
    80         if( rels.size() == 1 )
    81             getCurrentDataSet().setSelected(rels);
    82         else
    83             getCurrentDataSet().clearSelection();
    84         return;
    85         }
    86     }
    87 
    88     // for now, just copying standard action
    89     MultipolygonBuilder mpc = new MultipolygonBuilder();
    90     String error = mpc.makeFromWays(getCurrentDataSet().getSelectedWays());
    91     if( error != null ) {
    92         JOptionPane.showMessageDialog(Main.parent, error);
    93         return;
    94     }
    95     Relation rel = new Relation();
    96     if( isBoundary ) {
    97         rel.put("type", "boundary");
    98         rel.put("boundary", "administrative");
    99     } else
    100         rel.put("type", "multipolygon");
    101     for( MultipolygonBuilder.JoinedPolygon poly : mpc.outerWays )
    102         for( Way w : poly.ways )
    103         rel.addMember(new RelationMember("outer", w));
    104     for( MultipolygonBuilder.JoinedPolygon poly : mpc.innerWays )
    105         for( Way w : poly.ways )
    106         rel.addMember(new RelationMember("inner", w));
    107     List<Command> list = removeTagsFromInnerWays(rel);
    108     if( !list.isEmpty() && isBoundary ) {
    109         Main.main.undoRedo.add(new SequenceCommand(tr("Move tags from ways to relation"), list));
    110         list = new ArrayList<>();
    111     }
    112     if( isBoundary ) {
    113         if( !askForAdminLevelAndName(rel) )
    114         return;
    115         addBoundaryMembers(rel);
    116         if( getPref("boundaryways") )
    117         list.addAll(fixWayTagsForBoundary(rel));
    118     }
    119     list.add(new AddCommand(rel));
    120     Main.main.undoRedo.add(new SequenceCommand(tr("Create multipolygon"), list));
    121 
    122     if( chRel != null )
    123         chRel.set(rel);
    124 
    125     getCurrentDataSet().setSelected(rel);
     133            rel.put("type", "multipolygon");
     134        }
     135        for (MultipolygonBuilder.JoinedPolygon poly : mpc.outerWays ) {
     136            for (Way w : poly.ways ) {
     137                rel.addMember(new RelationMember("outer", w));
     138            }
     139        }
     140        for (MultipolygonBuilder.JoinedPolygon poly : mpc.innerWays ) {
     141            for (Way w : poly.ways ) {
     142                rel.addMember(new RelationMember("inner", w));
     143            }
     144        }
     145        List<Command> list = removeTagsFromInnerWays(rel);
     146        if (!list.isEmpty() && isBoundary) {
     147            Main.main.undoRedo.add(new SequenceCommand(tr("Move tags from ways to relation"), list));
     148            list = new ArrayList<>();
     149        }
     150        if (isBoundary) {
     151            if (!askForAdminLevelAndName(rel) )
     152                return;
     153            addBoundaryMembers(rel);
     154            if (getPref("boundaryways") ) {
     155                list.addAll(fixWayTagsForBoundary(rel));
     156            }
     157        }
     158        list.add(new AddCommand(rel));
     159        Main.main.undoRedo.add(new SequenceCommand(tr("Create multipolygon"), list));
     160
     161        if (chRel != null ) {
     162            chRel.set(rel);
     163        }
     164
     165        getCurrentDataSet().setSelected(rel);
    126166    }
    127167
    128168    @Override
    129169    protected void updateEnabledState() {
    130     if( getCurrentDataSet() == null ) {
    131         setEnabled(false);
    132     } else {
    133         updateEnabledState(getCurrentDataSet().getSelected());
    134     }
     170        if (getCurrentDataSet() == null) {
     171            setEnabled(false);
     172        } else {
     173            updateEnabledState(getCurrentDataSet().getSelected());
     174        }
    135175    }
    136176
    137177    @Override
    138     protected void updateEnabledState( Collection<? extends OsmPrimitive> selection ) {
    139     boolean isEnabled = true;
    140     if( selection == null || selection.isEmpty() )
    141         isEnabled = false;
    142     else {
    143         if( !getPref("boundary") ) {
    144         for( OsmPrimitive p : selection ) {
    145             if( !(p instanceof Way) ) {
     178    protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) {
     179        boolean isEnabled = true;
     180        if (selection == null || selection.isEmpty() ) {
    146181            isEnabled = false;
    147             break;
    148             }
    149         }
    150         }
    151     }
    152     setEnabled(isEnabled);
     182        } else {
     183            if (!getPref("boundary")) {
     184                for (OsmPrimitive p : selection) {
     185                    if (!(p instanceof Way)) {
     186                        isEnabled = false;
     187                        break;
     188                    }
     189                }
     190            }
     191        }
     192        setEnabled(isEnabled);
    153193    }
    154194
     
    156196     * Add selected nodes and relations with corresponding roles.
    157197     */
    158     private void addBoundaryMembers( Relation rel ) {
    159     for( OsmPrimitive p : getCurrentDataSet().getSelected() ) {
    160         String role = null;
    161         if( p.getType().equals(OsmPrimitiveType.RELATION) ) {
    162         role = "subarea";
    163         } else if( p.getType().equals(OsmPrimitiveType.NODE) ) {
    164         Node n = (Node)p;
    165         if( !n.isIncomplete() ) {
    166             if( n.hasKey("place") )
    167             role = "admin_centre";
    168             else
    169             role = "label";
    170         }
    171         }
    172         if( role != null )
    173         rel.addMember(new RelationMember(role, p));
    174     }
     198    private void addBoundaryMembers(Relation rel) {
     199        for (OsmPrimitive p : getCurrentDataSet().getSelected()) {
     200            String role = null;
     201            if (p.getType().equals(OsmPrimitiveType.RELATION)) {
     202                role = "subarea";
     203            } else if (p.getType().equals(OsmPrimitiveType.NODE)) {
     204                Node n = (Node)p;
     205                if (!n.isIncomplete()) {
     206                    if (n.hasKey("place") ) {
     207                        role = "admin_centre";
     208                    } else {
     209                        role = "label";
     210                    }
     211                }
     212            }
     213            if (role != null ) {
     214                rel.addMember(new RelationMember(role, p));
     215            }
     216        }
    175217    }
    176218
     
    178220     * For all untagged ways in relation, add tags boundary and admin_level.
    179221     */
    180     private List<Command> fixWayTagsForBoundary( Relation rel ) {
    181     List<Command> commands = new ArrayList<>();
    182     if( !rel.hasKey("boundary") || !rel.hasKey("admin_level") )
     222    private List<Command> fixWayTagsForBoundary(Relation rel) {
     223        List<Command> commands = new ArrayList<>();
     224        if (!rel.hasKey("boundary") || !rel.hasKey("admin_level") )
     225            return commands;
     226        String adminLevelStr = rel.get("admin_level");
     227        int adminLevel = 0;
     228        try {
     229            adminLevel = Integer.parseInt(adminLevelStr);
     230        } catch(NumberFormatException e) {
     231            return commands;
     232        }
     233        Set<OsmPrimitive> waysBoundary = new HashSet<>();
     234        Set<OsmPrimitive> waysAdminLevel = new HashSet<>();
     235        for (OsmPrimitive p : rel.getMemberPrimitives()) {
     236            if (p instanceof Way) {
     237                int count = 0;
     238                if (p.hasKey("boundary") && p.get("boundary").equals("administrative") ) {
     239                    count++;
     240                }
     241                if (p.hasKey("admin_level") ) {
     242                    count++;
     243                }
     244                if (p.keySet().size() - count == 0) {
     245                    if (!p.hasKey("boundary") ) {
     246                        waysBoundary.add(p);
     247                    }
     248                    if (!p.hasKey("admin_level")) {
     249                        waysAdminLevel.add(p);
     250                    } else {
     251                        try {
     252                            int oldAdminLevel = Integer.parseInt(p.get("admin_level"));
     253                            if (oldAdminLevel > adminLevel ) {
     254                                waysAdminLevel.add(p);
     255                            }
     256                        } catch(NumberFormatException e) {
     257                            waysAdminLevel.add(p); // some garbage, replace it
     258                        }
     259                    }
     260                }
     261            }
     262        }
     263        if (!waysBoundary.isEmpty() ) {
     264            commands.add(new ChangePropertyCommand(waysBoundary, "boundary", "administrative"));
     265        }
     266        if (!waysAdminLevel.isEmpty() ) {
     267            commands.add(new ChangePropertyCommand(waysAdminLevel, "admin_level", adminLevelStr));
     268        }
    183269        return commands;
    184     String adminLevelStr = rel.get("admin_level");
    185     int adminLevel = 0;
    186     try {
    187         adminLevel = Integer.parseInt(adminLevelStr);
    188     } catch( NumberFormatException e ) {
    189         return commands;
    190     }
    191     Set<OsmPrimitive> waysBoundary = new HashSet<>();
    192     Set<OsmPrimitive> waysAdminLevel = new HashSet<>();
    193     for( OsmPrimitive p : rel.getMemberPrimitives() ) {
    194         if( p instanceof Way ) {
    195         int count = 0;
    196         if( p.hasKey("boundary") && p.get("boundary").equals("administrative") )
    197             count++;
    198         if( p.hasKey("admin_level") )
    199             count++;
    200         if( p.keySet().size() - count == 0 ) {
    201             if( !p.hasKey("boundary") )
    202             waysBoundary.add(p);
    203             if( !p.hasKey("admin_level") ) {
    204             waysAdminLevel.add(p);
    205             } else {
    206             try {
    207                 int oldAdminLevel = Integer.parseInt(p.get("admin_level"));
    208                 if( oldAdminLevel > adminLevel )
    209                 waysAdminLevel.add(p);
    210             } catch( NumberFormatException e ) {
    211                 waysAdminLevel.add(p); // some garbage, replace it
    212             }
    213             }
    214         }
    215         }
    216     }
    217     if( !waysBoundary.isEmpty() )
    218         commands.add(new ChangePropertyCommand(waysBoundary, "boundary", "administrative"));
    219     if( !waysAdminLevel.isEmpty() )
    220         commands.add(new ChangePropertyCommand(waysAdminLevel, "admin_level", adminLevelStr));
    221     return commands;
    222270    }
    223271    static public final List<String> DEFAULT_LINEAR_TAGS = Arrays.asList(new String[] {"barrier", "source"});
    224272    private static final Set<String> REMOVE_FROM_BOUNDARY_TAGS = new TreeSet<>(Arrays.asList(new String[] {
    225         "boundary", "boundary_type", "type", "admin_level"
    226         }));
     273            "boundary", "boundary_type", "type", "admin_level"
     274    }));
    227275
    228276    /**
     
    231279     * Todo: rewrite it.
    232280     */
    233     private List<Command> removeTagsFromInnerWays( Relation relation ) {
    234     Map<String, String> values = new HashMap<>();
    235 
    236     if( relation.hasKeys() ) {
    237         for( String key : relation.keySet() ) {
    238         values.put(key, relation.get(key));
    239         }
    240     }
    241 
    242     List<Way> innerWays = new ArrayList<>();
    243     List<Way> outerWays = new ArrayList<>();
    244 
    245     Set<String> conflictingKeys = new TreeSet<>();
    246 
    247     for( RelationMember m : relation.getMembers() ) {
    248 
    249         if( m.hasRole() && "inner".equals(m.getRole()) && m.isWay() && m.getWay().hasKeys() ) {
    250         innerWays.add(m.getWay());
    251         }
    252 
    253         if( m.hasRole() && "outer".equals(m.getRole()) && m.isWay() && m.getWay().hasKeys() ) {
    254         Way way = m.getWay();
    255         outerWays.add(way);
    256         for( String key : way.keySet() ) {
    257             if( !values.containsKey(key) ) { //relation values take precedence
    258             values.put(key, way.get(key));
    259             } else if( !relation.hasKey(key) && !values.get(key).equals(way.get(key)) ) {
    260             conflictingKeys.add(key);
    261             }
    262         }
    263         }
    264     }
    265 
    266     // filter out empty key conflicts - we need second iteration
    267     boolean isBoundary = getPref("boundary");
    268     if( isBoundary || !getPref("alltags") )
    269         for( RelationMember m : relation.getMembers() )
    270         if( m.hasRole() && m.getRole().equals("outer") && m.isWay() )
    271             for( String key : values.keySet() )
    272             if( !m.getWay().hasKey(key) && !relation.hasKey(key) )
    273                 conflictingKeys.add(key);
    274 
    275     for( String key : conflictingKeys )
    276         values.remove(key);
    277 
    278     for( String linearTag : Main.pref.getCollection(PREF_MULTIPOLY + "lineartags", DEFAULT_LINEAR_TAGS) )
    279         values.remove(linearTag);
    280 
    281     if( values.containsKey("natural") && values.get("natural").equals("coastline") )
    282         values.remove("natural");
    283 
    284     String name = values.get("name");
    285     if( isBoundary ) {
    286         Set<String> keySet = new TreeSet<>(values.keySet());
    287         for( String key : keySet )
    288         if( !REMOVE_FROM_BOUNDARY_TAGS.contains(key) )
     281    private List<Command> removeTagsFromInnerWays(Relation relation) {
     282        Map<String, String> values = new HashMap<>();
     283
     284        if (relation.hasKeys()) {
     285            for (String key : relation.keySet()) {
     286                values.put(key, relation.get(key));
     287            }
     288        }
     289
     290        List<Way> innerWays = new ArrayList<>();
     291        List<Way> outerWays = new ArrayList<>();
     292
     293        Set<String> conflictingKeys = new TreeSet<>();
     294
     295        for (RelationMember m : relation.getMembers()) {
     296
     297            if (m.hasRole() && "inner".equals(m.getRole()) && m.isWay() && m.getWay().hasKeys()) {
     298                innerWays.add(m.getWay());
     299            }
     300
     301            if (m.hasRole() && "outer".equals(m.getRole()) && m.isWay() && m.getWay().hasKeys()) {
     302                Way way = m.getWay();
     303                outerWays.add(way);
     304                for (String key : way.keySet()) {
     305                    if (!values.containsKey(key)) { //relation values take precedence
     306                        values.put(key, way.get(key));
     307                    } else if (!relation.hasKey(key) && !values.get(key).equals(way.get(key))) {
     308                        conflictingKeys.add(key);
     309                    }
     310                }
     311            }
     312        }
     313
     314        // filter out empty key conflicts - we need second iteration
     315        boolean isBoundary = getPref("boundary");
     316        if (isBoundary || !getPref("alltags") ) {
     317            for (RelationMember m : relation.getMembers() )
     318                if (m.hasRole() && m.getRole().equals("outer") && m.isWay() ) {
     319                    for (String key : values.keySet() )
     320                        if (!m.getWay().hasKey(key) && !relation.hasKey(key) ) {
     321                            conflictingKeys.add(key);
     322                        }
     323                }
     324        }
     325
     326        for (String key : conflictingKeys ) {
    289327            values.remove(key);
    290     }
    291 
    292     values.put("area", "yes");
    293 
    294     List<Command> commands = new ArrayList<>();
    295     boolean moveTags = getPref("tags");
    296 
    297     for( String key : values.keySet() ) {
    298         List<OsmPrimitive> affectedWays = new ArrayList<>();
    299         String value = values.get(key);
    300 
    301         for( Way way : innerWays ) {
    302         if( way.hasKey(key) && (isBoundary || value.equals(way.get(key))) ) {
    303             affectedWays.add(way);
    304         }
    305         }
    306 
    307         if( moveTags ) {
    308         // remove duplicated tags from outer ways
    309         for( Way way : outerWays ) {
    310             if( way.hasKey(key) ) {
    311             affectedWays.add(way);
    312             }
    313         }
    314         }
    315 
    316         if( affectedWays.size() > 0 ) {
    317         commands.add(new ChangePropertyCommand(affectedWays, key, null));
    318         }
    319     }
    320 
    321     if( moveTags ) {
    322         // add those tag values to the relation
    323         if( isBoundary )
    324         values.put("name", name);
    325         boolean fixed = false;
    326         Relation r2 = new Relation(relation);
    327         for( String key : values.keySet() ) {
    328         if( !r2.hasKey(key) && !key.equals("area")
    329             && (!isBoundary || key.equals("admin_level") || key.equals("name")) ) {
    330             if( relation.isNew() )
    331             relation.put(key, values.get(key));
    332             else
    333             r2.put(key, values.get(key));
    334             fixed = true;
    335         }
    336         }
    337         if( fixed && !relation.isNew() )
    338         commands.add(new ChangeCommand(relation, r2));
    339     }
    340 
    341     return commands;
     328        }
     329
     330        for (String linearTag : Main.pref.getCollection(PREF_MULTIPOLY + "lineartags", DEFAULT_LINEAR_TAGS) ) {
     331            values.remove(linearTag);
     332        }
     333
     334        if (values.containsKey("natural") && values.get("natural").equals("coastline") ) {
     335            values.remove("natural");
     336        }
     337
     338        String name = values.get("name");
     339        if (isBoundary) {
     340            Set<String> keySet = new TreeSet<>(values.keySet());
     341            for (String key : keySet )
     342                if (!REMOVE_FROM_BOUNDARY_TAGS.contains(key) ) {
     343                    values.remove(key);
     344                }
     345        }
     346
     347        values.put("area", "yes");
     348
     349        List<Command> commands = new ArrayList<>();
     350        boolean moveTags = getPref("tags");
     351
     352        for (String key : values.keySet()) {
     353            List<OsmPrimitive> affectedWays = new ArrayList<>();
     354            String value = values.get(key);
     355
     356            for (Way way : innerWays) {
     357                if (way.hasKey(key) && (isBoundary || value.equals(way.get(key)))) {
     358                    affectedWays.add(way);
     359                }
     360            }
     361
     362            if (moveTags) {
     363                // remove duplicated tags from outer ways
     364                for (Way way : outerWays) {
     365                    if (way.hasKey(key)) {
     366                        affectedWays.add(way);
     367                    }
     368                }
     369            }
     370
     371            if (affectedWays.size() > 0) {
     372                commands.add(new ChangePropertyCommand(affectedWays, key, null));
     373            }
     374        }
     375
     376        if (moveTags) {
     377            // add those tag values to the relation
     378            if (isBoundary ) {
     379                values.put("name", name);
     380            }
     381            boolean fixed = false;
     382            Relation r2 = new Relation(relation);
     383            for (String key : values.keySet()) {
     384                if (!r2.hasKey(key) && !key.equals("area")
     385                        && (!isBoundary || key.equals("admin_level") || key.equals("name"))) {
     386                    if (relation.isNew() ) {
     387                        relation.put(key, values.get(key));
     388                    } else {
     389                        r2.put(key, values.get(key));
     390                    }
     391                    fixed = true;
     392                }
     393            }
     394            if (fixed && !relation.isNew() ) {
     395                commands.add(new ChangeCommand(relation, r2));
     396            }
     397        }
     398
     399        return commands;
    342400    }
    343401
     
    347405     * @return false if user pressed "cancel".
    348406     */
    349     private boolean askForAdminLevelAndName( Relation rel ) {
    350     String relAL = rel.get("admin_level");
    351     String relName = rel.get("name");
    352     if( relAL != null && relName != null )
     407    private boolean askForAdminLevelAndName(Relation rel) {
     408        String relAL = rel.get("admin_level");
     409        String relName = rel.get("name");
     410        if (relAL != null && relName != null )
     411            return true;
     412
     413        JPanel panel = new JPanel(new GridBagLayout());
     414        panel.add(new JLabel(tr("Enter admin level and name for the border relation:")), GBC.eol().insets(0, 0, 0, 5));
     415
     416        final JTextField admin = new JTextField();
     417        admin.setText(relAL != null ? relAL : Main.pref.get(PREF_MULTIPOLY + "lastadmin", ""));
     418        panel.add(new JLabel(tr("Admin level")), GBC.std());
     419        panel.add(Box.createHorizontalStrut(10), GBC.std());
     420        panel.add(admin, GBC.eol().fill(GBC.HORIZONTAL).insets(0, 0, 0, 5));
     421
     422        final JTextField name = new JTextField();
     423        if (relName != null ) {
     424            name.setText(relName);
     425        }
     426        panel.add(new JLabel(tr("Name")), GBC.std());
     427        panel.add(Box.createHorizontalStrut(10), GBC.std());
     428        panel.add(name, GBC.eol().fill(GBC.HORIZONTAL));
     429
     430        final JOptionPane optionPane = new JOptionPane(panel, JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION) {
     431            @Override
     432            public void selectInitialValue() {
     433                admin.requestFocusInWindow();
     434                admin.selectAll();
     435            }
     436        };
     437        final JDialog dlg = optionPane.createDialog(Main.parent, tr("Create a new relation"));
     438        dlg.setModalityType(ModalityType.DOCUMENT_MODAL);
     439
     440        name.addActionListener(new ActionListener() {
     441            @Override
     442            public void actionPerformed(ActionEvent e) {
     443                dlg.setVisible(false);
     444                optionPane.setValue(JOptionPane.OK_OPTION);
     445            }
     446        });
     447
     448        dlg.setVisible(true);
     449
     450        Object answer = optionPane.getValue();
     451        if (answer == null || answer == JOptionPane.UNINITIALIZED_VALUE
     452                || (answer instanceof Integer && (Integer)answer != JOptionPane.OK_OPTION))
     453            return false;
     454
     455        String admin_level = admin.getText().trim();
     456        String new_name = name.getText().trim();
     457        if (admin_level.equals("10") || (admin_level.length() == 1 && Character.isDigit(admin_level.charAt(0)))) {
     458            rel.put("admin_level", admin_level);
     459            Main.pref.put(PREF_MULTIPOLY + "lastadmin", admin_level);
     460        }
     461        if (new_name.length() > 0 ) {
     462            rel.put("name", new_name);
     463        }
    353464        return true;
    354 
    355     JPanel panel = new JPanel(new GridBagLayout());
    356     panel.add(new JLabel(tr("Enter admin level and name for the border relation:")), GBC.eol().insets(0, 0, 0, 5));
    357 
    358     final JTextField admin = new JTextField();
    359     admin.setText(relAL != null ? relAL : Main.pref.get(PREF_MULTIPOLY + "lastadmin", ""));
    360     panel.add(new JLabel(tr("Admin level")), GBC.std());
    361     panel.add(Box.createHorizontalStrut(10), GBC.std());
    362     panel.add(admin, GBC.eol().fill(GBC.HORIZONTAL).insets(0, 0, 0, 5));
    363 
    364     final JTextField name = new JTextField();
    365     if( relName != null )
    366         name.setText(relName);
    367     panel.add(new JLabel(tr("Name")), GBC.std());
    368     panel.add(Box.createHorizontalStrut(10), GBC.std());
    369     panel.add(name, GBC.eol().fill(GBC.HORIZONTAL));
    370 
    371     final JOptionPane optionPane = new JOptionPane(panel, JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION) {
    372         @Override
    373         public void selectInitialValue() {
    374         admin.requestFocusInWindow();
    375         admin.selectAll();
    376         }
    377     };
    378     final JDialog dlg = optionPane.createDialog(Main.parent, tr("Create a new relation"));
    379     dlg.setModalityType(ModalityType.DOCUMENT_MODAL);
    380 
    381     name.addActionListener(new ActionListener() {
    382         public void actionPerformed( ActionEvent e ) {
    383         dlg.setVisible(false);
    384         optionPane.setValue(JOptionPane.OK_OPTION);
    385         }
    386     });
    387 
    388     dlg.setVisible(true);
    389 
    390     Object answer = optionPane.getValue();
    391     if( answer == null || answer == JOptionPane.UNINITIALIZED_VALUE
    392         || (answer instanceof Integer && (Integer)answer != JOptionPane.OK_OPTION) ) {
    393         return false;
    394     }
    395 
    396     String admin_level = admin.getText().trim();
    397     String new_name = name.getText().trim();
    398     if( admin_level.equals("10") || (admin_level.length() == 1 && Character.isDigit(admin_level.charAt(0))) ) {
    399         rel.put("admin_level", admin_level);
    400         Main.pref.put(PREF_MULTIPOLY + "lastadmin", admin_level);
    401     }
    402     if( new_name.length() > 0 )
    403         rel.put("name", new_name);
    404     return true;
    405465    }
    406466}
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/CreateRelationAction.java

    r27927 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext.actions;
     3
     4import static org.openstreetmap.josm.tools.I18n.tr;
    25
    36import java.awt.Dialog.ModalityType;
    47import java.awt.GridBagLayout;
    5 import java.util.Collection;
    6 import org.openstreetmap.josm.data.osm.OsmPrimitive;
    7 import static org.openstreetmap.josm.tools.I18n.tr;
    88import java.awt.event.ActionEvent;
    99import java.awt.event.ActionListener;
    1010import java.awt.event.KeyEvent;
    1111import java.util.Arrays;
     12import java.util.Collection;
    1213import java.util.List;
     14
    1315import javax.swing.Box;
    1416import javax.swing.JDialog;
     
    1618import javax.swing.JOptionPane;
    1719import javax.swing.JPanel;
     20
    1821import org.openstreetmap.josm.Main;
    1922import org.openstreetmap.josm.actions.JosmAction;
    2023import org.openstreetmap.josm.command.AddCommand;
     24import org.openstreetmap.josm.data.osm.OsmPrimitive;
    2125import org.openstreetmap.josm.data.osm.Relation;
    2226import org.openstreetmap.josm.data.osm.RelationMember;
     
    2428import org.openstreetmap.josm.tools.GBC;
    2529import org.openstreetmap.josm.tools.Shortcut;
     30
    2631import relcontext.ChosenRelation;
    2732
     
    3641    protected ChosenRelation chRel;
    3742
    38     public CreateRelationAction( ChosenRelation chRel ) {
     43    public CreateRelationAction(ChosenRelation chRel) {
    3944        super(tr("New"), "data/relation", tr("Create a relation from selected objects"),
    4045                Shortcut.registerShortcut("reltoolbox:create", tr("Relation Toolbox: {0}", tr("Create a new relation")),
    41                 KeyEvent.VK_N, Shortcut.ALT_CTRL), false);
     46                        KeyEvent.VK_N, Shortcut.ALT_CTRL), false);
    4247        this.chRel = chRel;
    4348        updateEnabledState();
     
    4853    }
    4954
    50     public void actionPerformed( ActionEvent e ) {
     55    @Override
     56    public void actionPerformed(ActionEvent e) {
    5157        String type = askForType();
    52         if( type == null )
     58        if (type == null )
    5359            return;
    5460
    5561        Relation rel = new Relation();
    56         if( type.length() > 0 )
     62        if (type.length() > 0 ) {
    5763            rel.put("type", type);
    58         for( OsmPrimitive selected : getCurrentDataSet().getSelected() )
     64        }
     65        for (OsmPrimitive selected : getCurrentDataSet().getSelected() ) {
    5966            rel.addMember(new RelationMember("", selected));
     67        }
    6068
    6169        Main.main.undoRedo.add(new AddCommand(rel));
    6270
    63         if( chRel != null ) {
     71        if (chRel != null) {
    6472            chRel.set(rel);
    6573        }
     
    6876    @Override
    6977    protected void updateEnabledState() {
    70         if( getCurrentDataSet() == null ) {
     78        if (getCurrentDataSet() == null) {
    7179            setEnabled(false);
    7280        } else {
     
    7684
    7785    @Override
    78     protected void updateEnabledState( Collection<? extends OsmPrimitive> selection ) {
     86    protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) {
    7987        setEnabled(selection != null && !selection.isEmpty());
    8088    }
     
    8290    // Thanks to TagInfo for the list
    8391    private static final List<String> RELATION_TYPES = Arrays.asList(new String[] {
    84         "multipolygon", "boundary", "route", "site", "restriction", "associatedStreet", "public_transport",
    85         "street", "collection", "address", "enforcement", "destination_sign", "route_master", "junction",
    86         "waterway", "bridge", "tunnel", "surveillance"
     92            "multipolygon", "boundary", "route", "site", "restriction", "associatedStreet", "public_transport",
     93            "street", "collection", "address", "enforcement", "destination_sign", "route_master", "junction",
     94            "waterway", "bridge", "tunnel", "surveillance"
    8795    });
    8896
     
    111119
    112120        keys.getEditor().addActionListener(new ActionListener() {
    113             public void actionPerformed( ActionEvent e ) {
     121            @Override
     122            public void actionPerformed(ActionEvent e) {
    114123                dlg.setVisible(false);
    115124                optionPane.setValue(JOptionPane.OK_OPTION);
     
    120129
    121130        Object answer = optionPane.getValue();
    122         if( answer == null || answer == JOptionPane.UNINITIALIZED_VALUE
    123                 || (answer instanceof Integer && (Integer)answer != JOptionPane.OK_OPTION) ) {
     131        if (answer == null || answer == JOptionPane.UNINITIALIZED_VALUE
     132                || (answer instanceof Integer && (Integer)answer != JOptionPane.OK_OPTION))
    124133            return null;
    125         }
    126134
    127135        String result = keys.getEditor().getItem().toString().trim();
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/DeleteChosenRelationAction.java

    r28813 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext.actions;
    23
    34import static org.openstreetmap.josm.tools.I18n.tr;
     5
    46import java.awt.event.ActionEvent;
    57import java.util.Collections;
     8
    69import javax.swing.AbstractAction;
     10
    711import org.openstreetmap.josm.Main;
    812import org.openstreetmap.josm.command.Command;
     
    1014import org.openstreetmap.josm.data.osm.Relation;
    1115import org.openstreetmap.josm.tools.ImageProvider;
     16
    1217import relcontext.ChosenRelation;
    1318import relcontext.ChosenRelationListener;
     
    1621    private ChosenRelation rel;
    1722
    18     public DeleteChosenRelationAction( ChosenRelation rel ) {
     23    public DeleteChosenRelationAction(ChosenRelation rel) {
    1924        super(tr("Delete relation"));
    2025        putValue(SMALL_ICON, ImageProvider.get("dialogs", "delete"));
     
    2429    }
    2530
    26     public void actionPerformed( ActionEvent e ) {
     31    @Override
     32    public void actionPerformed(ActionEvent e) {
    2733        Relation r = rel.get();
    2834        rel.clear();
    2935        Command c = DeleteCommand.delete(Main.main.getEditLayer(), Collections.singleton(r), true, true);
    30         if( c != null )
     36        if (c != null ) {
    3137            Main.main.undoRedo.add(c);
     38        }
    3239    }
    3340
    34     public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) {
     41    @Override
     42    public void chosenRelationChanged(Relation oldRelation, Relation newRelation) {
    3543        setEnabled(newRelation != null);
    3644    }
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/DownloadChosenRelationAction.java

    r30737 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext.actions;
    23
    34import static org.openstreetmap.josm.tools.I18n.tr;
     5
    46import java.awt.event.ActionEvent;
    57import java.util.Collections;
    68import java.util.HashSet;
    79import java.util.Set;
     10
    811import javax.swing.AbstractAction;
     12
    913import org.openstreetmap.josm.Main;
    1014import org.openstreetmap.josm.data.osm.OsmPrimitive;
     
    1418import org.openstreetmap.josm.gui.dialogs.relation.DownloadRelationTask;
    1519import org.openstreetmap.josm.tools.ImageProvider;
     20
    1621import relcontext.ChosenRelation;
    1722import relcontext.ChosenRelationListener;
     
    1924/**
    2025 * Downloads or updates chosen relation members, depending on completeness.
    21  * 
     26 *
    2227 * @author Zverik
    2328 */
     
    2530    private ChosenRelation rel;
    2631
    27     public DownloadChosenRelationAction( ChosenRelation rel ) {
     32    public DownloadChosenRelationAction(ChosenRelation rel) {
    2833        super();
    29 //        putValue(NAME, "D");
     34        //        putValue(NAME, "D");
    3035        putValue(SMALL_ICON, ImageProvider.get("relcontext", "download"));
    3136        putValue(SHORT_DESCRIPTION, tr("Download incomplete members for the chosen relation"));
     
    3540    }
    3641
    37     public void actionPerformed( ActionEvent e ) {
     42    @Override
     43    public void actionPerformed(ActionEvent e) {
    3844        Relation relation = rel.get();
    39         if( relation == null || relation.isNew() ) return;
     45        if (relation == null || relation.isNew() ) return;
    4046        int total = relation.getMembersCount();
    4147        int incomplete = relation.getIncompleteMembers().size();
    42 //        if( incomplete <= 5 || (incomplete <= 10 && incomplete * 3 < total) )
    43         if( incomplete <= 10 && incomplete * 3 < total )
     48        //        if (incomplete <= 5 || (incomplete <= 10 && incomplete * 3 < total) )
     49        if (incomplete <= 10 && incomplete * 3 < total ) {
    4450            downloadIncomplete(relation);
    45         else
     51        } else {
    4652            downloadMembers(relation);
     53        }
    4754    }
    4855
    49     public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) {
     56    @Override
     57    public void chosenRelationChanged(Relation oldRelation, Relation newRelation) {
    5058        boolean incomplete = false;
    51         if( newRelation != null ) {
    52             for( RelationMember m : newRelation.getMembers()) {
    53                 if( m.getMember().isIncomplete() ) {
     59        if (newRelation != null) {
     60            for (RelationMember m : newRelation.getMembers()) {
     61                if (m.getMember().isIncomplete()) {
    5462                    incomplete = true;
    5563                    break;
     
    6068    }
    6169
    62     protected void downloadMembers( Relation rel ) {
    63         if( !rel.isNew() ) {
     70    protected void downloadMembers(Relation rel) {
     71        if (!rel.isNew()) {
    6472            Main.worker.submit(new DownloadRelationTask(Collections.singletonList(rel), Main.main.getEditLayer()));
    6573        }
    6674    }
    6775
    68     protected void downloadIncomplete( Relation rel ) {
    69         if( rel.isNew() ) return;
     76    protected void downloadIncomplete(Relation rel) {
     77        if (rel.isNew() ) return;
    7078        Set<OsmPrimitive> ret = new HashSet<>();
    7179        ret.addAll(rel.getIncompleteMembers());
    72         if( ret.isEmpty() ) return;
     80        if (ret.isEmpty() ) return;
    7381        Main.worker.submit(new DownloadRelationMemberTask(Collections.singletonList(rel), ret, Main.main.getEditLayer()));
    7482    }
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/DownloadParentsAction.java

    r30737 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext.actions;
    23
     
    2526/**
    2627 * Downloads parent relations for this relation and all parent objects for its members.
    27  * 
     28 *
    2829 * @author Zverik
    2930 */
     
    3132    private ChosenRelation rel;
    3233
    33     public DownloadParentsAction( ChosenRelation rel ) {
     34    public DownloadParentsAction(ChosenRelation rel) {
    3435        super(tr("Download referrers"));
    3536        putValue(SMALL_ICON, ImageProvider.get("download"));
     
    4041    }
    4142
    42     public void actionPerformed( ActionEvent e ) {
     43    @Override
     44    public void actionPerformed(ActionEvent e) {
    4345        Relation relation = rel.get();
    44         if( relation == null ) return;
     46        if (relation == null ) return;
    4547        List<OsmPrimitive> objects = new ArrayList<>();
    4648        objects.add(relation);
     
    4951    }
    5052
    51     public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) {
     53    @Override
     54    public void chosenRelationChanged(Relation oldRelation, Relation newRelation) {
    5255        setEnabled(newRelation != null && Main.main.getEditLayer() != null);
    5356    }
    5457
    55     protected void downloadMembers( Relation rel ) {
    56         if( !rel.isNew() ) {
     58    protected void downloadMembers(Relation rel) {
     59        if (!rel.isNew()) {
    5760            Main.worker.submit(new DownloadRelationTask(Collections.singletonList(rel), Main.main.getEditLayer()));
    5861        }
    5962    }
    6063
    61     protected void downloadIncomplete( Relation rel ) {
    62         if( rel.isNew() ) return;
     64    protected void downloadIncomplete(Relation rel) {
     65        if (rel.isNew() ) return;
    6366        Set<OsmPrimitive> ret = new HashSet<>();
    6467        ret.addAll(rel.getIncompleteMembers());
    65         if( ret.isEmpty() ) return;
     68        if (ret.isEmpty() ) return;
    6669        Main.worker.submit(new DownloadRelationMemberTask(Collections.singletonList(rel), ret, Main.main.getEditLayer()));
    6770    }
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/DuplicateChosenRelationAction.java

    r26290 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext.actions;
    23
    34import static org.openstreetmap.josm.tools.I18n.tr;
     5
    46import java.awt.event.ActionEvent;
     7
    58import javax.swing.AbstractAction;
     9
    610import org.openstreetmap.josm.Main;
    711import org.openstreetmap.josm.command.AddCommand;
    812import org.openstreetmap.josm.data.osm.Relation;
    913import org.openstreetmap.josm.tools.ImageProvider;
     14
    1015import relcontext.ChosenRelation;
    1116import relcontext.ChosenRelationListener;
     
    1419    private ChosenRelation rel;
    1520
    16     public DuplicateChosenRelationAction( ChosenRelation rel ) {
     21    public DuplicateChosenRelationAction(ChosenRelation rel) {
    1722        super(tr("Duplicate relation"));
    1823        putValue(SMALL_ICON, ImageProvider.get("duplicate"));
     
    2328    }
    2429
    25     public void actionPerformed( ActionEvent e ) {
     30    @Override
     31    public void actionPerformed(ActionEvent e) {
    2632        Relation r = rel.get();
    2733        Relation copy = new Relation(r, true);
    2834        Main.main.undoRedo.add(new AddCommand(copy));
    2935        rel.set(copy);
    30         if( Main.main.getCurrentDataSet() != null )
     36        if (Main.main.getCurrentDataSet() != null ) {
    3137            Main.main.getCurrentDataSet().setSelected(copy);
     38        }
    3239    }
    3340
    34     public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) {
     41    @Override
     42    public void chosenRelationChanged(Relation oldRelation, Relation newRelation) {
    3543        setEnabled(newRelation != null);
    3644    }
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/EditChosenRelationAction.java

    r30145 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext.actions;
    23
    34import static org.openstreetmap.josm.tools.I18n.tr;
     5
    46import java.awt.event.ActionEvent;
     7
    58import javax.swing.AbstractAction;
     9
    610import org.openstreetmap.josm.Main;
    711import org.openstreetmap.josm.data.osm.Relation;
    812import org.openstreetmap.josm.gui.dialogs.relation.RelationEditor;
    913import org.openstreetmap.josm.tools.ImageProvider;
     14
    1015import relcontext.ChosenRelation;
    1116import relcontext.ChosenRelationListener;
     
    1318/**
    1419 * Opens an editor for chosen relation.
    15  * 
     20 *
    1621 * @author Zverik
    1722 */
     
    1924    private ChosenRelation rel;
    2025
    21     public EditChosenRelationAction( ChosenRelation rel ) {
     26    public EditChosenRelationAction(ChosenRelation rel) {
    2227        super();
    23 //        putValue(NAME, "E");
     28        //        putValue(NAME, "E");
    2429        putValue(SMALL_ICON, ImageProvider.get("dialogs/mappaint", "pencil"));
    2530        putValue(SHORT_DESCRIPTION, tr("Open relation editor for the chosen relation"));
     
    2934    }
    3035
    31     public void actionPerformed( ActionEvent e ) {
     36    @Override
     37    public void actionPerformed(ActionEvent e) {
    3238        Relation relation = rel.get();
    33         if( relation == null ) return;
     39        if (relation == null ) return;
    3440        RelationEditor.getEditor(Main.main.getEditLayer(), relation, null).setVisible(true);
    3541    }
    3642
    37     public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) {
     43    @Override
     44    public void chosenRelationChanged(Relation oldRelation, Relation newRelation) {
    3845        setEnabled(newRelation != null);
    3946    }
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/FindRelationAction.java

    r30737 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext.actions;
     3
     4import static org.openstreetmap.josm.tools.I18n.tr;
    25
    36import java.awt.BorderLayout;
    47import java.awt.Dialog.ModalityType;
    58import java.awt.Dimension;
    6 import java.awt.event.*;
    7 import static org.openstreetmap.josm.tools.I18n.tr;
    8 import java.util.*;
     9import java.awt.event.ActionEvent;
     10import java.awt.event.ActionListener;
     11import java.awt.event.KeyAdapter;
     12import java.awt.event.KeyEvent;
     13import java.awt.event.MouseAdapter;
     14import java.awt.event.MouseEvent;
    915import java.util.ArrayList;
    10 import javax.swing.*;
     16import java.util.Collection;
     17import java.util.Collections;
     18import java.util.List;
     19
     20import javax.swing.AbstractListModel;
     21import javax.swing.DefaultListSelectionModel;
     22import javax.swing.JDialog;
     23import javax.swing.JList;
     24import javax.swing.JOptionPane;
     25import javax.swing.JPanel;
     26import javax.swing.JScrollPane;
     27import javax.swing.JTextField;
     28import javax.swing.ListSelectionModel;
     29import javax.swing.SwingUtilities;
     30
    1131import org.openstreetmap.josm.Main;
    1232import org.openstreetmap.josm.actions.JosmAction;
     
    1535import org.openstreetmap.josm.gui.OsmPrimitivRenderer;
    1636import org.openstreetmap.josm.tools.Shortcut;
     37
    1738import relcontext.ChosenRelation;
    1839
     
    2546    protected ChosenRelation chRel;
    2647
    27     public FindRelationAction( ChosenRelation chRel ) {
     48    public FindRelationAction(ChosenRelation chRel) {
    2849        super(tr("Find"), "relcontext/find", tr("Find a relation"),
    2950                Shortcut.registerShortcut("reltoolbox:find", tr("Relation Toolbox: {0}", tr("Find a relation")),
    30                 KeyEvent.VK_F, Shortcut.ALT_CTRL), false);
     51                        KeyEvent.VK_F, Shortcut.ALT_CTRL), false);
    3152        this.chRel = chRel;
    3253    }
    3354
    34     public void actionPerformed( ActionEvent e ) {
     55    @Override
     56    public void actionPerformed(ActionEvent e) {
    3557        JPanel panel = new JPanel(new BorderLayout());
    3658        final JTextField searchField = new JTextField();
     
    5577        relationsList.addMouseListener(new MouseAdapter() {
    5678            @Override
    57             public void mouseClicked( MouseEvent e ) {
    58                 if( e.getClickCount() >= 2 && !relationsList.isSelectionEmpty() ) {
     79            public void mouseClicked(MouseEvent e) {
     80                if (e.getClickCount() >= 2 && !relationsList.isSelectionEmpty()) {
    5981                    dlg.setVisible(false);
    6082                    optionPane.setValue(JOptionPane.OK_OPTION);
     
    6486
    6587        searchField.addActionListener(new ActionListener() {
    66             public void actionPerformed( ActionEvent e ) {
    67                 if( !relationsList.isSelectionEmpty() ) {
     88            @Override
     89            public void actionPerformed(ActionEvent e) {
     90                if (!relationsList.isSelectionEmpty()) {
    6891                    dlg.setVisible(false);
    6992                    optionPane.setValue(JOptionPane.OK_OPTION);
     
    7497        searchField.addKeyListener(new KeyAdapter() {
    7598            @Override
    76             public void keyTyped( KeyEvent e ) {
     99            public void keyTyped(KeyEvent e) {
    77100                SwingUtilities.invokeLater(new Runnable() {
     101                    @Override
    78102                    public void run() {
    79103                        updateRelationData(relationsData, searchField.getText());
     
    83107
    84108            @Override
    85             public void keyPressed( KeyEvent e ) {
    86                 if( shouldForward(e) )
     109            public void keyPressed(KeyEvent e) {
     110                if (shouldForward(e) ) {
    87111                    relationsList.dispatchEvent(e);
    88             }
    89 
    90             @Override
    91             public void keyReleased( KeyEvent e ) {
    92                 if( shouldForward(e) )
     112                }
     113            }
     114
     115            @Override
     116            public void keyReleased(KeyEvent e) {
     117                if (shouldForward(e) ) {
    93118                    relationsList.dispatchEvent(e);
    94             }
    95 
    96             private boolean shouldForward( KeyEvent e ) {
     119                }
     120            }
     121
     122            private boolean shouldForward(KeyEvent e) {
    97123                return e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() == KeyEvent.VK_DOWN
    98124                        || e.getKeyCode() == KeyEvent.VK_PAGE_DOWN || e.getKeyCode() == KeyEvent.VK_PAGE_UP
     
    105131
    106132        Object answer = optionPane.getValue();
    107         if( answer == null || answer == JOptionPane.UNINITIALIZED_VALUE
    108                 || (answer instanceof Integer && (Integer)answer != JOptionPane.OK_OPTION) ) {
     133        if (answer == null || answer == JOptionPane.UNINITIALIZED_VALUE
     134                || (answer instanceof Integer && (Integer)answer != JOptionPane.OK_OPTION))
    109135            return;
    110         }
    111 
    112         Relation r = (Relation)relationsList.getSelectedValue();
    113         if( r != null )
     136
     137        Relation r = relationsList.getSelectedValue();
     138        if (r != null ) {
    114139            chRel.set(r);
     140        }
    115141    }
    116142
     
    120146    }
    121147
    122     protected void updateRelationData( FindRelationListModel data, String filter ) {
     148    protected void updateRelationData(FindRelationListModel data, String filter) {
    123149        String[] keywords = filter == null ? new String[0] : filter.split("\\s+");
    124         if( keywords.length > 0 ) {
     150        if (keywords.length > 0) {
    125151            List<String> filteredKeywords = new ArrayList<>(keywords.length);
    126             for( String s : keywords )
    127                 if( s.length() > 0 )
     152            for (String s : keywords )
     153                if (s.length() > 0 ) {
    128154                    filteredKeywords.add(s.trim().toLowerCase());
     155                }
    129156            keywords = filteredKeywords.toArray(new String[0]);
    130157        }
    131158
    132159        System.out.println("keywords.length = " + keywords.length);
    133         for( int i = 0; i < keywords.length; i++ )
     160        for (int i = 0; i < keywords.length; i++ ) {
    134161            System.out.println("keyword["+i+"] = " + keywords[i]);
     162        }
    135163
    136164        List<Relation> relations = new ArrayList<>();
    137         if( getEditLayer() != null ) {
    138             for( Relation r : getEditLayer().data.getRelations() ) {
    139                 if( !r.isDeleted() && r.isVisible() && !r.isIncomplete() ) {
     165        if (getEditLayer() != null) {
     166            for (Relation r : getEditLayer().data.getRelations()) {
     167                if (!r.isDeleted() && r.isVisible() && !r.isIncomplete()) {
    140168                    boolean add = true;
    141                     for( int i = 0; i < keywords.length && add; i++ ) {
     169                    for (int i = 0; i < keywords.length && add; i++) {
    142170                        boolean ok = false;
    143                         if( String.valueOf(r.getPrimitiveId().getUniqueId()).contains(keywords[i]) )
     171                        if (String.valueOf(r.getPrimitiveId().getUniqueId()).contains(keywords[i]) ) {
    144172                            ok = true;
    145                         else {
    146                             for( String key : r.keySet() ) {
    147                                 if( key.contains(keywords[i]) || r.get(key).toLowerCase().contains(keywords[i])
    148                                         || tr(r.get(key)).toLowerCase().contains(keywords[i]) ) {
     173                        } else {
     174                            for (String key : r.keySet()) {
     175                                if (key.contains(keywords[i]) || r.get(key).toLowerCase().contains(keywords[i])
     176                                        || tr(r.get(key)).toLowerCase().contains(keywords[i])) {
    149177                                    ok = true;
    150178                                    break;
     
    152180                            }
    153181                        }
    154                         if( !ok ) add = false;
     182                        if (!ok ) {
     183                            add = false;
     184                        }
    155185                    }
    156                     if( add )
     186                    if (add ) {
    157187                        relations.add(r);
     188                    }
    158189                }
    159190            }
     
    171202        private DefaultListSelectionModel selectionModel;
    172203
    173         public FindRelationListModel( DefaultListSelectionModel selectionModel ) {
     204        public FindRelationListModel(DefaultListSelectionModel selectionModel) {
    174205            super();
    175206            this.selectionModel = selectionModel;
     
    190221
    191222        @Override
    192         public Relation getElementAt( int index ) {
     223        public Relation getElementAt(int index) {
    193224            return relations.get(index);
    194225        }
     
    197228            int selectedIndex = selectionModel.getMinSelectionIndex();
    198229            Relation sel =  selectedIndex < 0 ? null : getElementAt(selectedIndex);
    199            
     230
    200231            this.relations.clear();
    201232            selectionModel.clearSelection();
    202             if( relations != null )
     233            if (relations != null ) {
    203234                this.relations.addAll(relations);
     235            }
    204236            fireIntervalAdded(this, 0, getSize());
    205237
    206             if( sel != null ) {
     238            if (sel != null) {
    207239                selectedIndex = this.relations.indexOf(sel);
    208                 if( selectedIndex >= 0 )
     240                if (selectedIndex >= 0 ) {
    209241                    selectionModel.addSelectionInterval(selectedIndex, selectedIndex);
    210             }
    211             if( selectionModel.isSelectionEmpty() && !this.relations.isEmpty() )
     242                }
     243            }
     244            if (selectionModel.isSelectionEmpty() && !this.relations.isEmpty() ) {
    212245                selectionModel.addSelectionInterval(0, 0);
     246            }
    213247        }
    214248    }
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/PublicTransportHelper.java

    r30841 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext.actions;
    23
    3 import org.openstreetmap.josm.data.osm.Node;
    44import org.openstreetmap.josm.data.osm.OsmPrimitive;
    55import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
    66import org.openstreetmap.josm.data.osm.RelationMember;
    7 import org.openstreetmap.josm.data.osm.Way;
    87
    98/**
     
    2625    public final static String BUS_STOP = "bus_stop";
    2726    public final static String RAILWAY_HALT = "halt";
    28     public final static String RAILWAY_STATION = "station";   
    29    
     27    public final static String RAILWAY_STATION = "station";
     28
    3029    private PublicTransportHelper() {
    3130        // Hide default constructor for utils classes
    32     }       
    33    
     31    }
     32
    3433    public static String getRoleByMember(RelationMember m) {
    3534        if (isMemberStop(m)) return STOP;
     
    3736        return null;
    3837    }
    39    
     38
    4039    public static boolean isMemberStop(RelationMember m) {
    4140        return isNodeStop(m);   // stop is only node
    4241    }
    43    
     42
    4443    public static boolean isMemberPlatform(RelationMember m) {
    4544        return isNodePlatform(m) || isWayPlatform(m);
    4645    }
    47    
     46
    4847    public static boolean isNodeStop(RelationMember m) {
    4948        return isNodeStop(m.getMember());
    5049    }
    51    
     50
    5251    public static boolean isNodeStop(OsmPrimitive p) {
    5352        if (p.getType() == OsmPrimitiveType.NODE && !p.isIncomplete()) {
     
    6362        return false;
    6463    }
    65    
     64
    6665    public static boolean isNodePlatform(RelationMember m) {
    6766        return isNodePlatform(m.getMember());
    6867    }
    69    
     68
    7069    public static boolean isNodePlatform(OsmPrimitive p) {
    7170        if (p.getType() == OsmPrimitiveType.NODE && !p.isIncomplete()) {
     
    8786        return isWayPlatform(m.getMember());
    8887    }
    89    
     88
    9089    public static boolean isWayPlatform(OsmPrimitive p) {
    9190        if (p.getType() == OsmPrimitiveType.WAY && !p.isIncomplete()) {
     
    103102        return false;
    104103    }
    105    
     104
    106105    public static boolean isMemberRouteway(RelationMember m) {
    107106        return isWayRouteway(m.getMember());
    108107    }
    109    
     108
    110109    public static boolean isWayRouteway(OsmPrimitive p) {
    111         if (p.getType() == OsmPrimitiveType.WAY && !p.isIncomplete()) {
     110        if (p.getType() == OsmPrimitiveType.WAY && !p.isIncomplete())
    112111            return p.hasKey(HIGHWAY) || p.hasKey(RAILWAY);
    113         }
    114112        return false;
    115113    }
    116    
     114
    117115    public static String getNameViaStoparea(RelationMember m) {
    118116        return getNameViaStoparea(m.getMember());
    119117    }
    120    
     118
    121119    public static String getNameViaStoparea(OsmPrimitive prim) {
    122120        String result = prim.getName();
     
    125123        for (OsmPrimitive refOp : prim.getReferrers())
    126124            if (refOp.getType() == OsmPrimitiveType.RELATION
    127                 && refOp.hasTag(PUBLIC_TRANSPORT, STOP_AREA)) {
     125            && refOp.hasTag(PUBLIC_TRANSPORT, STOP_AREA)) {
    128126                result = refOp.getName();
    129127                if (result != null) return result;
    130128            }
    131129        return result;
    132     }   
     130    }
    133131}
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/ReconstructPolygonAction.java

    r30738 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext.actions;
    23
     
    4041public class ReconstructPolygonAction extends AbstractAction implements ChosenRelationListener {
    4142    private ChosenRelation rel;
    42    
     43
    4344    private static final List<String> IRRELEVANT_KEYS = Arrays.asList(new String[] {
    44     "source", "created_by", "note"});
     45            "source", "created_by", "note"});
    4546
    46     public ReconstructPolygonAction( ChosenRelation rel ) {
     47    public ReconstructPolygonAction(ChosenRelation rel) {
    4748        super(tr("Reconstruct polygon"));
    4849        putValue(SMALL_ICON, ImageProvider.get("dialogs", "filter"));
    49     putValue(LONG_DESCRIPTION, "Reconstruct polygon from multipolygon relation");
     50        putValue(LONG_DESCRIPTION, "Reconstruct polygon from multipolygon relation");
    5051        this.rel = rel;
    5152        rel.addChosenRelationListener(this);
     
    5354    }
    5455
    55     public void actionPerformed( ActionEvent e ) {
     56    @Override
     57    public void actionPerformed(ActionEvent e) {
    5658        Relation r = rel.get();
    57     List<Way> ways = new ArrayList<>();
    58     boolean wont = false;
    59     for( RelationMember m : r.getMembers() ) {
    60         if( m.isWay() )
    61         ways.add(m.getWay());
    62         else
    63         wont = true;
    64     }
    65     if( wont ) {
    66         JOptionPane.showMessageDialog(Main.parent, tr("Multipolygon must consist only of ways"), tr("Reconstruct polygon"), JOptionPane.ERROR_MESSAGE);
    67         return;
    68     }
    69    
    70     MultipolygonBuilder mpc = new MultipolygonBuilder();
    71     String error = mpc.makeFromWays(ways);
    72     if( error != null ) {
    73         JOptionPane.showMessageDialog(Main.parent, error);
    74         return;
    75     }
    76    
    77     if( !mpc.innerWays.isEmpty() ) {
    78         JOptionPane.showMessageDialog(Main.parent, tr("Reconstruction of polygons can be done only from outer ways"), tr("Reconstruct polygon"), JOptionPane.ERROR_MESSAGE);
    79         return;
    80     }
    81    
    82     rel.clear();
    83     List<Way> newSelection = new ArrayList<>();
    84     List<Command> commands = new ArrayList<>();
    85         Command c = DeleteCommand.delete(Main.main.getEditLayer(), Collections.singleton(r), true, true);
    86         if( c == null )
    87             return;
    88     commands.add(c);
    89    
    90     for( JoinedPolygon p : mpc.outerWays ) {
    91         // move all tags from relation and common tags from ways
    92         Map<String, String> tags = p.ways.get(0).getKeys();
    93         List<OsmPrimitive> relations = p.ways.get(0).getReferrers();
    94         Set<String> noTags = new HashSet<>(r.keySet());
    95         for( int i = 1; i < p.ways.size(); i++ ) {
    96         Way w = p.ways.get(i);
    97         for( String key : w.keySet() ) {
    98             String value = w.get(key);
    99             if( !noTags.contains(key) && tags.containsKey(key) && !tags.get(key).equals(value) ) {
    100             tags.remove(key);
    101             noTags.add(key);
     59        List<Way> ways = new ArrayList<>();
     60        boolean wont = false;
     61        for (RelationMember m : r.getMembers()) {
     62            if (m.isWay() ) {
     63                ways.add(m.getWay());
     64            } else {
     65                wont = true;
    10266            }
    10367        }
    104         List<OsmPrimitive> referrers = w.getReferrers();
    105         for( Iterator<OsmPrimitive> ref1 = relations.iterator(); ref1.hasNext(); )
    106             if( !referrers.contains(ref1.next()) )
    107             ref1.remove();
     68        if (wont) {
     69            JOptionPane.showMessageDialog(Main.parent, tr("Multipolygon must consist only of ways"), tr("Reconstruct polygon"), JOptionPane.ERROR_MESSAGE);
     70            return;
    10871        }
    109         tags.putAll(r.getKeys());
    110         tags.remove("type");
    111        
    112         // then delete ways that are not relevant (do not take part in other relations of have strange tags)
    113         Way candidateWay = null;
    114         for( Way w : p.ways ) {
    115         if( w.getReferrers().equals(relations) ) {
    116             // check tags that remain
    117             Set<String> keys = new HashSet<>(w.keySet());
    118             keys.removeAll(tags.keySet());
    119             keys.removeAll(IRRELEVANT_KEYS);
    120             if( keys.isEmpty() ) {
    121             if( candidateWay == null )
    122                 candidateWay = w;
    123             else {
    124                 if( candidateWay.isNew() && !w.isNew() ) {
    125                 // prefer ways that are already in the database
    126                 Way tmp = w;
    127                 w = candidateWay;
    128                 candidateWay = tmp;
     72
     73        MultipolygonBuilder mpc = new MultipolygonBuilder();
     74        String error = mpc.makeFromWays(ways);
     75        if (error != null) {
     76            JOptionPane.showMessageDialog(Main.parent, error);
     77            return;
     78        }
     79
     80        if (!mpc.innerWays.isEmpty()) {
     81            JOptionPane.showMessageDialog(Main.parent, tr("Reconstruction of polygons can be done only from outer ways"), tr("Reconstruct polygon"), JOptionPane.ERROR_MESSAGE);
     82            return;
     83        }
     84
     85        rel.clear();
     86        List<Way> newSelection = new ArrayList<>();
     87        List<Command> commands = new ArrayList<>();
     88        Command c = DeleteCommand.delete(Main.main.getEditLayer(), Collections.singleton(r), true, true);
     89        if (c == null )
     90            return;
     91        commands.add(c);
     92
     93        for (JoinedPolygon p : mpc.outerWays) {
     94            // move all tags from relation and common tags from ways
     95            Map<String, String> tags = p.ways.get(0).getKeys();
     96            List<OsmPrimitive> relations = p.ways.get(0).getReferrers();
     97            Set<String> noTags = new HashSet<>(r.keySet());
     98            for (int i = 1; i < p.ways.size(); i++) {
     99                Way w = p.ways.get(i);
     100                for (String key : w.keySet()) {
     101                    String value = w.get(key);
     102                    if (!noTags.contains(key) && tags.containsKey(key) && !tags.get(key).equals(value)) {
     103                        tags.remove(key);
     104                        noTags.add(key);
     105                    }
    129106                }
    130                 commands.add(new DeleteCommand(w));
     107                List<OsmPrimitive> referrers = w.getReferrers();
     108                for (Iterator<OsmPrimitive> ref1 = relations.iterator(); ref1.hasNext(); )
     109                    if (!referrers.contains(ref1.next()) ) {
     110                        ref1.remove();
     111                    }
    131112            }
     113            tags.putAll(r.getKeys());
     114            tags.remove("type");
     115
     116            // then delete ways that are not relevant (do not take part in other relations of have strange tags)
     117            Way candidateWay = null;
     118            for (Way w : p.ways) {
     119                if (w.getReferrers().equals(relations)) {
     120                    // check tags that remain
     121                    Set<String> keys = new HashSet<>(w.keySet());
     122                    keys.removeAll(tags.keySet());
     123                    keys.removeAll(IRRELEVANT_KEYS);
     124                    if (keys.isEmpty()) {
     125                        if (candidateWay == null ) {
     126                            candidateWay = w;
     127                        } else {
     128                            if (candidateWay.isNew() && !w.isNew()) {
     129                                // prefer ways that are already in the database
     130                                Way tmp = w;
     131                                w = candidateWay;
     132                                candidateWay = tmp;
     133                            }
     134                            commands.add(new DeleteCommand(w));
     135                        }
     136                    }
     137                }
    132138            }
     139
     140            // take the first way, put all nodes into it, making it a closed polygon
     141            Way result = candidateWay == null ? new Way() : new Way(candidateWay);
     142            result.setNodes(p.nodes);
     143            result.addNode(result.firstNode());
     144            result.setKeys(tags);
     145            newSelection.add(candidateWay == null ? result : candidateWay);
     146            commands.add(candidateWay == null ? new AddCommand(result) : new ChangeCommand(candidateWay, result));
    133147        }
    134         }
    135        
    136         // take the first way, put all nodes into it, making it a closed polygon
    137         Way result = candidateWay == null ? new Way() : new Way(candidateWay);
    138         result.setNodes(p.nodes);
    139         result.addNode(result.firstNode());
    140         result.setKeys(tags);
    141         newSelection.add(candidateWay == null ? result : candidateWay);
    142         commands.add(candidateWay == null ? new AddCommand(result) : new ChangeCommand(candidateWay, result));
    143     }
    144    
     148
    145149        Main.main.undoRedo.add(new SequenceCommand(tr("Reconstruct polygons from relation {0}",
    146         r.getDisplayName(DefaultNameFormatter.getInstance())), commands));
    147     Main.main.getCurrentDataSet().setSelected(newSelection);
     150                r.getDisplayName(DefaultNameFormatter.getInstance())), commands));
     151        Main.main.getCurrentDataSet().setSelected(newSelection);
    148152    }
    149153
    150     public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) {
    151     setEnabled(isSuitableRelation(newRelation));
     154    @Override
     155    public void chosenRelationChanged(Relation oldRelation, Relation newRelation) {
     156        setEnabled(isSuitableRelation(newRelation));
    152157    }
    153    
    154     private boolean isSuitableRelation( Relation newRelation ) {
    155     if( newRelation == null || !"multipolygon".equals(newRelation.get("type")) || newRelation.getMembersCount() == 0 )
    156         return false;
    157     else {
    158         for( RelationMember m : newRelation.getMembers() )
    159         if( "inner".equals(m.getRole()) )
     158
     159    private boolean isSuitableRelation(Relation newRelation) {
     160        if (newRelation == null || !"multipolygon".equals(newRelation.get("type")) || newRelation.getMembersCount() == 0 )
    160161            return false;
    161         return true;
    162     }
     162        else {
     163            for (RelationMember m : newRelation.getMembers() )
     164                if ("inner".equals(m.getRole()) )
     165                    return false;
     166            return true;
     167        }
    163168    }
    164169}
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/ReconstructRouteAction.java

    r30841 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext.actions;
     3
     4import static org.openstreetmap.josm.tools.I18n.tr;
    25
    36import java.awt.event.ActionEvent;
     
    69import java.util.List;
    710import java.util.Map;
     11
    812import javax.swing.AbstractAction;
    9 import static javax.swing.Action.LONG_DESCRIPTION;
    10 import static javax.swing.Action.SMALL_ICON;
     13
    1114import org.openstreetmap.josm.Main;
    1215import org.openstreetmap.josm.command.ChangeCommand;
     
    2124import org.openstreetmap.josm.gui.dialogs.relation.sort.RelationSorter;
    2225import org.openstreetmap.josm.tools.Geometry;
    23 import static org.openstreetmap.josm.tools.I18n.tr;
    2426import org.openstreetmap.josm.tools.ImageProvider;
     27
    2528import relcontext.ChosenRelation;
    2629import relcontext.ChosenRelationListener;
     
    3235public class ReconstructRouteAction  extends AbstractAction implements ChosenRelationListener {
    3336    private final ChosenRelation rel;
    34    
     37
    3538    public ReconstructRouteAction (ChosenRelation rel) {
    3639        super(tr("Reconstruct route"));
     
    4144        setEnabled(isSuitableRelation(rel.get()));
    4245    }
    43    
    44     public void actionPerformed( ActionEvent e ) {
     46
     47    @Override
     48    public void actionPerformed(ActionEvent e) {
    4549        Relation r = rel.get();
    46         Relation recRel = new Relation(r);       
     50        Relation recRel = new Relation(r);
    4751        recRel.removeMembersFor(recRel.getMemberPrimitives());
    48        
     52
    4953        Map<OsmPrimitive, RelationMember> stopMembers = new LinkedHashMap<>();
    5054        Map<String, List<RelationMember>> platformMembers = new LinkedHashMap<>();
     
    5256        List<RelationMember> routeMembers = new ArrayList<>();
    5357        List<RelationMember> wtfMembers = new ArrayList<>();
    54        
     58
    5559        int mCount = r.getMembersCount();
    5660        for (int i = 0; i < mCount; i++) {
     
    5862            if (PublicTransportHelper.isMemberStop(m)) {
    5963                RelationMember rm = new RelationMember(
    60                         m.hasRole() ? m.getRole() : PublicTransportHelper.STOP, 
    61                         m.getMember());
     64                        m.hasRole() ? m.getRole() : PublicTransportHelper.STOP,
     65                                m.getMember());
    6266                stopMembers.put(rm.getMember(), rm);
    6367            }
    6468            else if (PublicTransportHelper.isMemberPlatform(m)) {
    6569                RelationMember rm = new RelationMember(
    66                         m.hasRole() ? m.getRole() : PublicTransportHelper.PLATFORM, 
    67                         m.getMember());
     70                        m.hasRole() ? m.getRole() : PublicTransportHelper.PLATFORM,
     71                                m.getMember());
    6872                String platformName = PublicTransportHelper.getNameViaStoparea(rm);
    69                 if (platformName == null) platformName = "";
    70                 if (platformMembers.containsKey(platformName)) platformMembers.get(platformName).add(rm);
    71                 else {
     73                if (platformName == null) {
     74                    platformName = "";
     75                }
     76                if (platformMembers.containsKey(platformName)) {
     77                    platformMembers.get(platformName).add(rm);
     78                } else {
    7279                    List<RelationMember> nList = new ArrayList<>();
    7380                    nList.add(rm);
    7481                    platformMembers.put(platformName, nList);
    75                 }               
    76             }
    77             else if (PublicTransportHelper.isMemberRouteway(m)) routeMembers.add(new RelationMember(m));
    78             else wtfMembers.add(new RelationMember(m));
    79         }
    80        
     82                }
     83            }
     84            else if (PublicTransportHelper.isMemberRouteway(m)) {
     85                routeMembers.add(new RelationMember(m));
     86            } else {
     87                wtfMembers.add(new RelationMember(m));
     88            }
     89        }
     90
    8191        routeMembers = RelationSorter.sortMembersByConnectivity(routeMembers);
    82        
     92
    8393        Node lastNode = null;
    8494        for (int rIndex = 0; rIndex < routeMembers.size(); rIndex++) {
     
    91101                        dirForward = true;
    92102                        lastNode = w.lastNode();
    93                     } else lastNode = w.firstNode();
     103                    } else {
     104                        lastNode = w.firstNode();
     105                    }
    94106                } // else one segment - direction unknown
    95107            } else {
    96                 if (lastNode.equals(w.firstNode())) { dirForward = true; lastNode = w.lastNode(); }
    97                 else lastNode = w.firstNode();
     108                if (lastNode.equals(w.firstNode())) { dirForward = true; lastNode = w.lastNode(); } else {
     109                    lastNode = w.firstNode();
     110                }
    98111            }
    99112            final int wayNodeBeginIndex = (dirForward ? 0 : w.getNodesCount() - 1);
    100113            final int wayNodeEndIndex = (dirForward ? w.getNodesCount() - 1 : 0);
    101114            final int increment = (dirForward ? 1 : -1);
    102             for(int nIndex = wayNodeBeginIndex;
     115            for (int nIndex = wayNodeBeginIndex;
    103116                    nIndex != wayNodeEndIndex;
    104117                    nIndex += increment) {
     
    109122                        stopMembers.remove(refNode);
    110123                        String stopName = PublicTransportHelper.getNameViaStoparea(refNode);
    111                         if (stopName == null) stopName = "";
     124                        if (stopName == null) {
     125                            stopName = "";
     126                        }
    112127                        boolean existsPlatform = platformMembers.containsKey(stopName);
    113128                        if (!existsPlatform) { stopName = ""; } // find of the nameless
     
    118133                                lMember.remove(0);
    119134                            } else {
    120                                 // choose closest                               
     135                                // choose closest
    121136                                RelationMember candidat = getClosestPlatform(lMember, refNode);
    122137                                if (candidat != null) {
     
    125140                                }
    126141                            }
    127                             if (lMember.isEmpty()) platformMembers.remove(stopName);                           
     142                            if (lMember.isEmpty()) {
     143                                platformMembers.remove(stopName);
     144                            }
    128145                        }
    129146                    }
     
    131148            }
    132149        }
    133        
     150
    134151        for (RelationMember stop : stopMembers.values()) {
    135152            recRel.addMember(stop);
     
    137154            boolean existsPlatform = platformMembers.containsKey(stopName);
    138155            if (!existsPlatform) { stopName = ""; } // find of the nameless
    139             if (existsPlatform || platformMembers.containsKey(stopName)) {           
     156            if (existsPlatform || platformMembers.containsKey(stopName)) {
    140157                List<RelationMember> lMember = platformMembers.get(stopName);
    141158                if (lMember.size() == 1) {
     
    143160                    lMember.remove(0);
    144161                } else {
    145                     // choose closest                               
     162                    // choose closest
    146163                    RelationMember candidat = getClosestPlatform(lMember, stop.getNode());
    147164                    if (candidat != null) {
     
    150167                    }
    151168                }
    152                 if (lMember.isEmpty()) platformMembers.remove(stopName);                           
    153             }
    154         }
    155        
    156         for (List<RelationMember> lPlatforms : platformMembers.values())
    157             for (RelationMember platform : lPlatforms)
     169                if (lMember.isEmpty()) {
     170                    platformMembers.remove(stopName);
     171                }
     172            }
     173        }
     174
     175        for (List<RelationMember> lPlatforms : platformMembers.values()) {
     176            for (RelationMember platform : lPlatforms) {
    158177                recRel.addMember(platform);
    159        
    160         for (RelationMember route : routeMembers)
     178            }
     179        }
     180
     181        for (RelationMember route : routeMembers) {
    161182            recRel.addMember(route);
    162         for (RelationMember wtf : wtfMembers)
    163             recRel.addMember(wtf);       
     183        }
     184        for (RelationMember wtf : wtfMembers) {
     185            recRel.addMember(wtf);
     186        }
    164187        Command command = new ChangeCommand(r, recRel);
    165188        Main.main.undoRedo.add(command);
    166189    }
    167    
    168     private static final double maxSqrDistBetweenStopAndPlatform = 2000; // ~ 26m   
     190
     191    private static final double maxSqrDistBetweenStopAndPlatform = 2000; // ~ 26m
    169192    private RelationMember getClosestPlatform(List<RelationMember> members, Node stop) {
    170193        if (stop == null || members.isEmpty()) return null;
     
    182205                Way way = member.getWay();
    183206                EastNorth closest = Geometry.closestPointToSegment(
    184                                 way.firstNode().getEastNorth(),
    185                                 way.lastNode().getEastNorth(),
    186                                 stop.getEastNorth()
    187                 );
     207                        way.firstNode().getEastNorth(),
     208                        way.lastNode().getEastNorth(),
     209                        stop.getEastNorth()
     210                        );
    188211                double sqrDist = stop.getEastNorth().distanceSq(closest);
    189212                if (sqrDist < maxDist) {
     
    195218        return result;
    196219    }
    197  
    198     public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) {
    199         setEnabled(isSuitableRelation(newRelation));
    200     }   
    201    
     220
     221    @Override
     222    public void chosenRelationChanged(Relation oldRelation, Relation newRelation) {
     223        setEnabled(isSuitableRelation(newRelation));
     224    }
     225
    202226    private boolean isSuitableRelation (Relation newRelation) {
    203227        return !(newRelation == null || !"route".equals(newRelation.get("type")) || newRelation.getMembersCount() == 0);
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/RelationHelpAction.java

    r30737 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext.actions;
    23
    34import static org.openstreetmap.josm.tools.I18n.tr;
     5
    46import java.awt.event.ActionEvent;
    57import java.net.HttpURLConnection;
     
    810import java.util.ArrayList;
    911import java.util.List;
     12
    1013import javax.swing.AbstractAction;
     14
    1115import org.openstreetmap.josm.Main;
    1216import org.openstreetmap.josm.data.osm.Relation;
     
    1418import org.openstreetmap.josm.tools.LanguageInfo;
    1519import org.openstreetmap.josm.tools.OpenBrowser;
     20
    1621import relcontext.ChosenRelation;
    1722import relcontext.ChosenRelationListener;
     
    2025    private ChosenRelation rel;
    2126
    22     public RelationHelpAction( ChosenRelation rel ) {
     27    public RelationHelpAction(ChosenRelation rel) {
    2328        super();
    2429        putValue(NAME, tr("Open relation wiki page"));
     
    3035    }
    3136
    32     public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) {
     37    @Override
     38    public void chosenRelationChanged(Relation oldRelation, Relation newRelation) {
    3339        setEnabled(newRelation != null);
    3440    }
     
    3743     * Copypasted from {@link org.openstreetmap.josm.gui.dialogs.properties.PropertiesDialog.HelpAction}.
    3844     */
    39     public void actionPerformed( ActionEvent e ) {
    40         if( rel.get() == null )
     45    @Override
     46    public void actionPerformed(ActionEvent e) {
     47        if (rel.get() == null )
    4148            return;
    4249        try {
     
    5562
    5663            Main.worker.execute(new Runnable(){
     64                @Override
    5765                public void run() {
    5866                    try {
     
    7381                                        .replace("=", "%3D") /* do not URLencode whole string! */
    7482                                        .replaceFirst("/wiki/", "/w/index.php?redirect=no&title=")
    75                                 ).toURL().openConnection();
     83                                        ).toURL().openConnection();
    7684                                conn.setConnectTimeout(5000);
    7785
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/SelectInRelationPanelAction.java

    r25711 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext.actions;
    23
    34import static org.openstreetmap.josm.tools.I18n.tr;
     5
    46import java.awt.event.ActionEvent;
     7
    58import javax.swing.AbstractAction;
     9
    610import org.openstreetmap.josm.Main;
    711import org.openstreetmap.josm.data.osm.Relation;
    812import org.openstreetmap.josm.tools.ImageProvider;
     13
    914import relcontext.ChosenRelation;
    1015import relcontext.ChosenRelationListener;
     
    1318    private ChosenRelation rel;
    1419
    15     public SelectInRelationPanelAction( ChosenRelation rel ) {
     20    public SelectInRelationPanelAction(ChosenRelation rel) {
    1621        super();
    1722        putValue(NAME, tr("Select in relation list"));
     
    2328    }
    2429
    25     public void actionPerformed( ActionEvent e ) {
    26         if( rel.get() != null ) {
     30    @Override
     31    public void actionPerformed(ActionEvent e) {
     32        if (rel.get() != null) {
    2733            Main.map.relationListDialog.selectRelation(rel.get());
    2834            Main.map.relationListDialog.unfurlDialog();
     
    3036    }
    3137
    32     public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) {
     38    @Override
     39    public void chosenRelationChanged(Relation oldRelation, Relation newRelation) {
    3340        setEnabled(newRelation != null);
    3441    }
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/SelectMembersAction.java

    r30145 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext.actions;
    23
    34import static org.openstreetmap.josm.tools.I18n.tr;
     5
    46import java.awt.event.ActionEvent;
     7
    58import javax.swing.AbstractAction;
     9
    610import org.openstreetmap.josm.Main;
    711import org.openstreetmap.josm.data.osm.Relation;
    812import org.openstreetmap.josm.tools.ImageProvider;
     13
    914import relcontext.ChosenRelation;
    1015import relcontext.ChosenRelationListener;
     
    1318    private ChosenRelation rel;
    1419
    15     public SelectMembersAction( ChosenRelation rel ) {
     20    public SelectMembersAction(ChosenRelation rel) {
    1621        super(tr("Select members"));
    1722        putValue(SMALL_ICON, ImageProvider.get("selectall"));
     
    2126    }
    2227
    23     public void actionPerformed( ActionEvent e ) {
     28    @Override
     29    public void actionPerformed(ActionEvent e) {
    2430        Main.main.getEditLayer().data.setSelected(rel.get() == null ? null : rel.get().getMemberPrimitives());
    2531    }
    2632
    27     public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) {
     33    @Override
     34    public void chosenRelationChanged(Relation oldRelation, Relation newRelation) {
    2835        setEnabled(newRelation != null);
    2936    }
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/SelectRelationAction.java

    r30145 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext.actions;
    23
    34import static org.openstreetmap.josm.tools.I18n.tr;
     5
    46import java.awt.event.ActionEvent;
     7
    58import javax.swing.AbstractAction;
     9
    610import org.openstreetmap.josm.Main;
    711import org.openstreetmap.josm.data.osm.Relation;
    812import org.openstreetmap.josm.tools.ImageProvider;
     13
    914import relcontext.ChosenRelation;
    1015import relcontext.ChosenRelationListener;
     
    1318    private ChosenRelation rel;
    1419
    15     public SelectRelationAction( ChosenRelation rel ) {
     20    public SelectRelationAction(ChosenRelation rel) {
    1621        super(tr("Select relation"));
    1722        putValue(SHORT_DESCRIPTION, tr("Select relation in main selection."));
     
    2227    }
    2328
    24     public void actionPerformed( ActionEvent e ) {
     29    @Override
     30    public void actionPerformed(ActionEvent e) {
    2531        Main.main.getEditLayer().data.setSelected(rel.get() == null ? null : rel.get());
    2632    }
    2733
    28     public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) {
     34    @Override
     35    public void chosenRelationChanged(Relation oldRelation, Relation newRelation) {
    2936        setEnabled(newRelation != null);
    3037    }
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/SortAndFixAction.java

    r30841 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext.actions;
    23
     
    3031    private List<RelationFixer> fixers;
    3132
    32     public SortAndFixAction( ChosenRelation rel ) {
     33    public SortAndFixAction(ChosenRelation rel) {
    3334        super();
    34 //        putValue(Action.NAME, "AZ");
     35        //        putValue(Action.NAME, "AZ");
    3536        putValue(Action.SMALL_ICON, ImageProvider.get("data", "warning"));
    3637        putValue(Action.SHORT_DESCRIPTION, tr("Fix roles of the chosen relation members"));
     
    4748        fixers.add(new PublicTransportFixer()); //public_transport
    4849
    49         for(RelationFixer fix : fixers) {
     50        for (RelationFixer fix : fixers) {
    5051            fix.setFixAction(this);
    5152        }
     
    5354
    5455    @Override
    55     public void actionPerformed( ActionEvent e ) {
     56    public void actionPerformed(ActionEvent e) {
    5657        Command c = fixRelation(rel.get());
    57         if( c != null )
     58        if (c != null ) {
    5859            Main.main.undoRedo.add(c);
     60        }
    5961    }
    6062
    6163    @Override
    62     public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) {
    63         setEnabled(newRelation != null && needsFixing( newRelation));
     64    public void chosenRelationChanged(Relation oldRelation, Relation newRelation) {
     65        setEnabled(newRelation != null && needsFixing(newRelation));
    6466    }
    6567
    66     public boolean needsFixing( Relation rel ) {
     68    public boolean needsFixing(Relation rel) {
    6769        return !isIncomplete(rel) && !getFixer(rel).isRelationGood(rel);
    6870    }
    6971
    70     private RelationFixer getFixer( Relation rel ) {
    71         for(RelationFixer fixer : fixers)
     72    private RelationFixer getFixer(Relation rel) {
     73        for (RelationFixer fixer : fixers)
    7274            if (fixer.isFixerApplicable(rel))
    7375                return fixer;
     
    7577    }
    7678
    77     public Command fixRelation( Relation rel ) {
     79    public Command fixRelation(Relation rel) {
    7880        return getFixer(rel).fixRelation(rel);
    7981    }
    8082
    81     protected static boolean isIncomplete( Relation r ) {
    82         if( r == null || r.isIncomplete() || r.isDeleted() )
     83    protected static boolean isIncomplete(Relation r) {
     84        if (r == null || r.isIncomplete() || r.isDeleted() )
    8385            return true;
    84         for( RelationMember m : r.getMembers())
    85             if( m.getMember().isIncomplete() )
     86        for (RelationMember m : r.getMembers())
     87            if (m.getMember().isIncomplete() )
    8688                return true;
    8789        return false;
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/SplittingMultipolygons.java

    r30738 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext.actions;
    23
     4import static org.openstreetmap.josm.tools.I18n.tr;
     5
    36import java.awt.geom.Area;
    4 
    5 import static org.openstreetmap.josm.tools.I18n.tr;
    6 
    7 import java.util.*;
     7import java.util.ArrayList;
     8import java.util.Collection;
     9import java.util.Collections;
     10import java.util.HashMap;
     11import java.util.Iterator;
     12import java.util.List;
     13import java.util.Map;
    814
    915import org.openstreetmap.josm.Main;
    10 import org.openstreetmap.josm.command.*;
     16import org.openstreetmap.josm.command.AddCommand;
     17import org.openstreetmap.josm.command.ChangeCommand;
     18import org.openstreetmap.josm.command.Command;
     19import org.openstreetmap.josm.command.SequenceCommand;
    1120import org.openstreetmap.josm.data.coor.EastNorth;
    1221import org.openstreetmap.josm.data.coor.LatLon;
    13 import org.openstreetmap.josm.data.osm.*;
     22import org.openstreetmap.josm.data.osm.Node;
     23import org.openstreetmap.josm.data.osm.OsmPrimitive;
     24import org.openstreetmap.josm.data.osm.Relation;
     25import org.openstreetmap.josm.data.osm.RelationMember;
     26import org.openstreetmap.josm.data.osm.Way;
    1427import org.openstreetmap.josm.gui.DefaultNameFormatter;
    1528import org.openstreetmap.josm.tools.Geometry;
     
    2336    private static final String PREF_MULTIPOLY = "reltoolbox.multipolygon.";
    2437
    25     public static boolean canProcess( Collection<Way> ways ) {
    26     List<Way> rings = new ArrayList<>();
    27     List<Way> arcs = new ArrayList<>();
    28     Area a = Main.main.getCurrentDataSet().getDataSourceArea();
    29     for( Way way : ways ) {
    30         if( way.isDeleted() )
    31         return false;
    32         for( Node n : way.getNodes() ) {
    33             LatLon ll = n.getCoor();
    34             if( n.isIncomplete() || (a != null && !a.contains(ll.getX(), ll.getY())) )
     38    public static boolean canProcess(Collection<Way> ways) {
     39        List<Way> rings = new ArrayList<>();
     40        List<Way> arcs = new ArrayList<>();
     41        Area a = Main.main.getCurrentDataSet().getDataSourceArea();
     42        for (Way way : ways) {
     43            if (way.isDeleted() )
    3544                return false;
    36         }
    37         if( way.isClosed() )
    38         rings.add(way);
    39         else
    40         arcs.add(way);
    41     }
    42    
    43     // If there are more that one segment, check that they touch rings
    44     if( arcs.size() > 1 ) {
    45         for( Way segment : arcs ) {
    46         boolean found = false;
    47         for( Way ring : rings )
    48             if( ring.containsNode(segment.firstNode()) && ring.containsNode(segment.lastNode()) )
    49             found = true;
    50         if( !found )
     45            for (Node n : way.getNodes()) {
     46                LatLon ll = n.getCoor();
     47                if (n.isIncomplete() || (a != null && !a.contains(ll.getX(), ll.getY())) )
     48                    return false;
     49            }
     50            if (way.isClosed() ) {
     51                rings.add(way);
     52            } else {
     53                arcs.add(way);
     54            }
     55        }
     56
     57        // If there are more that one segment, check that they touch rings
     58        if (arcs.size() > 1) {
     59            for (Way segment : arcs) {
     60                boolean found = false;
     61                for (Way ring : rings )
     62                    if (ring.containsNode(segment.firstNode()) && ring.containsNode(segment.lastNode()) ) {
     63                        found = true;
     64                    }
     65                if (!found )
     66                    return false;
     67            }
     68        }
     69
     70        if (rings.isEmpty() && arcs.isEmpty() )
    5171            return false;
    52         }
    53     }
    54 
    55     if( rings.isEmpty() && arcs.isEmpty() )
    56         return false;
    57 
    58     // check for non-containment of rings
    59     for( int i = 0; i < rings.size() - 1; i++ ) {
    60         for( int j = i + 1; j < rings.size(); j++ ) {
    61         PolygonIntersection intersection = Geometry.polygonIntersection(rings.get(i).getNodes(), rings.get(j).getNodes());
    62         if( intersection == PolygonIntersection.FIRST_INSIDE_SECOND || intersection == PolygonIntersection.SECOND_INSIDE_FIRST )
    63             return false;
    64         }
    65     }
    66 
    67     return true;
    68     }
    69    
    70     public static List<Relation> process( Collection<Way> selectedWays ) {
    71 //    System.out.println("---------------------------------------");
    72     List<Relation> result = new ArrayList<>();
    73     List<Way> rings = new ArrayList<>();
    74     List<Way> arcs = new ArrayList<>();
    75     for( Way way : selectedWays ) {
    76         if( way.isClosed() )
    77         rings.add(way);
    78         else
    79         arcs.add(way);
    80     }
    81 
    82     for( Way ring : rings ) {
    83         List<Command> commands = new ArrayList<>();
    84         Relation newRelation = SplittingMultipolygons.attachRingToNeighbours(ring, commands);
    85         if( newRelation != null && !commands.isEmpty() ) {
    86         Main.main.undoRedo.add(commands.get(0));
    87         result.add(newRelation);
    88         }
    89     }
    90 
    91     for( Way arc : arcs) {
    92         List<Command> commands = new ArrayList<>();
    93         Relation newRelation = SplittingMultipolygons.tryToCloseOneWay(arc, commands);
    94         if( newRelation != null && !commands.isEmpty() ) {
    95         Main.main.undoRedo.add(commands.get(0));
    96         result.add(newRelation);
    97         }
    98     }
    99     return result;
     72
     73        // check for non-containment of rings
     74        for (int i = 0; i < rings.size() - 1; i++) {
     75            for (int j = i + 1; j < rings.size(); j++) {
     76                PolygonIntersection intersection = Geometry.polygonIntersection(rings.get(i).getNodes(), rings.get(j).getNodes());
     77                if (intersection == PolygonIntersection.FIRST_INSIDE_SECOND || intersection == PolygonIntersection.SECOND_INSIDE_FIRST )
     78                    return false;
     79            }
     80        }
     81
     82        return true;
     83    }
     84
     85    public static List<Relation> process(Collection<Way> selectedWays) {
     86        //    System.out.println("---------------------------------------");
     87        List<Relation> result = new ArrayList<>();
     88        List<Way> rings = new ArrayList<>();
     89        List<Way> arcs = new ArrayList<>();
     90        for (Way way : selectedWays) {
     91            if (way.isClosed() ) {
     92                rings.add(way);
     93            } else {
     94                arcs.add(way);
     95            }
     96        }
     97
     98        for (Way ring : rings) {
     99            List<Command> commands = new ArrayList<>();
     100            Relation newRelation = SplittingMultipolygons.attachRingToNeighbours(ring, commands);
     101            if (newRelation != null && !commands.isEmpty()) {
     102                Main.main.undoRedo.add(commands.get(0));
     103                result.add(newRelation);
     104            }
     105        }
     106
     107        for (Way arc : arcs) {
     108            List<Command> commands = new ArrayList<>();
     109            Relation newRelation = SplittingMultipolygons.tryToCloseOneWay(arc, commands);
     110            if (newRelation != null && !commands.isEmpty()) {
     111                Main.main.undoRedo.add(commands.get(0));
     112                result.add(newRelation);
     113            }
     114        }
     115        return result;
    100116    }
    101117
     
    103119     * Appends "append" to "base" so the closed polygon forms.
    104120     */
    105     private static void closePolygon( List<Node> base, List<Node> append ) {
    106     if( append.get(0).equals(base.get(0)) && append.get(append.size() - 1).equals(base.get(base.size() - 1)) ) {
    107         List<Node> ap2 = new ArrayList<>(append);
    108         Collections.reverse(ap2);
    109         append = ap2;
    110     }
    111     base.remove(base.size() - 1);
    112     base.addAll(append);
     121    private static void closePolygon(List<Node> base, List<Node> append) {
     122        if (append.get(0).equals(base.get(0)) && append.get(append.size() - 1).equals(base.get(base.size() - 1))) {
     123            List<Node> ap2 = new ArrayList<>(append);
     124            Collections.reverse(ap2);
     125            append = ap2;
     126        }
     127        base.remove(base.size() - 1);
     128        base.addAll(append);
    113129    }
    114130
     
    116132     * Checks if a middle point between two nodes is inside a polygon. Useful to check if the way is inside.
    117133     */
    118     private static boolean segmentInsidePolygon( Node n1, Node n2, List<Node> polygon ) {
    119     EastNorth en1 = n1.getEastNorth();
    120     EastNorth en2 = n2.getEastNorth();
    121     Node testNode = new Node(new EastNorth((en1.east() + en2.east()) / 2.0, (en1.north() + en2.north()) / 2.0));
    122     return Geometry.nodeInsidePolygon(testNode, polygon);
     134    private static boolean segmentInsidePolygon(Node n1, Node n2, List<Node> polygon) {
     135        EastNorth en1 = n1.getEastNorth();
     136        EastNorth en2 = n2.getEastNorth();
     137        Node testNode = new Node(new EastNorth((en1.east() + en2.east()) / 2.0, (en1.north() + en2.north()) / 2.0));
     138        return Geometry.nodeInsidePolygon(testNode, polygon);
    123139    }
    124140
     
    130146     * @return Newly created ways. <b>Warning:</b> if commands is no not, newWays contains {@code w}.
    131147     */
    132     public static List<Way> splitWay( Way w, Node n1, Node n2, List<Command> commands ) {
    133     List<Node> nodes = new ArrayList<>(w.getNodes());
    134     if( w.isClosed() )
    135         nodes.remove(nodes.size() - 1);
    136     int index1 = nodes.indexOf(n1);
    137     int index2 = n2 == null ? -1 : nodes.indexOf(n2);
    138     if( index1 > index2 ) {
    139         int tmp = index1;
    140         index1 = index2;
    141         index2 = tmp;
    142     }
    143     // right now index2 >= index1
    144     if( index2 < 1 || index1 >= w.getNodesCount() - 1 || index2 >= w.getNodesCount() )
    145         return Collections.emptyList();
    146     if( w.isClosed() && (index1 < 0 || index1 == index2 || index1 + w.getNodesCount() == index2) )
    147         return Collections.emptyList();
    148    
    149     // todo: download parent relations!
    150 
    151     // make a list of segments
    152     List<List<Node>> chunks = new ArrayList<>(2);
    153     List<Node> chunk = new ArrayList<>();
    154     for( int i = 0; i < nodes.size(); i++ ) {
    155         chunk.add(nodes.get(i));
    156         if( (w.isClosed() || chunk.size() > 1) && (i == index1 || i == index2) ) {
     148    public static List<Way> splitWay(Way w, Node n1, Node n2, List<Command> commands) {
     149        List<Node> nodes = new ArrayList<>(w.getNodes());
     150        if (w.isClosed() ) {
     151            nodes.remove(nodes.size() - 1);
     152        }
     153        int index1 = nodes.indexOf(n1);
     154        int index2 = n2 == null ? -1 : nodes.indexOf(n2);
     155        if (index1 > index2) {
     156            int tmp = index1;
     157            index1 = index2;
     158            index2 = tmp;
     159        }
     160        // right now index2 >= index1
     161        if (index2 < 1 || index1 >= w.getNodesCount() - 1 || index2 >= w.getNodesCount() )
     162            return Collections.emptyList();
     163        if (w.isClosed() && (index1 < 0 || index1 == index2 || index1 + w.getNodesCount() == index2) )
     164            return Collections.emptyList();
     165
     166        // todo: download parent relations!
     167
     168        // make a list of segments
     169        List<List<Node>> chunks = new ArrayList<>(2);
     170        List<Node> chunk = new ArrayList<>();
     171        for (int i = 0; i < nodes.size(); i++) {
     172            chunk.add(nodes.get(i));
     173            if ((w.isClosed() || chunk.size() > 1) && (i == index1 || i == index2)) {
     174                chunks.add(chunk);
     175                chunk = new ArrayList<>();
     176                chunk.add(nodes.get(i));
     177            }
     178        }
    157179        chunks.add(chunk);
    158         chunk = new ArrayList<>();
    159         chunk.add(nodes.get(i));
    160         }
    161     }
    162     chunks.add(chunk);
    163 
    164     // for closed way ignore the way boundary
    165     if( w.isClosed() ) {
    166         chunks.get(chunks.size() - 1).addAll(chunks.get(0));
    167         chunks.remove(0);
    168     } else if( chunks.get(chunks.size() - 1).size() < 2 )
    169         chunks.remove(chunks.size() - 1);
    170 
    171     // todo remove debug: show chunks array contents
    172     /*for( List<Node> c1 : chunks ) {
    173     for( Node cn1 : c1 )
     180
     181        // for closed way ignore the way boundary
     182        if (w.isClosed()) {
     183            chunks.get(chunks.size() - 1).addAll(chunks.get(0));
     184            chunks.remove(0);
     185        } else if (chunks.get(chunks.size() - 1).size() < 2 ) {
     186            chunks.remove(chunks.size() - 1);
     187        }
     188
     189        // todo remove debug: show chunks array contents
     190        /*for (List<Node> c1 : chunks) {
     191    for (Node cn1 : c1 )
    174192    System.out.print(cn1.getId() + ",");
    175193    System.out.println();
    176194    }*/
    177195
    178     // build a map of referencing relations
    179     Map<Relation, Integer> references = new HashMap<>();
    180     List<Command> relationCommands = new ArrayList<>();
    181     for( OsmPrimitive p : w.getReferrers() ) {
    182         if( p instanceof Relation ) {
    183         Relation rel = commands == null ? (Relation)p : new Relation((Relation)p);
    184         if( commands != null )
    185             relationCommands.add(new ChangeCommand((Relation)p, rel));
    186         for( int i = 0; i < rel.getMembersCount(); i++ )
    187             if( rel.getMember(i).getMember().equals(w) )
    188             references.put(rel, Integer.valueOf(i));
    189         }
    190     }
    191 
    192     // build ways
    193     List<Way> result = new ArrayList<>();
    194     Way updatedWay = commands == null ? w : new Way(w);
    195     updatedWay.setNodes(chunks.get(0));
    196     if( commands != null ) {
    197         commands.add(new ChangeCommand(w, updatedWay));
    198         result.add(updatedWay);
    199     }
    200 
    201     for( int i = 1; i < chunks.size(); i++ ) {
    202         List<Node> achunk = chunks.get(i);
    203         Way newWay = new Way();
    204         newWay.setKeys(w.getKeys());
    205         result.add(newWay);
    206         for( Relation rel : references.keySet() ) {
    207         int relIndex = references.get(rel);
    208         rel.addMember(relIndex + 1, new RelationMember(rel.getMember(relIndex).getRole(), newWay));
    209         }
    210         newWay.setNodes(achunk);
    211         if( commands != null )
    212         commands.add(new AddCommand(newWay));
    213     }
    214     if( commands != null )
    215         commands.addAll(relationCommands);
    216     return result;
    217     }
    218 
    219     public static List<Way> splitWay( Way w, Node n1, Node n2 ) {
    220     return splitWay(w, n1, n2, null);
     196        // build a map of referencing relations
     197        Map<Relation, Integer> references = new HashMap<>();
     198        List<Command> relationCommands = new ArrayList<>();
     199        for (OsmPrimitive p : w.getReferrers()) {
     200            if (p instanceof Relation) {
     201                Relation rel = commands == null ? (Relation)p : new Relation((Relation)p);
     202                if (commands != null ) {
     203                    relationCommands.add(new ChangeCommand(p, rel));
     204                }
     205                for (int i = 0; i < rel.getMembersCount(); i++ )
     206                    if (rel.getMember(i).getMember().equals(w) ) {
     207                        references.put(rel, Integer.valueOf(i));
     208                    }
     209            }
     210        }
     211
     212        // build ways
     213        List<Way> result = new ArrayList<>();
     214        Way updatedWay = commands == null ? w : new Way(w);
     215        updatedWay.setNodes(chunks.get(0));
     216        if (commands != null) {
     217            commands.add(new ChangeCommand(w, updatedWay));
     218            result.add(updatedWay);
     219        }
     220
     221        for (int i = 1; i < chunks.size(); i++) {
     222            List<Node> achunk = chunks.get(i);
     223            Way newWay = new Way();
     224            newWay.setKeys(w.getKeys());
     225            result.add(newWay);
     226            for (Relation rel : references.keySet()) {
     227                int relIndex = references.get(rel);
     228                rel.addMember(relIndex + 1, new RelationMember(rel.getMember(relIndex).getRole(), newWay));
     229            }
     230            newWay.setNodes(achunk);
     231            if (commands != null ) {
     232                commands.add(new AddCommand(newWay));
     233            }
     234        }
     235        if (commands != null ) {
     236            commands.addAll(relationCommands);
     237        }
     238        return result;
     239    }
     240
     241    public static List<Way> splitWay(Way w, Node n1, Node n2) {
     242        return splitWay(w, n1, n2, null);
    221243    }
    222244
     
    224246     * Find a way the tips of a segment, ensure it's in a multipolygon and try to close the relation.
    225247     */
    226     public static Relation tryToCloseOneWay( Way segment, List<Command> resultingCommands ) {
    227     if( segment.isClosed() || segment.isIncomplete() )
    228         return null;
    229 
    230     List<Way> ways = intersection(
    231         OsmPrimitive.getFilteredList(segment.firstNode().getReferrers(), Way.class),
    232         OsmPrimitive.getFilteredList(segment.lastNode().getReferrers(), Way.class));
    233     ways.remove(segment);
    234     for( Iterator<Way> iter = ways.iterator(); iter.hasNext(); ) {
    235         boolean save = false;
    236         for( OsmPrimitive ref : iter.next().getReferrers() )
    237         if( ref instanceof Relation && ((Relation)ref).isMultipolygon() && !ref.isDeleted() )
    238             save = true;
    239         if( !save )
    240         iter.remove();
    241     }
    242     if( ways.isEmpty() )
    243         return null; // well...
    244     Way target = ways.get(0);
    245 
    246     // time to create a new multipolygon relation and a command stack
    247     List<Command> commands = new ArrayList<>();
    248     Relation newRelation = new Relation();
    249     newRelation.put("type", "multipolygon");
    250     newRelation.addMember(new RelationMember("outer", segment));
    251     Collection<String> linearTags = Main.pref.getCollection(PREF_MULTIPOLY + "lineartags", CreateMultipolygonAction.DEFAULT_LINEAR_TAGS);
    252     Way segmentCopy = new Way(segment);
    253     boolean changed = false;
    254     for( String key : segmentCopy.keySet() ) {
    255         if( !linearTags.contains(key) ) {
    256         newRelation.put(key, segmentCopy.get(key));
    257         segmentCopy.remove(key);
    258         changed = true;
    259         }
    260     }
    261     if( changed )
    262         commands.add(new ChangeCommand(segment, segmentCopy));
    263 
    264     // now split the way, at last
    265     List<Way> newWays = new ArrayList<>(splitWay(target, segment.firstNode(), segment.lastNode(), commands));
    266 
    267     Way addingWay = null;
    268     if( target.isClosed() ) {
    269         Way utarget = newWays.get(1);
    270         Way alternate = newWays.get(0);
    271         List<Node> testRing = new ArrayList<>(segment.getNodes());
    272         closePolygon(testRing, utarget.getNodes());
    273         addingWay = segmentInsidePolygon(alternate.getNode(0), alternate.getNode(1), testRing) ? alternate : utarget;
    274     } else {
    275         for( Way w : newWays ) {
    276         if( (w.firstNode().equals(segment.firstNode()) && w.lastNode().equals(segment.lastNode()))
    277             || (w.firstNode().equals(segment.lastNode()) && w.lastNode().equals(segment.firstNode())) ) {
    278             addingWay = w;
    279             break;
    280         }
    281         }
    282     }
    283     newRelation.addMember(new RelationMember("outer", addingWay.getUniqueId() == target.getUniqueId() ? target : addingWay));
    284     commands.add(new AddCommand(newRelation));
    285     resultingCommands.add(new SequenceCommand(tr("Complete multipolygon for way {0}",
    286         DefaultNameFormatter.getInstance().format(segment)), commands));
    287     return newRelation;
     248    public static Relation tryToCloseOneWay(Way segment, List<Command> resultingCommands) {
     249        if (segment.isClosed() || segment.isIncomplete() )
     250            return null;
     251
     252        List<Way> ways = intersection(
     253                OsmPrimitive.getFilteredList(segment.firstNode().getReferrers(), Way.class),
     254                OsmPrimitive.getFilteredList(segment.lastNode().getReferrers(), Way.class));
     255        ways.remove(segment);
     256        for (Iterator<Way> iter = ways.iterator(); iter.hasNext();) {
     257            boolean save = false;
     258            for (OsmPrimitive ref : iter.next().getReferrers() )
     259                if (ref instanceof Relation && ((Relation)ref).isMultipolygon() && !ref.isDeleted() ) {
     260                    save = true;
     261                }
     262            if (!save ) {
     263                iter.remove();
     264            }
     265        }
     266        if (ways.isEmpty() )
     267            return null; // well...
     268        Way target = ways.get(0);
     269
     270        // time to create a new multipolygon relation and a command stack
     271        List<Command> commands = new ArrayList<>();
     272        Relation newRelation = new Relation();
     273        newRelation.put("type", "multipolygon");
     274        newRelation.addMember(new RelationMember("outer", segment));
     275        Collection<String> linearTags = Main.pref.getCollection(PREF_MULTIPOLY + "lineartags", CreateMultipolygonAction.DEFAULT_LINEAR_TAGS);
     276        Way segmentCopy = new Way(segment);
     277        boolean changed = false;
     278        for (String key : segmentCopy.keySet()) {
     279            if (!linearTags.contains(key)) {
     280                newRelation.put(key, segmentCopy.get(key));
     281                segmentCopy.remove(key);
     282                changed = true;
     283            }
     284        }
     285        if (changed ) {
     286            commands.add(new ChangeCommand(segment, segmentCopy));
     287        }
     288
     289        // now split the way, at last
     290        List<Way> newWays = new ArrayList<>(splitWay(target, segment.firstNode(), segment.lastNode(), commands));
     291
     292        Way addingWay = null;
     293        if (target.isClosed()) {
     294            Way utarget = newWays.get(1);
     295            Way alternate = newWays.get(0);
     296            List<Node> testRing = new ArrayList<>(segment.getNodes());
     297            closePolygon(testRing, utarget.getNodes());
     298            addingWay = segmentInsidePolygon(alternate.getNode(0), alternate.getNode(1), testRing) ? alternate : utarget;
     299        } else {
     300            for (Way w : newWays) {
     301                if ((w.firstNode().equals(segment.firstNode()) && w.lastNode().equals(segment.lastNode()))
     302                        || (w.firstNode().equals(segment.lastNode()) && w.lastNode().equals(segment.firstNode()))) {
     303                    addingWay = w;
     304                    break;
     305                }
     306            }
     307        }
     308        newRelation.addMember(new RelationMember("outer", addingWay.getUniqueId() == target.getUniqueId() ? target : addingWay));
     309        commands.add(new AddCommand(newRelation));
     310        resultingCommands.add(new SequenceCommand(tr("Complete multipolygon for way {0}",
     311                DefaultNameFormatter.getInstance().format(segment)), commands));
     312        return newRelation;
    288313    }
    289314
     
    291316     * Returns all elements from {@code list1} that are in {@code list2}.
    292317     */
    293     private static <T> List<T> intersection( Collection<T> list1, Collection<T> list2 ) {
    294     List<T> result = new ArrayList<>();
    295     for( T item : list1 )
    296         if( list2.contains(item) )
    297         result.add(item);
    298     return result;
    299     }
    300    
     318    private static <T> List<T> intersection(Collection<T> list1, Collection<T> list2) {
     319        List<T> result = new ArrayList<>();
     320        for (T item : list1 )
     321            if (list2.contains(item) ) {
     322                result.add(item);
     323            }
     324        return result;
     325    }
     326
    301327    /**
    302328     * Make a multipolygon out of the ring, but split it to attach to neighboring multipolygons.
    303329     */
    304     public static Relation attachRingToNeighbours( Way ring, List<Command> resultingCommands ) {
    305     if( !ring.isClosed() || ring.isIncomplete() )
    306         return null;
    307     Map<Way, Boolean> touchingWays = new HashMap<>();
    308     for( Node n : ring.getNodes() ) {
    309         for( OsmPrimitive p : n.getReferrers() ) {
    310         if( p instanceof Way && !p.equals(ring) ) {
    311             for( OsmPrimitive r : p.getReferrers() ) {
    312             if( r instanceof Relation && ((Relation)r).hasKey("type") && ((Relation)r).get("type").equals("multipolygon") ) {
    313                 if( touchingWays.containsKey((Way)p) )
    314                 touchingWays.put((Way)p, Boolean.TRUE);
    315                 else
    316                 touchingWays.put((Way)p, Boolean.FALSE);
    317                 break;
    318             }
    319             }
    320         }
    321         }
    322     }
    323    
    324     List<TheRing> otherWays = new ArrayList<>();
    325     for( Way w : touchingWays.keySet() )
    326         if( touchingWays.get(w) ) {
    327         otherWays.add(new TheRing(w));
    328 //        System.out.println("Touching ring: " + otherWays.get(otherWays.size()-1));
    329         }
    330    
    331 //    for( Iterator<Way> keys = touchingWays.keySet().iterator(); keys.hasNext(); ) {
    332 //        if( !touchingWays.get(keys.next()) )
    333 //        keys.remove();
    334 //    }
    335    
    336     // now touchingWays has only ways that touch the ring twice
    337     List<Command> commands = new ArrayList<>();
    338     TheRing theRing = new TheRing(ring); // this is actually useful
    339    
    340     for( TheRing otherRing : otherWays )
    341         theRing.collide(otherRing);
    342    
    343     theRing.putSourceWayFirst();
    344     for( TheRing otherRing : otherWays )
    345         otherRing.putSourceWayFirst();
    346    
    347     Map<Relation, Relation> relationCache = new HashMap<>();
    348     for( TheRing otherRing : otherWays )
    349         commands.addAll(otherRing.getCommands(false, relationCache));
    350     commands.addAll(theRing.getCommands(relationCache));
    351     TheRing.updateCommandsWithRelations(commands, relationCache);
    352     resultingCommands.add(new SequenceCommand(tr("Complete multipolygon for way {0}",
    353         DefaultNameFormatter.getInstance().format(ring)), commands));
    354     return theRing.getRelation();
     330    public static Relation attachRingToNeighbours(Way ring, List<Command> resultingCommands) {
     331        if (!ring.isClosed() || ring.isIncomplete() )
     332            return null;
     333        Map<Way, Boolean> touchingWays = new HashMap<>();
     334        for (Node n : ring.getNodes()) {
     335            for (OsmPrimitive p : n.getReferrers()) {
     336                if (p instanceof Way && !p.equals(ring)) {
     337                    for (OsmPrimitive r : p.getReferrers()) {
     338                        if (r instanceof Relation && ((Relation)r).hasKey("type") && ((Relation)r).get("type").equals("multipolygon")) {
     339                            if (touchingWays.containsKey(p) ) {
     340                                touchingWays.put((Way)p, Boolean.TRUE);
     341                            } else {
     342                                touchingWays.put((Way)p, Boolean.FALSE);
     343                            }
     344                            break;
     345                        }
     346                    }
     347                }
     348            }
     349        }
     350
     351        List<TheRing> otherWays = new ArrayList<>();
     352        for (Way w : touchingWays.keySet() )
     353            if (touchingWays.get(w)) {
     354                otherWays.add(new TheRing(w));
     355                //        System.out.println("Touching ring: " + otherWays.get(otherWays.size()-1));
     356            }
     357
     358        //    for (Iterator<Way> keys = touchingWays.keySet().iterator(); keys.hasNext();) {
     359        //        if (!touchingWays.get(keys.next()) )
     360        //        keys.remove();
     361        //    }
     362
     363        // now touchingWays has only ways that touch the ring twice
     364        List<Command> commands = new ArrayList<>();
     365        TheRing theRing = new TheRing(ring); // this is actually useful
     366
     367        for (TheRing otherRing : otherWays ) {
     368            theRing.collide(otherRing);
     369        }
     370
     371        theRing.putSourceWayFirst();
     372        for (TheRing otherRing : otherWays ) {
     373            otherRing.putSourceWayFirst();
     374        }
     375
     376        Map<Relation, Relation> relationCache = new HashMap<>();
     377        for (TheRing otherRing : otherWays ) {
     378            commands.addAll(otherRing.getCommands(false, relationCache));
     379        }
     380        commands.addAll(theRing.getCommands(relationCache));
     381        TheRing.updateCommandsWithRelations(commands, relationCache);
     382        resultingCommands.add(new SequenceCommand(tr("Complete multipolygon for way {0}",
     383                DefaultNameFormatter.getInstance().format(ring)), commands));
     384        return theRing.getRelation();
    355385    }
    356386}
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/TheRing.java

    r30738 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext.actions;
    23
     
    2526 * One ring that contains segments forming an outer way of multipolygon.
    2627 * This class is used in {@link CreateMultipolygonAction#makeManySimpleMultipolygons(java.util.Collection)}.
    27  * 
     28 *
    2829 * @author Zverik
    2930 */
     
    3536    private Relation relation = null;
    3637
    37     public TheRing( Way source ) {
    38     this.source = source;
    39     segments = new ArrayList<>(1);
    40     segments.add(new RingSegment(source));
    41     }
    42    
    43     public static boolean areAllOfThoseRings( Collection<Way> ways ) {
    44     List<Way> rings = new ArrayList<>();
    45     for( Way way : ways ) {
    46         if( way.isClosed() )
    47         rings.add(way);
    48         else
    49         return false;
    50     }
    51     if( rings.isEmpty() || ways.size() == 1 )
    52         return false;
    53 
    54     // check for non-containment of rings
    55     for( int i = 0; i < rings.size() - 1; i++ ) {
    56         for( int j = i + 1; j < rings.size(); j++ ) {
    57         PolygonIntersection intersection = Geometry.polygonIntersection(rings.get(i).getNodes(), rings.get(j).getNodes());
    58         if( intersection == PolygonIntersection.FIRST_INSIDE_SECOND || intersection == PolygonIntersection.SECOND_INSIDE_FIRST )
     38    public TheRing(Way source) {
     39        this.source = source;
     40        segments = new ArrayList<>(1);
     41        segments.add(new RingSegment(source));
     42    }
     43
     44    public static boolean areAllOfThoseRings(Collection<Way> ways) {
     45        List<Way> rings = new ArrayList<>();
     46        for (Way way : ways) {
     47            if (way.isClosed() ) {
     48                rings.add(way);
     49            } else
     50                return false;
     51        }
     52        if (rings.isEmpty() || ways.size() == 1 )
    5953            return false;
    60         }
    61     }
    62 
    63     return true;
     54
     55        // check for non-containment of rings
     56        for (int i = 0; i < rings.size() - 1; i++) {
     57            for (int j = i + 1; j < rings.size(); j++) {
     58                PolygonIntersection intersection = Geometry.polygonIntersection(rings.get(i).getNodes(), rings.get(j).getNodes());
     59                if (intersection == PolygonIntersection.FIRST_INSIDE_SECOND || intersection == PolygonIntersection.SECOND_INSIDE_FIRST )
     60                    return false;
     61            }
     62        }
     63
     64        return true;
    6465    }
    6566
     
    6869     * @return list of new relations.
    6970     */
    70     public static List<Relation> makeManySimpleMultipolygons( Collection<Way> selection, List<Command> commands ) {
    71     log("---------------------------------------");
    72     List<TheRing> rings = new ArrayList<>(selection.size());
    73     for( Way w : selection )
    74         rings.add(new TheRing(w));
    75     for( int i = 0; i < rings.size() - 1; i++ )
    76         for( int j = i + 1; j < rings.size(); j++ )
    77         rings.get(i).collide(rings.get(j));
    78     redistributeSegments(rings);
    79     List<Relation> relations = new ArrayList<>();
    80     Map<Relation, Relation> relationCache = new HashMap<>();
    81     for( TheRing r : rings ) {
    82         commands.addAll(r.getCommands(relationCache));
    83         relations.add(r.getRelation());
    84     }
    85     updateCommandsWithRelations(commands, relationCache);
    86     return relations;
    87     }
    88 
    89     public void collide( TheRing other ) {
    90     boolean collideNoted = false;
    91     for( int i = 0; i < segments.size(); i++ ) {
    92         RingSegment segment1 = segments.get(i);
    93         if( !segment1.isReference() ) {
    94         for( int j = 0; j < other.segments.size(); j++ ) {
    95             RingSegment segment2 = other.segments.get(j);
    96             if( !segment2.isReference() ) {
    97             log("Comparing " + segment1 + " and " + segment2);
    98             Node[] split = getSplitNodes(segment1.getNodes(), segment2.getNodes(), segment1.isRing(), segment2.isRing());
    99             if( split != null ) {
    100                 if( !collideNoted ) {
    101                 log("Rings for ways " + source.getUniqueId() + " and " + other.source.getUniqueId() + " collide.");
    102                 collideNoted = true;
    103                 }
    104                 RingSegment segment = splitRingAt(i, split[0], split[1]);
    105                 RingSegment otherSegment = other.splitRingAt(j, split[2], split[3]);
    106                 if( !areSegmentsEqual(segment, otherSegment) )
    107                 throw new IllegalArgumentException("Error: algorithm gave incorrect segments: " + segment + " and " + otherSegment);
    108                 segment.makeReference(otherSegment);
    109             }
    110             }
    111             if( segment1.isReference() )
    112             break;
    113         }
    114         }
    115     }
    116     }
    117    
     71    public static List<Relation> makeManySimpleMultipolygons(Collection<Way> selection, List<Command> commands) {
     72        log("---------------------------------------");
     73        List<TheRing> rings = new ArrayList<>(selection.size());
     74        for (Way w : selection ) {
     75            rings.add(new TheRing(w));
     76        }
     77        for (int i = 0; i < rings.size() - 1; i++ ) {
     78            for (int j = i + 1; j < rings.size(); j++ ) {
     79                rings.get(i).collide(rings.get(j));
     80            }
     81        }
     82        redistributeSegments(rings);
     83        List<Relation> relations = new ArrayList<>();
     84        Map<Relation, Relation> relationCache = new HashMap<>();
     85        for (TheRing r : rings) {
     86            commands.addAll(r.getCommands(relationCache));
     87            relations.add(r.getRelation());
     88        }
     89        updateCommandsWithRelations(commands, relationCache);
     90        return relations;
     91    }
     92
     93    public void collide(TheRing other) {
     94        boolean collideNoted = false;
     95        for (int i = 0; i < segments.size(); i++) {
     96            RingSegment segment1 = segments.get(i);
     97            if (!segment1.isReference()) {
     98                for (int j = 0; j < other.segments.size(); j++) {
     99                    RingSegment segment2 = other.segments.get(j);
     100                    if (!segment2.isReference()) {
     101                        log("Comparing " + segment1 + " and " + segment2);
     102                        Node[] split = getSplitNodes(segment1.getNodes(), segment2.getNodes(), segment1.isRing(), segment2.isRing());
     103                        if (split != null) {
     104                            if (!collideNoted) {
     105                                log("Rings for ways " + source.getUniqueId() + " and " + other.source.getUniqueId() + " collide.");
     106                                collideNoted = true;
     107                            }
     108                            RingSegment segment = splitRingAt(i, split[0], split[1]);
     109                            RingSegment otherSegment = other.splitRingAt(j, split[2], split[3]);
     110                            if (!areSegmentsEqual(segment, otherSegment) )
     111                                throw new IllegalArgumentException("Error: algorithm gave incorrect segments: " + segment + " and " + otherSegment);
     112                            segment.makeReference(otherSegment);
     113                        }
     114                    }
     115                    if (segment1.isReference() ) {
     116                        break;
     117                    }
     118                }
     119            }
     120        }
     121    }
     122
    118123    /**
    119124     * Returns array of {start1, last1, start2, last2} or null if there is no common nodes.
    120125     */
    121     public static Node[] getSplitNodes( List<Node> nodes1, List<Node> nodes2, boolean isRing1, boolean isRing2 ) {
    122     int pos = 0;
    123     while( pos < nodes1.size() && !nodes2.contains(nodes1.get(pos)) )
    124         pos++;
    125     boolean collideFound = pos == nodes1.size();
    126     if( pos == 0 && isRing1 ) {
    127         // rewind a bit
    128         pos = nodes1.size() - 1;
    129         while( pos > 0 && nodes2.contains(nodes1.get(pos)) )
    130         pos--;
    131         if( pos == 0 && nodes1.size() == nodes2.size() ) {
    132         JOptionPane.showMessageDialog(Main.parent, "Two rings are equal, and this must not be.", "Multipolygon from rings", JOptionPane.ERROR_MESSAGE);
     126    public static Node[] getSplitNodes(List<Node> nodes1, List<Node> nodes2, boolean isRing1, boolean isRing2) {
     127        int pos = 0;
     128        while(pos < nodes1.size() && !nodes2.contains(nodes1.get(pos)) ) {
     129            pos++;
     130        }
     131        boolean collideFound = pos == nodes1.size();
     132        if (pos == 0 && isRing1) {
     133            // rewind a bit
     134            pos = nodes1.size() - 1;
     135            while(pos > 0 && nodes2.contains(nodes1.get(pos)) ) {
     136                pos--;
     137            }
     138            if (pos == 0 && nodes1.size() == nodes2.size()) {
     139                JOptionPane.showMessageDialog(Main.parent, "Two rings are equal, and this must not be.", "Multipolygon from rings", JOptionPane.ERROR_MESSAGE);
     140                return null;
     141            }
     142            pos = pos == nodes1.size() - 1 ? 0 : pos + 1;
     143        }
     144        int firstPos = isRing1 ? pos : nodes1.size();
     145        while(!collideFound) {
     146            log("pos=" + pos);
     147            int start1 = pos;
     148            int start2 = nodes2.indexOf(nodes1.get(start1));
     149            int last1 = incrementBy(start1, 1, nodes1.size(), isRing1);
     150            int last2 = start2;
     151            int increment2 = 0;
     152            if (last1 >= 0) {
     153                last2 = incrementBy(start2, -1, nodes2.size(), isRing2);
     154                if (last2 >= 0 && nodes1.get(last1).equals(nodes2.get(last2)) ) {
     155                    increment2 = -1;
     156                } else {
     157                    last2 = incrementBy(start2, 1, nodes2.size(), isRing2);
     158                    if (last2 >= 0 && nodes1.get(last1).equals(nodes2.get(last2)) ) {
     159                        increment2 = 1;
     160                    }
     161                }
     162            }
     163            log("last1=" + last1 + " last2=" + last2 + " increment2=" + increment2);
     164            if (increment2 != 0) {
     165                // find the first nodes
     166                boolean reachedEnd = false;
     167                while(!reachedEnd) {
     168                    int newLast1 = incrementBy(last1, 1, nodes1.size(), isRing1);
     169                    int newLast2 = incrementBy(last2, increment2, nodes2.size(), isRing2);
     170                    if (newLast1 < 0 || newLast2 < 0 || !nodes1.get(newLast1).equals(nodes2.get(newLast2)) ) {
     171                        reachedEnd = true;
     172                    } else {
     173                        last1 = newLast1;
     174                        last2 = newLast2;
     175                    }
     176                }
     177                log("last1=" + last1 + " last2=" + last2);
     178                if (increment2 < 0) {
     179                    int tmp = start2;
     180                    start2 = last2;
     181                    last2 = tmp;
     182                }
     183                return new Node[] {nodes1.get(start1), nodes1.get(last1), nodes2.get(start2), nodes2.get(last2)};
     184            } else {
     185                pos = last1;
     186                while(pos != firstPos && pos >= 0 && !nodes2.contains(nodes1.get(pos)) ) {
     187                    pos = incrementBy(pos, 1, nodes1.size(), isRing1);
     188                }
     189                if (pos < 0 || pos == firstPos || !nodes2.contains(nodes1.get(pos)) ) {
     190                    collideFound = true;
     191                }
     192            }
     193        }
    133194        return null;
    134         }
    135         pos = pos == nodes1.size() - 1 ? 0 : pos + 1;
    136     }
    137     int firstPos = isRing1 ? pos : nodes1.size();
    138     while( !collideFound ) {
    139         log("pos=" + pos);
    140         int start1 = pos;
    141         int start2 = nodes2.indexOf(nodes1.get(start1));
    142         int last1 = incrementBy(start1, 1, nodes1.size(), isRing1);
    143         int last2 = start2;
    144         int increment2 = 0;
    145         if( last1 >= 0 ) {
    146         last2 = incrementBy(start2, -1, nodes2.size(), isRing2);
    147         if( last2 >= 0 && nodes1.get(last1).equals(nodes2.get(last2)) )
    148             increment2 = -1;
    149         else {
    150             last2 = incrementBy(start2, 1, nodes2.size(), isRing2);
    151             if( last2 >= 0 && nodes1.get(last1).equals(nodes2.get(last2)) )
    152             increment2 = 1;
    153         }
    154         }
    155         log("last1=" + last1 + " last2=" + last2 + " increment2=" + increment2);
    156         if( increment2 != 0 ) {
    157         // find the first nodes
    158         boolean reachedEnd = false;
    159         while( !reachedEnd ) {
    160             int newLast1 = incrementBy(last1, 1, nodes1.size(), isRing1);
    161             int newLast2 = incrementBy(last2, increment2, nodes2.size(), isRing2);
    162             if( newLast1 < 0 || newLast2 < 0 || !nodes1.get(newLast1).equals(nodes2.get(newLast2)) )
    163             reachedEnd = true;
    164             else {
    165             last1 = newLast1;
    166             last2 = newLast2;
    167             }
    168         }
    169         log("last1=" + last1 + " last2=" + last2);
    170         if( increment2 < 0 ) {
    171             int tmp = start2;
    172             start2 = last2;
    173             last2 = tmp;
    174         }
    175         return new Node[] {nodes1.get(start1), nodes1.get(last1), nodes2.get(start2), nodes2.get(last2)};
    176         } else {
    177         pos = last1;
    178         while( pos != firstPos && pos >= 0 && !nodes2.contains(nodes1.get(pos)) )
    179             pos = incrementBy(pos, 1, nodes1.size(), isRing1);
    180         if( pos < 0 || pos == firstPos || !nodes2.contains(nodes1.get(pos)) )
    181             collideFound = true;
    182         }
    183     }
    184     return null;
    185     }
    186    
    187     private static int incrementBy( int value, int increment, int limit1, boolean isRing ) {
    188     int result = value + increment;
    189     if( result < 0 )
    190         return isRing ? result + limit1 : -1;
    191     else if( result >= limit1 )
    192         return isRing ? result - limit1 : -1;
    193     else
    194         return result;
    195     }
    196    
    197     private boolean areSegmentsEqual( RingSegment seg1, RingSegment seg2 ) {
    198     List<Node> nodes1 = seg1.getNodes();
    199     List<Node> nodes2 = seg2.getNodes();
    200     int size = nodes1.size();
    201     if( size != nodes2.size() )
    202         return false;
    203     boolean reverse = size > 1 && !nodes1.get(0).equals(nodes2.get(0));
    204     for( int i = 0; i < size; i++ )
    205         if( !nodes1.get(i).equals(nodes2.get(reverse ? size-1-i : i)) )
    206         return false;
    207     return true;
     195    }
     196
     197    private static int incrementBy(int value, int increment, int limit1, boolean isRing) {
     198        int result = value + increment;
     199        if (result < 0 )
     200            return isRing ? result + limit1 : -1;
     201        else if (result >= limit1 )
     202            return isRing ? result - limit1 : -1;
     203        else
     204            return result;
     205    }
     206
     207    private boolean areSegmentsEqual(RingSegment seg1, RingSegment seg2) {
     208        List<Node> nodes1 = seg1.getNodes();
     209        List<Node> nodes2 = seg2.getNodes();
     210        int size = nodes1.size();
     211        if (size != nodes2.size() )
     212            return false;
     213        boolean reverse = size > 1 && !nodes1.get(0).equals(nodes2.get(0));
     214        for (int i = 0; i < size; i++ )
     215            if (!nodes1.get(i).equals(nodes2.get(reverse ? size-1-i : i)) )
     216                return false;
     217        return true;
    208218    }
    209219
     
    212222     * @return The segment between nodes.
    213223     */
    214     private RingSegment splitRingAt( int segmentIndex, Node n1, Node n2 ) {
    215     if( n1.equals(n2) )
    216         throw new IllegalArgumentException("Both nodes are equal, id=" + n1.getUniqueId());
    217     RingSegment segment = segments.get(segmentIndex);
    218     boolean isRing = segment.isRing();
    219     log("Split segment " + segment + " at nodes " + n1.getUniqueId() + " and " + n2.getUniqueId());
    220     boolean reversed = segment.getNodes().indexOf(n2) < segment.getNodes().indexOf(n1);
    221     if( reversed && !isRing ) {
    222         // order nodes
    223         Node tmp = n1;
    224         n1 = n2;
    225         n2 = tmp;
    226     }
    227     RingSegment secondPart = isRing ? segment.split(n1, n2) : segment.split(n1);
    228     // if secondPart == null, then n1 == firstNode
    229     RingSegment thirdPart = isRing ? null : secondPart == null ? segment.split(n2) : secondPart.split(n2);
    230     // if secondPart == null, then thirdPart is between n1 and n2
    231     // otherwise, thirdPart is between n2 and lastNode
    232     // if thirdPart == null, then n2 == lastNode
    233     int pos = segmentIndex + 1;
    234     if( secondPart != null )
    235         segments.add(pos++, secondPart);
    236     if( thirdPart != null )
    237         segments.add(pos++, thirdPart);
    238     return isRing || secondPart == null ? segment : secondPart;
     224    private RingSegment splitRingAt(int segmentIndex, Node n1, Node n2) {
     225        if (n1.equals(n2) )
     226            throw new IllegalArgumentException("Both nodes are equal, id=" + n1.getUniqueId());
     227        RingSegment segment = segments.get(segmentIndex);
     228        boolean isRing = segment.isRing();
     229        log("Split segment " + segment + " at nodes " + n1.getUniqueId() + " and " + n2.getUniqueId());
     230        boolean reversed = segment.getNodes().indexOf(n2) < segment.getNodes().indexOf(n1);
     231        if (reversed && !isRing) {
     232            // order nodes
     233            Node tmp = n1;
     234            n1 = n2;
     235            n2 = tmp;
     236        }
     237        RingSegment secondPart = isRing ? segment.split(n1, n2) : segment.split(n1);
     238        // if secondPart == null, then n1 == firstNode
     239        RingSegment thirdPart = isRing ? null : secondPart == null ? segment.split(n2) : secondPart.split(n2);
     240        // if secondPart == null, then thirdPart is between n1 and n2
     241        // otherwise, thirdPart is between n2 and lastNode
     242        // if thirdPart == null, then n2 == lastNode
     243        int pos = segmentIndex + 1;
     244        if (secondPart != null ) {
     245            segments.add(pos++, secondPart);
     246        }
     247        if (thirdPart != null ) {
     248            segments.add(pos++, thirdPart);
     249        }
     250        return isRing || secondPart == null ? segment : secondPart;
    239251    }
    240252
     
    242254     * Tries to arrange segments in order for each ring to have at least one.
    243255     * Also, sets source way for all rings.
    244      * 
     256     *
    245257     * If this method is not called, do not forget to call {@link #putSourceWayFirst()} for all rings.
    246258     */
    247     public static void redistributeSegments( List<TheRing> rings ) {
    248     // build segments map
    249     Map<RingSegment, TheRing> segmentMap = new HashMap<>();
    250     for( TheRing ring : rings )
    251         for( RingSegment seg : ring.segments )
    252         if( !seg.isReference() )
    253             segmentMap.put(seg, ring);
    254 
    255     // rearrange references
    256     for( int i = 0; i < rings.size(); i++ ) {
    257         TheRing ring = rings.get(i);
    258         if( ring.countNonReferenceSegments() == 0 ) {
    259         // need to find one non-reference segment
    260         for( RingSegment seg : ring.segments ) {
    261             TheRing otherRing = segmentMap.get(seg.references);
    262             if( otherRing.countNonReferenceSegments() > 1 ) {
    263             // we could check for >0, but it is prone to deadlocking
    264             seg.swapReference();
    265             }
    266         }
    267         }
    268     }
    269 
    270     // initializing source way for each ring
    271     for( TheRing ring : rings )
    272         ring.putSourceWayFirst();
     259    public static void redistributeSegments(List<TheRing> rings) {
     260        // build segments map
     261        Map<RingSegment, TheRing> segmentMap = new HashMap<>();
     262        for (TheRing ring : rings ) {
     263            for (RingSegment seg : ring.segments )
     264                if (!seg.isReference() ) {
     265                    segmentMap.put(seg, ring);
     266                }
     267        }
     268
     269        // rearrange references
     270        for (int i = 0; i < rings.size(); i++) {
     271            TheRing ring = rings.get(i);
     272            if (ring.countNonReferenceSegments() == 0) {
     273                // need to find one non-reference segment
     274                for (RingSegment seg : ring.segments) {
     275                    TheRing otherRing = segmentMap.get(seg.references);
     276                    if (otherRing.countNonReferenceSegments() > 1) {
     277                        // we could check for >0, but it is prone to deadlocking
     278                        seg.swapReference();
     279                    }
     280                }
     281            }
     282        }
     283
     284        // initializing source way for each ring
     285        for (TheRing ring : rings ) {
     286            ring.putSourceWayFirst();
     287        }
    273288    }
    274289
    275290    private int countNonReferenceSegments() {
    276     int count = 0;
    277     for( RingSegment seg : segments )
    278         if( !seg.isReference() )
    279         count++;
    280     return count;
     291        int count = 0;
     292        for (RingSegment seg : segments )
     293            if (!seg.isReference() ) {
     294                count++;
     295            }
     296        return count;
    281297    }
    282298
    283299    public void putSourceWayFirst() {
    284     for( RingSegment seg : segments ) {
    285         if( !seg.isReference() ) {
    286         seg.overrideWay(source);
    287         return;
    288         }
    289     }
    290     }
    291    
     300        for (RingSegment seg : segments) {
     301            if (!seg.isReference()) {
     302                seg.overrideWay(source);
     303                return;
     304            }
     305        }
     306    }
     307
    292308    public List<Command> getCommands() {
    293     return getCommands(true, null);
    294     }
    295    
    296     public List<Command> getCommands( Map<Relation, Relation> relationChangeMap ) {
    297     return getCommands(true, relationChangeMap);
    298     }
    299    
     309        return getCommands(true, null);
     310    }
     311
     312    public List<Command> getCommands(Map<Relation, Relation> relationChangeMap) {
     313        return getCommands(true, relationChangeMap);
     314    }
     315
    300316    /**
    301317     * Returns a list of commands to make a new relation and all newly created ways.
    302318     * The first way is copied from the source one, ChangeCommand is issued in this case.
    303319     */
    304     public List<Command> getCommands( boolean createMultipolygon, Map<Relation, Relation> relationChangeMap ) {
    305     Way sourceCopy = new Way(source);
    306     if( createMultipolygon ) {
    307         Collection<String> linearTags = Main.pref.getCollection(PREF_MULTIPOLY + "lineartags", CreateMultipolygonAction.DEFAULT_LINEAR_TAGS);
    308         relation = new Relation();
    309         relation.put("type", "multipolygon");
    310         for( String key : sourceCopy.keySet() ) {
    311                 if( linearTags.contains(key) ) continue;
    312                 if( key.equals("natural") && sourceCopy.get("natural").equals("coastline") ) continue;
     320    public List<Command> getCommands(boolean createMultipolygon, Map<Relation, Relation> relationChangeMap) {
     321        Way sourceCopy = new Way(source);
     322        if (createMultipolygon) {
     323            Collection<String> linearTags = Main.pref.getCollection(PREF_MULTIPOLY + "lineartags", CreateMultipolygonAction.DEFAULT_LINEAR_TAGS);
     324            relation = new Relation();
     325            relation.put("type", "multipolygon");
     326            for (String key : sourceCopy.keySet()) {
     327                if (linearTags.contains(key) ) {
     328                    continue;
     329                }
     330                if (key.equals("natural") && sourceCopy.get("natural").equals("coastline") ) {
     331                    continue;
     332                }
    313333                relation.put(key, sourceCopy.get(key));
    314334                sourceCopy.remove(key);
    315         }
    316     }
    317 
    318     // build a map of referencing relations
    319     Map<Relation, Integer> referencingRelations = new HashMap<>();
    320     List<Command> relationCommands = new ArrayList<>();
    321     for( OsmPrimitive p : source.getReferrers() ) {
    322         if( p instanceof Relation ) {
    323         Relation rel = null;
    324         if( relationChangeMap != null ) {
    325             if( relationChangeMap.containsKey((Relation)p) )
    326             rel = relationChangeMap.get((Relation)p);
    327             else {
    328             rel = new Relation((Relation)p);
    329             relationChangeMap.put((Relation)p, rel);
    330             }
    331         } else {           
    332             rel = new Relation((Relation)p);
    333             relationCommands.add(new ChangeCommand((Relation)p, rel));
    334         }
    335         for( int i = 0; i < rel.getMembersCount(); i++ )
    336             if( rel.getMember(i).getMember().equals(source) )
    337             referencingRelations.put(rel, Integer.valueOf(i));
    338         }
    339     }
    340     // todo: когда два кольца менÑ�ÑŽÑ‚ одно и то же отношение, в Ñ�пиÑ�ок команд добавлÑ�етÑ�Ñ�
    341     // изменение базового отношениÑ� на новое, а не предыдущего
    342     // поÑ�тому Ñ�охранÑ�етÑ�Ñ� только первое изменение
    343 
    344     List<Command> commands = new ArrayList<>();
    345     boolean foundOwnWay = false;
    346     for( RingSegment seg : segments ) {
    347         boolean needAdding = !seg.isWayConstructed();
    348         Way w = seg.constructWay(seg.isReference() ? null : sourceCopy);
    349         if( needAdding )
    350         commands.add(new AddCommand(w));
    351         if( w.equals(source) ) {
    352         if( createMultipolygon || !seg.getWayNodes().equals(source.getNodes()) ) {
    353             sourceCopy.setNodes(seg.getWayNodes());
    354             commands.add(new ChangeCommand(source, sourceCopy));
    355         }
    356         foundOwnWay = true;
    357         } else {
    358         for( Relation rel : referencingRelations.keySet() ) {
    359             int relIndex = referencingRelations.get(rel);
    360             rel.addMember(new RelationMember(rel.getMember(relIndex).getRole(), w));
    361         }
    362         }
    363         if( createMultipolygon )
    364         relation.addMember(new RelationMember("outer", w));
    365     }
    366     if( !foundOwnWay )
    367         commands.add(new DeleteCommand(source));
    368     commands.addAll(relationCommands);
    369     if( createMultipolygon )
    370         commands.add(new AddCommand(relation));
    371     return commands;
    372     }
    373    
    374     public static void updateCommandsWithRelations( List<Command> commands, Map<Relation, Relation> relationCache ) {
    375     for( Relation src : relationCache.keySet() )
    376         commands.add(new ChangeCommand(src, relationCache.get(src)));
     335            }
     336        }
     337
     338        // build a map of referencing relations
     339        Map<Relation, Integer> referencingRelations = new HashMap<>();
     340        List<Command> relationCommands = new ArrayList<>();
     341        for (OsmPrimitive p : source.getReferrers()) {
     342            if (p instanceof Relation) {
     343                Relation rel = null;
     344                if (relationChangeMap != null) {
     345                    if (relationChangeMap.containsKey(p) ) {
     346                        rel = relationChangeMap.get(p);
     347                    } else {
     348                        rel = new Relation((Relation)p);
     349                        relationChangeMap.put((Relation)p, rel);
     350                    }
     351                } else {
     352                    rel = new Relation((Relation)p);
     353                    relationCommands.add(new ChangeCommand(p, rel));
     354                }
     355                for (int i = 0; i < rel.getMembersCount(); i++ )
     356                    if (rel.getMember(i).getMember().equals(source) ) {
     357                        referencingRelations.put(rel, Integer.valueOf(i));
     358                    }
     359            }
     360        }
     361        // todo: когда два кольца менÑ�ÑŽÑ‚ одно и то же отношение, в Ñ�пиÑ�ок команд добавлÑ�етÑ�Ñ�
     362        // изменение базового отношениÑ� на новое, а не предыдущего
     363        // поÑ�тому Ñ�охранÑ�етÑ�Ñ� только первое изменение
     364
     365        List<Command> commands = new ArrayList<>();
     366        boolean foundOwnWay = false;
     367        for (RingSegment seg : segments) {
     368            boolean needAdding = !seg.isWayConstructed();
     369            Way w = seg.constructWay(seg.isReference() ? null : sourceCopy);
     370            if (needAdding ) {
     371                commands.add(new AddCommand(w));
     372            }
     373            if (w.equals(source)) {
     374                if (createMultipolygon || !seg.getWayNodes().equals(source.getNodes())) {
     375                    sourceCopy.setNodes(seg.getWayNodes());
     376                    commands.add(new ChangeCommand(source, sourceCopy));
     377                }
     378                foundOwnWay = true;
     379            } else {
     380                for (Relation rel : referencingRelations.keySet()) {
     381                    int relIndex = referencingRelations.get(rel);
     382                    rel.addMember(new RelationMember(rel.getMember(relIndex).getRole(), w));
     383                }
     384            }
     385            if (createMultipolygon ) {
     386                relation.addMember(new RelationMember("outer", w));
     387            }
     388        }
     389        if (!foundOwnWay ) {
     390            commands.add(new DeleteCommand(source));
     391        }
     392        commands.addAll(relationCommands);
     393        if (createMultipolygon ) {
     394            commands.add(new AddCommand(relation));
     395        }
     396        return commands;
     397    }
     398
     399    public static void updateCommandsWithRelations(List<Command> commands, Map<Relation, Relation> relationCache) {
     400        for (Relation src : relationCache.keySet() ) {
     401            commands.add(new ChangeCommand(src, relationCache.get(src)));
     402        }
    377403    }
    378404
     
    381407     */
    382408    public Relation getRelation() {
    383     return relation;
     409        return relation;
    384410    }
    385411
    386412    @Override
    387413    public String toString() {
    388     StringBuilder sb = new StringBuilder("TheRing@");
    389     sb.append(this.hashCode()).append('[').append("wayId: ").append(source == null ? "null" : source.getUniqueId()).append("; segments: ");
    390     if( segments.isEmpty() )
    391         sb.append("empty");
    392     else {
    393         sb.append(segments.get(0));
    394         for( int i = 1; i < segments.size(); i++ )
    395         sb.append(", ").append(segments.get(i));
    396     }
    397     return sb.append(']').toString();
     414        StringBuilder sb = new StringBuilder("TheRing@");
     415        sb.append(this.hashCode()).append('[').append("wayId: ").append(source == null ? "null" : source.getUniqueId()).append("; segments: ");
     416        if (segments.isEmpty() ) {
     417            sb.append("empty");
     418        } else {
     419            sb.append(segments.get(0));
     420            for (int i = 1; i < segments.size(); i++ ) {
     421                sb.append(", ").append(segments.get(i));
     422            }
     423        }
     424        return sb.append(']').toString();
    398425    }
    399426
     
    401428     * Appends "append" to "base" so the closed polygon forms.
    402429     */
    403     /*private static void closePolygon( List<Node> base, List<Node> append ) {
    404     if( append.get(0).equals(base.get(0)) && append.get(append.size() - 1).equals(base.get(base.size() - 1)) ) {
     430    /*private static void closePolygon(List<Node> base, List<Node> append) {
     431    if (append.get(0).equals(base.get(0)) && append.get(append.size() - 1).equals(base.get(base.size() - 1))) {
    405432        List<Node> ap2 = new ArrayList<Node>(append);
    406433        Collections.reverse(ap2);
     
    414441     * Checks if a middle point between two nodes is inside a polygon. Useful to check if the way is inside.
    415442     */
    416     /*private static boolean segmentInsidePolygon( Node n1, Node n2, List<Node> polygon ) {
     443    /*private static boolean segmentInsidePolygon(Node n1, Node n2, List<Node> polygon) {
    417444    EastNorth en1 = n1.getEastNorth();
    418445    EastNorth en2 = n2.getEastNorth();
     
    420447    return Geometry.nodeInsidePolygon(testNode, polygon);
    421448    }*/
    422    
    423     private static void log( String s ) {
    424 //    System.out.println(s);
    425     }
    426    
     449
     450    private static void log(String s) {
     451        //    System.out.println(s);
     452    }
     453
    427454    private static class RingSegment {
    428     private List<Node> nodes;
    429     private RingSegment references;
    430     private Way resultingWay = null;
    431     private boolean wasTemplateApplied = false;
    432     private boolean isRing;
    433 
    434     /*private RingSegment() {
     455        private List<Node> nodes;
     456        private RingSegment references;
     457        private Way resultingWay = null;
     458        private boolean wasTemplateApplied = false;
     459        private boolean isRing;
     460
     461        /*private RingSegment() {
    435462    }*/
    436463
    437     public RingSegment( Way w ) {
    438         this(w.getNodes());
    439     }
    440 
    441     public RingSegment( List<Node> nodes ) {
    442         this.nodes = nodes;
    443         isRing = nodes.size() > 1 && nodes.get(0).equals(nodes.get(nodes.size() - 1));
    444         if( isRing )
    445         nodes.remove(nodes.size() - 1);
    446         references = null;
    447     }
    448 
    449     /*public RingSegment( RingSegment ref ) {
     464        public RingSegment(Way w) {
     465            this(w.getNodes());
     466        }
     467
     468        public RingSegment(List<Node> nodes) {
     469            this.nodes = nodes;
     470            isRing = nodes.size() > 1 && nodes.get(0).equals(nodes.get(nodes.size() - 1));
     471            if (isRing ) {
     472                nodes.remove(nodes.size() - 1);
     473            }
     474            references = null;
     475        }
     476
     477        /*public RingSegment(RingSegment ref) {
    450478        this.nodes = null;
    451479        this.references = ref;
    452480    }*/
    453481
    454     /**
    455      * Splits this segment at node n. Retains nodes 0..n and moves
    456      * nodes n..N to a separate segment that is returned.
    457      * @param n node at which to split.
    458      * @return new segment, {@code null} if splitting is unnecessary.
    459      */
    460     public RingSegment split( Node n ) {
    461         if( nodes == null )
    462         throw new IllegalArgumentException("Cannot split segment: it is a reference");
    463         int pos = nodes.indexOf(n);
    464         if( pos <= 0 || pos >= nodes.size() - 1 )
    465         return null;
    466         List<Node> newNodes = new ArrayList<>(nodes.subList(pos, nodes.size()));
    467         nodes.subList(pos + 1, nodes.size()).clear();
    468         return new RingSegment(newNodes);
    469     }
    470 
    471     /**
    472      * Split this segment as a way at two nodes. If one of them is null or at the end,
    473      * split as an arc. Note: order of nodes is important.
    474      * @return A new segment from n2 to n1.
    475      */
    476     public RingSegment split( Node n1, Node n2 ) {
    477         if( nodes == null )
    478         throw new IllegalArgumentException("Cannot split segment: it is a reference");
    479         if( !isRing ) {
    480         if( n1 == null || nodes.get(0).equals(n1) || nodes.get(nodes.size() - 1).equals(n1) )
    481             return split(n2);
    482         if( n2 == null || nodes.get(0).equals(n2) || nodes.get(nodes.size() - 1).equals(n2) )
    483             return split(n1);
    484         throw new IllegalArgumentException("Split for two nodes is called for not-ring: " + this);
    485         }
    486         int pos1 = nodes.indexOf(n1);
    487         int pos2 = nodes.indexOf(n2);
    488         if( pos1 == pos2 )
    489         return null;
    490 
    491         List<Node> newNodes = new ArrayList<>();
    492         if( pos2 > pos1 ) {
    493         newNodes.addAll(nodes.subList(pos2, nodes.size()));
    494         newNodes.addAll(nodes.subList(0, pos1 + 1));
    495         if( pos2 + 1 < nodes.size() )
    496             nodes.subList(pos2 + 1, nodes.size()).clear();
    497         if( pos1 > 0 )
    498             nodes.subList(0, pos1).clear();
    499         } else {
    500         newNodes.addAll(nodes.subList(pos2, pos1 + 1));
    501         nodes.addAll(new ArrayList<>(nodes.subList(0, pos2 + 1)));
    502         nodes.subList(0, pos1).clear();
    503         }
    504         isRing = false;
    505         return new RingSegment(newNodes);
    506     }
    507 
    508     public List<Node> getNodes() {
    509         return nodes == null ? references.nodes : nodes;
    510     }
    511 
    512     public List<Node> getWayNodes() {
    513         if( nodes == null )
    514         throw new IllegalArgumentException("Won't give you wayNodes: it is a reference");
    515         List<Node> wayNodes = new ArrayList<>(nodes);
    516         if( isRing )
    517         wayNodes.add(wayNodes.get(0));
    518         return wayNodes;
    519     }
    520 
    521     public boolean isReference() {
    522         return nodes == null;
    523     }
    524 
    525     public boolean isRing() {
    526         return isRing;
    527     }
    528 
    529     public void makeReference( RingSegment segment ) {
    530         log(this + " was made a reference to " + segment);
    531         this.nodes = null;
    532         this.references = segment;
    533     }
    534 
    535     public void swapReference() {
    536         this.nodes = references.nodes;
    537         references.nodes = null;
    538         references.references = this;
    539         this.references = null;
    540     }
    541 
    542     public boolean isWayConstructed() {
    543         return isReference() ? references.isWayConstructed() : resultingWay != null;
    544     }
    545 
    546     public Way constructWay( Way template ) {
    547         if( isReference() )
    548         return references.constructWay(template);
    549         if( resultingWay == null ) {
    550         resultingWay = new Way();
    551         resultingWay.setNodes(getWayNodes());
    552         }
    553         if( template != null && !wasTemplateApplied ) {
    554         resultingWay.setKeys(template.getKeys());
    555         wasTemplateApplied = true;
    556         }
    557         return resultingWay;
    558     }
    559 
    560     public void overrideWay( Way source ) {
    561         if( isReference() )
    562         references.overrideWay(source);
    563         else {
    564         resultingWay = source;
    565         wasTemplateApplied = true;
    566         }
    567     }
    568 
    569     /**
    570      * Compares two segments with respect to referencing.
    571      * @return true if ways are equals, or one references another.
    572      */
    573     /*public boolean isReferencingEqual( RingSegment other ) {
     482        /**
     483         * Splits this segment at node n. Retains nodes 0..n and moves
     484         * nodes n..N to a separate segment that is returned.
     485         * @param n node at which to split.
     486         * @return new segment, {@code null} if splitting is unnecessary.
     487         */
     488        public RingSegment split(Node n) {
     489            if (nodes == null )
     490                throw new IllegalArgumentException("Cannot split segment: it is a reference");
     491            int pos = nodes.indexOf(n);
     492            if (pos <= 0 || pos >= nodes.size() - 1 )
     493                return null;
     494            List<Node> newNodes = new ArrayList<>(nodes.subList(pos, nodes.size()));
     495            nodes.subList(pos + 1, nodes.size()).clear();
     496            return new RingSegment(newNodes);
     497        }
     498
     499        /**
     500         * Split this segment as a way at two nodes. If one of them is null or at the end,
     501         * split as an arc. Note: order of nodes is important.
     502         * @return A new segment from n2 to n1.
     503         */
     504        public RingSegment split(Node n1, Node n2) {
     505            if (nodes == null )
     506                throw new IllegalArgumentException("Cannot split segment: it is a reference");
     507            if (!isRing) {
     508                if (n1 == null || nodes.get(0).equals(n1) || nodes.get(nodes.size() - 1).equals(n1) )
     509                    return split(n2);
     510                if (n2 == null || nodes.get(0).equals(n2) || nodes.get(nodes.size() - 1).equals(n2) )
     511                    return split(n1);
     512                throw new IllegalArgumentException("Split for two nodes is called for not-ring: " + this);
     513            }
     514            int pos1 = nodes.indexOf(n1);
     515            int pos2 = nodes.indexOf(n2);
     516            if (pos1 == pos2 )
     517                return null;
     518
     519            List<Node> newNodes = new ArrayList<>();
     520            if (pos2 > pos1) {
     521                newNodes.addAll(nodes.subList(pos2, nodes.size()));
     522                newNodes.addAll(nodes.subList(0, pos1 + 1));
     523                if (pos2 + 1 < nodes.size() ) {
     524                    nodes.subList(pos2 + 1, nodes.size()).clear();
     525                }
     526                if (pos1 > 0 ) {
     527                    nodes.subList(0, pos1).clear();
     528                }
     529            } else {
     530                newNodes.addAll(nodes.subList(pos2, pos1 + 1));
     531                nodes.addAll(new ArrayList<>(nodes.subList(0, pos2 + 1)));
     532                nodes.subList(0, pos1).clear();
     533            }
     534            isRing = false;
     535            return new RingSegment(newNodes);
     536        }
     537
     538        public List<Node> getNodes() {
     539            return nodes == null ? references.nodes : nodes;
     540        }
     541
     542        public List<Node> getWayNodes() {
     543            if (nodes == null )
     544                throw new IllegalArgumentException("Won't give you wayNodes: it is a reference");
     545            List<Node> wayNodes = new ArrayList<>(nodes);
     546            if (isRing ) {
     547                wayNodes.add(wayNodes.get(0));
     548            }
     549            return wayNodes;
     550        }
     551
     552        public boolean isReference() {
     553            return nodes == null;
     554        }
     555
     556        public boolean isRing() {
     557            return isRing;
     558        }
     559
     560        public void makeReference(RingSegment segment) {
     561            log(this + " was made a reference to " + segment);
     562            this.nodes = null;
     563            this.references = segment;
     564        }
     565
     566        public void swapReference() {
     567            this.nodes = references.nodes;
     568            references.nodes = null;
     569            references.references = this;
     570            this.references = null;
     571        }
     572
     573        public boolean isWayConstructed() {
     574            return isReference() ? references.isWayConstructed() : resultingWay != null;
     575        }
     576
     577        public Way constructWay(Way template) {
     578            if (isReference() )
     579                return references.constructWay(template);
     580            if (resultingWay == null) {
     581                resultingWay = new Way();
     582                resultingWay.setNodes(getWayNodes());
     583            }
     584            if (template != null && !wasTemplateApplied) {
     585                resultingWay.setKeys(template.getKeys());
     586                wasTemplateApplied = true;
     587            }
     588            return resultingWay;
     589        }
     590
     591        public void overrideWay(Way source) {
     592            if (isReference() ) {
     593                references.overrideWay(source);
     594            } else {
     595                resultingWay = source;
     596                wasTemplateApplied = true;
     597            }
     598        }
     599
     600        /**
     601         * Compares two segments with respect to referencing.
     602         * @return true if ways are equals, or one references another.
     603         */
     604        /*public boolean isReferencingEqual(RingSegment other) {
    574605        return this.equals(other) || (other.isReference() && other.references == this) || (isReference() && references == other);
    575606    }*/
    576607
    577     @Override
    578     public String toString() {
    579         StringBuilder sb = new StringBuilder("RingSegment@");
    580         sb.append(this.hashCode()).append('[');
    581         if( isReference() )
    582         sb.append("references ").append(references.hashCode());
    583         else if( nodes.isEmpty() )
    584         sb.append("empty");
    585         else {
    586         if( isRing )
    587             sb.append("ring:");
    588         sb.append(nodes.get(0).getUniqueId());
    589         for( int i = 1; i < nodes.size(); i++ )
    590             sb.append(',').append(nodes.get(i).getUniqueId());
    591         }
    592         return sb.append(']').toString();
    593     }
     608        @Override
     609        public String toString() {
     610            StringBuilder sb = new StringBuilder("RingSegment@");
     611            sb.append(this.hashCode()).append('[');
     612            if (isReference() ) {
     613                sb.append("references ").append(references.hashCode());
     614            } else if (nodes.isEmpty() ) {
     615                sb.append("empty");
     616            } else {
     617                if (isRing ) {
     618                    sb.append("ring:");
     619                }
     620                sb.append(nodes.get(0).getUniqueId());
     621                for (int i = 1; i < nodes.size(); i++ ) {
     622                    sb.append(',').append(nodes.get(i).getUniqueId());
     623                }
     624            }
     625            return sb.append(']').toString();
     626        }
    594627    }
    595628}
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/relationfix/AssociatedStreetFixer.java

    r30738 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext.relationfix;
    23
     
    4647        // check that all street members have same name as relation (???)
    4748        String streetName = rel.get("name");
    48         if (streetName == null) streetName = "";
     49        if (streetName == null) {
     50            streetName = "";
     51        }
    4952        for (RelationMember m : rel.getMembers()) {
    5053            if ("street".equals(m.getRole()) && !streetName.equals(m.getWay().get("name"))) {
     
    101104        // fill relation name
    102105        Map<String, Integer> streetNames = new HashMap<>();
    103         for (RelationMember m : rel.getMembers())
     106        for (RelationMember m : rel.getMembers()) {
    104107            if ("street".equals(m.getRole()) && m.isWay()) {
    105108                String name = m.getWay().get("name");
    106                 if (name == null || name.isEmpty()) continue;
     109                if (name == null || name.isEmpty()) {
     110                    continue;
     111                }
    107112
    108113                Integer count = streetNames.get(name);
    109114
    110                 streetNames.put(name, count != null? count + 1 : 1);
     115                streetNames.put(name, count != null ? count + 1 : 1);
    111116            }
     117        }
    112118        String commonName = "";
    113119        Integer commonCount = 0;
     
    146152                commandList.add(new ChangeCommand(oldWay, newWay));
    147153            }
    148         */
     154         */
    149155        // return results
    150156        if (commandList.size() == 0)
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/relationfix/BoundaryFixer.java

    r30738 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext.relationfix;
    23
     
    3233    @Override
    3334    public boolean isRelationGood(Relation rel) {
    34         for( RelationMember m : rel.getMembers() ) {
     35        for (RelationMember m : rel.getMembers()) {
    3536            if (m.getType().equals(OsmPrimitiveType.RELATION) && !"subarea".equals(m.getRole())) {
    3637                setWarningMessage(tr("Relation without ''subarea'' role found"));
     
    6768    }
    6869
    69     private Relation fixBoundaryRoles( Relation source ) {
     70    private Relation fixBoundaryRoles(Relation source) {
    7071        Relation r = new Relation(source);
    7172        boolean fixed = false;
    72         for( int i = 0; i < r.getMembersCount(); i++ ) {
     73        for (int i = 0; i < r.getMembersCount(); i++) {
    7374            RelationMember m = r.getMember(i);
    7475            String role = null;
    75             if( m.isRelation() )
     76            if (m.isRelation()) {
    7677                role = "subarea";
    77             else if( m.isNode() ) {
    78                 Node n = (Node)m.getMember();
    79                 if( !n.isIncomplete() ) {
    80                     if( n.hasKey("place") ) {
     78            } else if (m.isNode()) {
     79                Node n = (Node) m.getMember();
     80                if (!n.isIncomplete()) {
     81                    if (n.hasKey("place")) {
    8182                        String place = n.get("place");
    8283                        if (place.equals("state") || place.equals("country") ||
     
    8687                            role = "admin_centre";
    8788                        }
    88                     } else
     89                    } else {
    8990                        role = "label";
     91                    }
    9092                }
    9193            }
    92             if( role != null && !role.equals(m.getRole()) ) {
     94            if (role != null && !role.equals(m.getRole())) {
    9395                r.setMember(i, new RelationMember(role, m.getMember()));
    9496                fixed = true;
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/relationfix/MultipolygonFixer.java

    r30738 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext.relationfix;
    23
     
    3031    }
    3132
    32 
    3333    @Override
    3434    public boolean isRelationGood(Relation rel) {
    35         for (RelationMember m : rel.getMembers())
     35        for (RelationMember m : rel.getMembers()) {
    3636            if (m.getType().equals(OsmPrimitiveType.WAY) && !("outer".equals(m.getRole()) || "inner".equals(m.getRole()))) {
    3737                setWarningMessage(tr("Way without ''inner'' or ''outer'' role found"));
    3838                return false;
    3939            }
     40        }
    4041        clearWarningMessage();
    4142        return true;
     
    4546    public Command fixRelation(Relation rel) {
    4647        Relation rr = fixMultipolygonRoles(rel);
    47         return rr != null? new ChangeCommand(rel, rr) : null;
     48        return rr != null ? new ChangeCommand(rel, rr) : null;
    4849    }
    4950
     
    5152     * Basically, created multipolygon from scratch, and if successful, replace roles with new ones.
    5253     */
    53     protected Relation fixMultipolygonRoles( Relation source ) {
     54    protected Relation fixMultipolygonRoles(Relation source) {
    5455        Collection<Way> ways = new ArrayList<>();
    55         for( OsmPrimitive p : source.getMemberPrimitives() )
    56             if( p instanceof Way )
    57                 ways.add((Way)p);
     56        for (OsmPrimitive p : source.getMemberPrimitives()) {
     57            if (p instanceof Way) {
     58                ways.add((Way) p);
     59            }
     60        }
    5861        MultipolygonBuilder mpc = new MultipolygonBuilder();
    5962        String error = mpc.makeFromWays(ways);
    60         if( error != null )
     63        if (error != null)
    6164            return null;
    6265
     
    6467        boolean fixed = false;
    6568        Set<Way> outerWays = new HashSet<>();
    66         for( MultipolygonBuilder.JoinedPolygon poly : mpc.outerWays )
    67             for( Way w : poly.ways )
     69        for (MultipolygonBuilder.JoinedPolygon poly : mpc.outerWays) {
     70            for (Way w : poly.ways) {
    6871                outerWays.add(w);
     72            }
     73        }
    6974        Set<Way> innerWays = new HashSet<>();
    70         for( MultipolygonBuilder.JoinedPolygon poly : mpc.innerWays )
    71             for( Way w : poly.ways )
     75        for (MultipolygonBuilder.JoinedPolygon poly : mpc.innerWays) {
     76            for (Way w : poly.ways) {
    7277                innerWays.add(w);
    73         for( int i = 0; i < r.getMembersCount(); i++ ) {
     78            }
     79        }
     80        for (int i = 0; i < r.getMembersCount(); i++) {
    7481            RelationMember m = r.getMember(i);
    75             if( m.isWay() ) {
     82            if (m.isWay()) {
    7683                String role = null;
    77                 if( outerWays.contains((Way)m.getMember()) )
     84                if (outerWays.contains(m.getMember())) {
    7885                    role = "outer";
    79                 else if( innerWays.contains((Way)m.getMember()) )
     86                } else if (innerWays.contains(m.getMember())) {
    8087                    role = "inner";
    81                 if( role != null && !role.equals(m.getRole()) ) {
     88                }
     89                if (role != null && !role.equals(m.getRole())) {
    8290                    r.setMember(i, new RelationMember(role, m.getMember()));
    8391                    fixed = true;
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/relationfix/NothingFixer.java

    r30738 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext.relationfix;
    23
     
    1213        super("");
    1314    }
     15
    1416    @Override
    1517    public boolean isFixerApplicable(Relation rel) {
    1618        return true;
    1719    }
     20
    1821    @Override
    1922    public boolean isRelationGood(Relation rel) {
     
    2528        return null;
    2629    }
    27 
    2830}
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/relationfix/PublicTransportFixer.java

    r30841 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext.relationfix;
     3
     4import static org.openstreetmap.josm.tools.I18n.tr;
    25
    36import org.openstreetmap.josm.command.ChangeCommand;
     
    69import org.openstreetmap.josm.data.osm.Relation;
    710import org.openstreetmap.josm.data.osm.RelationMember;
    8 import static org.openstreetmap.josm.tools.I18n.tr;
     11
    912import relcontext.actions.PublicTransportHelper;
    1013
     
    1821 */
    1922public class PublicTransportFixer extends RelationFixer {
    20        
     23
    2124    public PublicTransportFixer() {
    2225        super("route", "public_transport");
     
    3033    public boolean isRelationGood(Relation rel) {
    3134        for (RelationMember m : rel.getMembers()) {
    32             if (m.getType().equals(OsmPrimitiveType.NODE) 
     35            if (m.getType().equals(OsmPrimitiveType.NODE)
    3336                    && !(m.getRole().startsWith(PublicTransportHelper.STOP) || m.getRole().startsWith(PublicTransportHelper.PLATFORM))) {
    3437                setWarningMessage(tr("Node without ''stop'' or ''platform'' role found"));
     
    6265        return fixed ? new ChangeCommand(rel, r) : null;
    6366    }
    64    
     67
    6568    private Relation fixStopPlatformRole(Relation source) {
    6669        Relation r = new Relation(source);
    6770        boolean fixed = false;
    68         for( int i = 0; i < r.getMembersCount(); i++ ) {
     71        for (int i = 0; i < r.getMembersCount(); i++) {
    6972            RelationMember m = r.getMember(i);
    7073            String role = PublicTransportHelper.getRoleByMember(m);
     
    7578            }
    7679        }
    77         return fixed ? r : null;           
     80        return fixed ? r : null;
    7881    }
    7982}
  • applications/editors/josm/plugins/reltoolbox/src/relcontext/relationfix/RelationFixer.java

    r30738 r32395  
     1// License: GPL. For details, see LICENSE file.
    12package relcontext.relationfix;
    23
     
    2021    /**
    2122     * Construct new RelationFixer by a list of applicable types
    22      * @param types
     23     * @param types types
    2324     */
    2425    public RelationFixer(String... types) {
    2526        applicableTypes = new ArrayList<>();
    26         for(String type: types) {
     27        for (String type: types) {
    2728            applicableTypes.add(type);
    2829        }
     
    3334     * and then check desired relation properties.
    3435     * Note that this only verifies if current RelationFixer can be used to check and fix given relation
    35      * Deeper relation checking is at {@link isRelationGood}
     36     * Deeper relation checking is at {@link #isRelationGood}
    3637     *
    3738     * @param rel Relation to check
     
    4546
    4647        String type = rel.get("type");
    47         for(String oktype: applicableTypes)
     48        for (String oktype: applicableTypes) {
    4849            if (oktype.equals(type))
    4950                return true;
     51        }
    5052
    5153        return false;
     
    7375        this.sortAndFixAction = sortAndFixAction;
    7476    }
     77
    7578    protected void setWarningMessage(String text) {
    7679        if (text == null) {
     
    8083        }
    8184    }
     85
    8286    protected void clearWarningMessage() {
    8387        sortAndFixAction.putValue(Action.SHORT_DESCRIPTION, tr("Fix roles of the chosen relation members"));
    8488    }
    85 
    8689}
Note: See TracChangeset for help on using the changeset viewer.