Ignore:
Timestamp:
2009-01-01T18:28:53+01:00 (16 years ago)
Author:
stoecker
Message:

removed tab stop usage

Location:
applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator
Files:
26 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/ErrorTreeRenderer.java

    r9598 r12778  
    1616public class ErrorTreeRenderer extends DefaultTreeCellRenderer
    1717{
    18         /** Serializable ID */
    19         private static final long serialVersionUID = 5567632718124640198L;
     18    /** Serializable ID */
     19    private static final long serialVersionUID = 5567632718124640198L;
    2020
    21         @Override
    22         public Component getTreeCellRendererComponent(JTree tree, Object value,
    23                         boolean selected, boolean expanded, boolean leaf, int row,
    24                         boolean hasFocus)
    25         {
    26                 super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
    27                
    28                 DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
    29                 Object nodeInfo = node.getUserObject();
     21    @Override
     22    public Component getTreeCellRendererComponent(JTree tree, Object value,
     23            boolean selected, boolean expanded, boolean leaf, int row,
     24            boolean hasFocus)
     25    {
     26        super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
    3027
    31                 if (nodeInfo instanceof Severity)
    32                 {
    33                         Severity s = (Severity)nodeInfo;
    34                         setIcon(ImageProvider.get("data", s.getIcon()));
    35                 }
    36                 else if (nodeInfo instanceof TestError)
    37                 {
    38                         TestError error = (TestError)nodeInfo;
    39                         MultipleNameVisitor v = new MultipleNameVisitor();
    40                         v.visit(error.getPrimitives());
    41                         setText(v.getText());
    42                         setIcon(v.getIcon());
    43                 }
     28        DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
     29        Object nodeInfo = node.getUserObject();
    4430
    45                 return this;
    46         }
     31        if (nodeInfo instanceof Severity)
     32        {
     33            Severity s = (Severity)nodeInfo;
     34            setIcon(ImageProvider.get("data", s.getIcon()));
     35        }
     36        else if (nodeInfo instanceof TestError)
     37        {
     38            TestError error = (TestError)nodeInfo;
     39            MultipleNameVisitor v = new MultipleNameVisitor();
     40            v.visit(error.getPrimitives());
     41            setText(v.getText());
     42            setIcon(v.getIcon());
     43        }
     44
     45        return this;
     46    }
    4747}
  • applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/GridLayer.java

    r4844 r12778  
    2828public class GridLayer extends Layer
    2929{
    30         /**
    31         * Constructor
    32         * @param name
    33         */
    34         public GridLayer(String name)
     30    /**
     31    * Constructor
     32    * @param name
     33    */
     34    public GridLayer(String name)
    3535    {
    36                 super(name);
    37         }
     36        super(name);
     37    }
    3838
    39         /**
    40         * Return a static icon.
    41         */
    42         @Override public Icon getIcon() {
    43                 return ImageProvider.get("layer", "validator");
    44         }
     39    /**
     40    * Return a static icon.
     41    */
     42    @Override public Icon getIcon() {
     43        return ImageProvider.get("layer", "validator");
     44    }
    4545
    4646    /**
     
    5050    public void paint(final Graphics g, final MapView mv)
    5151    {
    52         if( !Main.pref.hasKey(PreferenceEditor.PREF_DEBUG + ".grid") )
    53                 return;
    54        
    55         int gridWidth = Integer.parseInt(Main.pref.get(PreferenceEditor.PREF_DEBUG + ".grid") );
    56         int width = mv.getWidth();
    57                 int height = mv.getHeight();
     52        if( !Main.pref.hasKey(PreferenceEditor.PREF_DEBUG + ".grid") )
     53            return;
     54       
     55        int gridWidth = Integer.parseInt(Main.pref.get(PreferenceEditor.PREF_DEBUG + ".grid") );
     56        int width = mv.getWidth();
     57        int height = mv.getHeight();
    5858
    59                 EastNorth origin = mv.getEastNorth(0, 0);
    60                 EastNorth border = mv.getEastNorth(width, height);
     59        EastNorth origin = mv.getEastNorth(0, 0);
     60        EastNorth border = mv.getEastNorth(width, height);
    6161
    62         if( border.east() * gridWidth > 50 )
    63                 return;
     62        if( border.east() * gridWidth > 50 )
     63            return;
    6464
    6565        g.setColor(Color.RED.darker().darker());
    66         HighlightCellVisitor visitor = new HighlightCellVisitor(g, mv, gridWidth);
    67         for(OsmPrimitive p : Main.ds.getSelected() )
    68                 p.visit(visitor);
     66        HighlightCellVisitor visitor = new HighlightCellVisitor(g, mv, gridWidth);
     67        for(OsmPrimitive p : Main.ds.getSelected() )
     68            p.visit(visitor);
    6969       
    7070        long x0 = (long)Math.floor(origin.east()  * gridWidth);
    71                 long x1 = (long)Math.floor(border.east()  * gridWidth);
     71        long x1 = (long)Math.floor(border.east()  * gridWidth);
    7272        long y0 = (long)Math.floor(origin.north() * gridWidth) + 1;
    7373        long y1 = (long)Math.floor(border.north() * gridWidth) + 1;       
     
    7777       
    7878        g.setColor(Color.RED.brighter().brighter());
    79         for( double x = x0; x <= x1; x++)
    80         {
    81                 Point point = mv.getPoint( new EastNorth(x/gridWidth, 0));
    82                         g.drawLine(point.x, 0, point.x, height);
    83         }
     79        for( double x = x0; x <= x1; x++)
     80        {
     81            Point point = mv.getPoint( new EastNorth(x/gridWidth, 0));
     82            g.drawLine(point.x, 0, point.x, height);
     83        }
    8484
    85         for( double y = y0; y <= y1; y++)
    86         {
    87                 Point point = mv.getPoint( new EastNorth(0, y/gridWidth));
    88                         g.drawLine(0, point.y, width, point.y);
    89         }
     85        for( double y = y0; y <= y1; y++)
     86        {
     87            Point point = mv.getPoint( new EastNorth(0, y/gridWidth));
     88            g.drawLine(0, point.y, width, point.y);
     89        }
    9090    }
    9191
    92         @Override
     92    @Override
    9393    public String getToolTipText()
    9494    {
    95                 return null;
    96         }
     95        return null;
     96    }
    9797
    98         @Override
    99         public void mergeFrom(Layer from) {}
     98    @Override
     99    public void mergeFrom(Layer from) {}
    100100
    101         @Override
    102         public boolean isMergable(Layer other) {
    103                 return false;
    104         }
     101    @Override
     102    public boolean isMergable(Layer other) {
     103        return false;
     104    }
    105105
    106         @Override
    107         public void visitBoundingBox(BoundingXYVisitor v) {}
     106    @Override
     107    public void visitBoundingBox(BoundingXYVisitor v) {}
    108108
    109         @Override
    110         public Object getInfoComponent()
     109    @Override
     110    public Object getInfoComponent()
    111111    {
    112             return getToolTipText();
    113         }
     112        return getToolTipText();
     113    }
    114114
    115         @Override
    116         public Component[] getMenuEntries()
     115    @Override
     116    public Component[] getMenuEntries()
    117117    {
    118118        return new Component[]{
     
    125125    }
    126126
    127         @Override public void destroy() { }
    128        
    129         /**
    130         * Visitor that highlights all cells the selected primitives go through
    131         */
    132         class HighlightCellVisitor implements Visitor
    133         {
    134                 /** The MapView */
    135                 private final MapView mv;
    136                 /** The graphics */
    137                 private final Graphics g;
    138                 /** The grid width */
    139                 private final int gridDetail;
    140                 /** The width of a cell */
    141                 private int cellWidth;
     127    @Override public void destroy() { }
     128   
     129    /**
     130    * Visitor that highlights all cells the selected primitives go through
     131    */
     132    class HighlightCellVisitor implements Visitor
     133    {
     134        /** The MapView */
     135        private final MapView mv;
     136        /** The graphics */
     137        private final Graphics g;
     138        /** The grid width */
     139        private final int gridDetail;
     140        /** The width of a cell */
     141        private int cellWidth;
    142142
    143                 /**
    144                 * Constructor
    145                 * @param g the graphics
    146                 * @param mv The MapView
    147                 * @param gridDetail The grid detail
    148                 */
    149                 public HighlightCellVisitor(final Graphics g, final MapView mv, int gridDetail)
    150                 {
    151                         this.g = g;
    152                         this.mv = mv;
    153                         this.gridDetail = gridDetail;
    154                        
    155                 Point p = mv.getPoint( new EastNorth(0, 0) );
    156                 Point p2 = mv.getPoint( new EastNorth(1d/gridDetail, 1d/gridDetail) );
    157                 cellWidth = Math.abs(p2.x - p.x);
    158                 }
     143        /**
     144        * Constructor
     145        * @param g the graphics
     146        * @param mv The MapView
     147        * @param gridDetail The grid detail
     148        */
     149        public HighlightCellVisitor(final Graphics g, final MapView mv, int gridDetail)
     150        {
     151            this.g = g;
     152            this.mv = mv;
     153            this.gridDetail = gridDetail;
     154           
     155            Point p = mv.getPoint( new EastNorth(0, 0) );
     156            Point p2 = mv.getPoint( new EastNorth(1d/gridDetail, 1d/gridDetail) );
     157            cellWidth = Math.abs(p2.x - p.x);
     158        }
    159159
    160                 public void visit(Node n)
    161                 {
    162                         double x = n.eastNorth.east() * gridDetail;
    163                 double y = n.eastNorth.north()* gridDetail + 1;
     160        public void visit(Node n)
     161        {
     162            double x = n.eastNorth.east() * gridDetail;
     163            double y = n.eastNorth.north()* gridDetail + 1;
    164164
    165                 drawCell( Math.floor(x), Math.floor(y) );
    166                 }
     165            drawCell( Math.floor(x), Math.floor(y) );
     166        }
    167167
    168                 public void visit(Way w)
    169                 {
    170                         Node lastN = null;
    171                         for (Node n : w.nodes) {
    172                                 if (lastN == null) {
    173                                         lastN = n;
    174                                         continue;
    175                                 }
    176                                 for (Point2D p : Util.getSegmentCells(lastN, n, gridDetail)) {
    177                                         drawCell( p.getX(), p.getY() );
    178                                 }
    179                                 lastN = n;
    180                         }
    181                 }
     168        public void visit(Way w)
     169        {
     170            Node lastN = null;
     171            for (Node n : w.nodes) {
     172                if (lastN == null) {
     173                    lastN = n;
     174                    continue;
     175                }
     176                for (Point2D p : Util.getSegmentCells(lastN, n, gridDetail)) {
     177                    drawCell( p.getX(), p.getY() );
     178                }
     179                lastN = n;
     180            }
     181        }
    182182
    183                 public void visit(Relation r) {}
    184                
    185                 /**
    186                 * Draws a solid cell at the (x,y) location
    187                 * @param x
    188                 * @param y
    189                 */
    190                 protected void drawCell(double x, double y)
    191                 {
    192                 Point p = mv.getPoint( new EastNorth(x/gridDetail, y/gridDetail) );
    193                         g.fillRect(p.x, p.y, cellWidth, cellWidth);
    194                 }
    195         }
     183        public void visit(Relation r) {}
     184       
     185        /**
     186        * Draws a solid cell at the (x,y) location
     187        * @param x
     188        * @param y
     189        */
     190        protected void drawCell(double x, double y)
     191        {
     192            Point p = mv.getPoint( new EastNorth(x/gridDetail, y/gridDetail) );
     193            g.fillRect(p.x, p.y, cellWidth, cellWidth);
     194        }
     195    }
    196196}
  • applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/PreferenceEditor.java

    r12777 r12778  
    2626public class PreferenceEditor implements PreferenceSetting
    2727{
    28         private OSMValidatorPlugin plugin;
     28    private OSMValidatorPlugin plugin;
    2929
    30         /** The preferences prefix */
    31         public static final String PREFIX = "validator";
     30    /** The preferences prefix */
     31    public static final String PREFIX = "validator";
    3232
    33         /** The preferences key for debug preferences */
    34         public static final String PREF_DEBUG = PREFIX + ".debug";
     33    /** The preferences key for debug preferences */
     34    public static final String PREF_DEBUG = PREFIX + ".debug";
    3535
    36         /** The preferences key for debug preferences */
    37         public static final String PREF_LAYER = PREFIX + ".layer";
     36    /** The preferences key for debug preferences */
     37    public static final String PREF_LAYER = PREFIX + ".layer";
    3838
    39         /** The preferences key for enabled tests */
    40         public static final String PREF_TESTS = PREFIX + ".tests";
     39    /** The preferences key for enabled tests */
     40    public static final String PREF_TESTS = PREFIX + ".tests";
    4141
    42         /** The preferences key for enabled tests */
    43         public static final String PREF_USE_IGNORE = PREFIX + ".ignore";
     42    /** The preferences key for enabled tests */
     43    public static final String PREF_USE_IGNORE = PREFIX + ".ignore";
    4444
    45         /** The preferences key for enabled tests before upload*/
    46         public static final String PREF_TESTS_BEFORE_UPLOAD = PREFIX + ".testsBeforeUpload";
     45    /** The preferences key for enabled tests before upload*/
     46    public static final String PREF_TESTS_BEFORE_UPLOAD = PREFIX + ".testsBeforeUpload";
    4747
    48         /**
    49         * The preferences key for enabling the permanent filtering
    50         * of the displayed errors in the tree regarding the current selection
    51         */
     48    /**
     49    * The preferences key for enabling the permanent filtering
     50    * of the displayed errors in the tree regarding the current selection
     51    */
    5252    public static final String PREF_FILTER_BY_SELECTION = PREFIX + ".selectionFilter";
    5353
    54         private JCheckBox prefUseIgnore;
    55         private JCheckBox prefUseLayer;
     54    private JCheckBox prefUseIgnore;
     55    private JCheckBox prefUseLayer;
    5656
    57         /** The list of all tests */
    58         private Collection<Test> allTests;
     57    /** The list of all tests */
     58    private Collection<Test> allTests;
    5959
    60         public PreferenceEditor(OSMValidatorPlugin plugin) {
    61                 this.plugin = plugin;
    62         }
     60    public PreferenceEditor(OSMValidatorPlugin plugin) {
     61        this.plugin = plugin;
     62    }
    6363
    64         public void addGui(PreferenceDialog gui)
    65         {
    66                 JPanel testPanel = new JPanel(new GridBagLayout());
    67                 testPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
     64    public void addGui(PreferenceDialog gui)
     65    {
     66        JPanel testPanel = new JPanel(new GridBagLayout());
     67        testPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
    6868
    69                 prefUseIgnore = new JCheckBox(tr("Use ignore list."), Main.pref.getBoolean(PREF_USE_IGNORE, true));
    70                 prefUseIgnore.setToolTipText(tr("Use the ignore list to suppress warnings."));
    71                 testPanel.add(prefUseIgnore, GBC.eol());
     69        prefUseIgnore = new JCheckBox(tr("Use ignore list."), Main.pref.getBoolean(PREF_USE_IGNORE, true));
     70        prefUseIgnore.setToolTipText(tr("Use the ignore list to suppress warnings."));
     71        testPanel.add(prefUseIgnore, GBC.eol());
    7272
    73                 prefUseLayer = new JCheckBox(tr("Use error layer."), Main.pref.getBoolean(PREF_LAYER, true));
    74                 prefUseLayer.setToolTipText(tr("Use the error layer to display problematic elements."));
    75                 testPanel.add(prefUseLayer, GBC.eol());
     73        prefUseLayer = new JCheckBox(tr("Use error layer."), Main.pref.getBoolean(PREF_LAYER, true));
     74        prefUseLayer.setToolTipText(tr("Use the error layer to display problematic elements."));
     75        testPanel.add(prefUseLayer, GBC.eol());
    7676
    77                 GBC a = GBC.eol().insets(-5,0,0,0);
    78                 a.anchor = GBC.EAST;
    79                 testPanel.add( new JLabel(tr("On demand")), GBC.std() );
    80                 testPanel.add( new JLabel(tr("On upload")), a );
     77        GBC a = GBC.eol().insets(-5,0,0,0);
     78        a.anchor = GBC.EAST;
     79        testPanel.add( new JLabel(tr("On demand")), GBC.std() );
     80        testPanel.add( new JLabel(tr("On upload")), a );
    8181
    82                 allTests = OSMValidatorPlugin.getTests();
    83                 for(Test test: allTests)
    84                 {
    85                         test.addGui(testPanel);
    86                 }
     82        allTests = OSMValidatorPlugin.getTests();
     83        for(Test test: allTests)
     84        {
     85            test.addGui(testPanel);
     86        }
    8787
    88                 JScrollPane testPane = new JScrollPane(testPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
    89                 testPane.setBorder(null);
     88        JScrollPane testPane = new JScrollPane(testPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
     89        testPane.setBorder(null);
    9090
    91                 Version ver = Util.getVersion();
    92                 String description = tr("A OSM data validator that checks for common errors made by users and editor programs.");
    93                 if( ver != null )
    94                         description += "<br>" + tr("Version {0} - Last change at {1}", ver.revision, ver.time);
    95                 JPanel tab = gui.createPreferenceTab("validator", tr("Data validator"), description);
    96                 tab.add(testPane, GBC.eol().fill(GBC.BOTH));
    97                 tab.add(GBC.glue(0,10), a);
    98         }
     91        Version ver = Util.getVersion();
     92        String description = tr("A OSM data validator that checks for common errors made by users and editor programs.");
     93        if( ver != null )
     94            description += "<br>" + tr("Version {0} - Last change at {1}", ver.revision, ver.time);
     95        JPanel tab = gui.createPreferenceTab("validator", tr("Data validator"), description);
     96        tab.add(testPane, GBC.eol().fill(GBC.BOTH));
     97        tab.add(GBC.glue(0,10), a);
     98    }
    9999
    100         public boolean ok()
    101         {
    102                 StringBuilder tests = new StringBuilder();
    103                 StringBuilder testsBeforeUpload = new StringBuilder();
    104                 Boolean res = false;
     100    public boolean ok()
     101    {
     102        StringBuilder tests = new StringBuilder();
     103        StringBuilder testsBeforeUpload = new StringBuilder();
     104        Boolean res = false;
    105105
    106                 for (Test test : allTests)
    107                 {
    108                         if(test.ok())
    109                             res = false;
    110                         String name = test.getClass().getSimpleName();
    111                         tests.append( ',' ).append( name ).append( '=' ).append( test.enabled );
    112                         testsBeforeUpload.append( ',' ).append( name ).append( '=' ).append( test.testBeforeUpload );
    113                 }
     106        for (Test test : allTests)
     107        {
     108            if(test.ok())
     109                res = false;
     110            String name = test.getClass().getSimpleName();
     111            tests.append( ',' ).append( name ).append( '=' ).append( test.enabled );
     112            testsBeforeUpload.append( ',' ).append( name ).append( '=' ).append( test.testBeforeUpload );
     113        }
    114114
    115                 if (tests.length() > 0 ) tests = tests.deleteCharAt(0);
    116                 if (testsBeforeUpload.length() > 0 ) testsBeforeUpload = testsBeforeUpload.deleteCharAt(0);
     115        if (tests.length() > 0 ) tests = tests.deleteCharAt(0);
     116        if (testsBeforeUpload.length() > 0 ) testsBeforeUpload = testsBeforeUpload.deleteCharAt(0);
    117117
    118                 plugin.initializeTests( allTests );
     118        plugin.initializeTests( allTests );
    119119
    120                 Main.pref.put( PREF_TESTS, tests.toString());
    121                 Main.pref.put( PREF_TESTS_BEFORE_UPLOAD, testsBeforeUpload.toString());
    122                 Main.pref.put( PREF_USE_IGNORE, prefUseIgnore.isSelected());
    123                 Main.pref.put( PREF_LAYER, prefUseLayer.isSelected());
    124                 return false;
    125         }
     120        Main.pref.put( PREF_TESTS, tests.toString());
     121        Main.pref.put( PREF_TESTS_BEFORE_UPLOAD, testsBeforeUpload.toString());
     122        Main.pref.put( PREF_USE_IGNORE, prefUseIgnore.isSelected());
     123        Main.pref.put( PREF_LAYER, prefUseLayer.isSelected());
     124        return false;
     125    }
    126126}
  • applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/Severity.java

    r9913 r12778  
    1010/** The error severity */
    1111public enum Severity {
    12         /** Error messages */
    13         ERROR(tr("Errors"), "error.gif",       Main.pref.getColor(marktr("validation error"), Color.RED)),
    14         /** Warning messages */
    15         WARNING(tr("Warnings"), "warning.gif", Main.pref.getColor(marktr("validation warning"), Color.YELLOW)),
    16         /** Other messages */
    17         OTHER(tr("Other"), "other.gif",        Main.pref.getColor(marktr("validation other"), Color.CYAN));
    18        
    19         /** Description of the severity code */
    20         private final String message;
    21        
     12    /** Error messages */
     13    ERROR(tr("Errors"), "error.gif",       Main.pref.getColor(marktr("validation error"), Color.RED)),
     14    /** Warning messages */
     15    WARNING(tr("Warnings"), "warning.gif", Main.pref.getColor(marktr("validation warning"), Color.YELLOW)),
     16    /** Other messages */
     17    OTHER(tr("Other"), "other.gif",        Main.pref.getColor(marktr("validation other"), Color.CYAN));
     18
     19    /** Description of the severity code */
     20    private final String message;
     21
    2222    /** Associated icon */
    2323    private final String icon;
     
    2626    private final Color color;
    2727
    28         /**
    29         * Constructor
    30          *
    31         * @param message Description
    32         * @param icon Associated icon
    33         * @param color The color of this severity
    34         */
    35     Severity(String message, String icon, Color color) 
     28    /**
     29    * Constructor
     30     *
     31    * @param message Description
     32    * @param icon Associated icon
     33    * @param color The color of this severity
     34    */
     35    Severity(String message, String icon, Color color)
    3636    {
    3737        this.message = message;
    38                 this.icon = icon;
     38        this.icon = icon;
    3939        this.color = color;
    4040    }
    4141
    42         @Override
    43         public String toString()
    44         {
    45                 return message;
    46         }
     42    @Override
     43    public String toString()
     44    {
     45        return message;
     46    }
    4747
    48         /**
    49         * Gets the associated icon
    50         * @return the associated icon
    51         */
    52         public String getIcon()
    53         {
    54                 return icon;
    55         }
     48    /**
     49    * Gets the associated icon
     50    * @return the associated icon
     51    */
     52    public String getIcon()
     53    {
     54        return icon;
     55    }
    5656
    5757    /**
     
    6363        return color;
    6464    }
    65    
    66    
     65
     66
    6767}
  • applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/Test.java

    r12777 r12778  
    2727public class Test implements Visitor
    2828{
    29         /** Name of the test */
    30         protected String name;
    31        
    32         /** Description of the test */
    33         protected String description;
    34        
     29    /** Name of the test */
     30    protected String name;
     31   
     32    /** Description of the test */
     33    protected String description;
     34   
    3535    /** Whether this test is enabled. Enabled by default */
    3636    protected boolean enabled = true;
     
    4848    protected boolean isBeforeUpload;
    4949
    50         /** The list of errors */
    51         protected List<TestError> errors = new ArrayList<TestError>(30);
    52 
    53         /** Whether the test is run on a partial selection data */
    54         protected boolean partialSelection;
    55 
    56         /**
    57         * Constructor
    58         * @param name Name of the test
    59         * @param description Description of the test
    60         */
    61         public Test(String name, String description)
    62         {
    63                 this.name = name;
    64                 this.description = description;
    65         }
    66        
    67         /**
    68         * Constructor
    69         * @param name Name of the test
    70         */
    71         public Test(String name)
    72         {
    73                 this.name = name;
    74         }
    75        
    76         /**
    77         * Initializes any global data used this tester.
    78         * @param plugin The plugin
    79         * @throws Exception When cannot initialize the test
    80         */
    81         public static void initialize(OSMValidatorPlugin plugin) throws Exception {}
    82        
    83         /**
    84         * Notification of the start of the test. The tester can initialize the
    85         * structures it may need for this test
    86         */
    87         public void startTest()
    88         {
    89                 errors = new ArrayList<TestError>(30);
    90         }
    91 
    92         /**
    93         * Flag notifying that this test is run over a partial data selection
    94         * @param partialSelection Whether the test is on a partial selection data
    95         */
    96         public void setPartialSelection(boolean partialSelection)
    97         {
    98                 this.partialSelection = partialSelection;
    99         }
    100        
    101         /**
    102         * Gets the validation errors accumulated until this moment.
    103         * @return The list of errors
    104         */
    105         public List<TestError> getErrors()
    106         {
    107                 return errors;
    108         }
    109        
    110         /**
    111         * Notification of the end of the test. The tester may perform additional
    112         * actions and destroy the used structures
    113         */
    114         public void endTest() {}
     50    /** The list of errors */
     51    protected List<TestError> errors = new ArrayList<TestError>(30);
     52
     53    /** Whether the test is run on a partial selection data */
     54    protected boolean partialSelection;
     55
     56    /**
     57    * Constructor
     58    * @param name Name of the test
     59    * @param description Description of the test
     60    */
     61    public Test(String name, String description)
     62    {
     63        this.name = name;
     64        this.description = description;
     65    }
     66   
     67    /**
     68    * Constructor
     69    * @param name Name of the test
     70    */
     71    public Test(String name)
     72    {
     73        this.name = name;
     74    }
     75   
     76    /**
     77    * Initializes any global data used this tester.
     78    * @param plugin The plugin
     79    * @throws Exception When cannot initialize the test
     80    */
     81    public static void initialize(OSMValidatorPlugin plugin) throws Exception {}
     82   
     83    /**
     84    * Notification of the start of the test. The tester can initialize the
     85    * structures it may need for this test
     86    */
     87    public void startTest()
     88    {
     89        errors = new ArrayList<TestError>(30);
     90    }
     91
     92    /**
     93    * Flag notifying that this test is run over a partial data selection
     94    * @param partialSelection Whether the test is on a partial selection data
     95    */
     96    public void setPartialSelection(boolean partialSelection)
     97    {
     98        this.partialSelection = partialSelection;
     99    }
     100   
     101    /**
     102    * Gets the validation errors accumulated until this moment.
     103    * @return The list of errors
     104    */
     105    public List<TestError> getErrors()
     106    {
     107        return errors;
     108    }
     109   
     110    /**
     111    * Notification of the end of the test. The tester may perform additional
     112    * actions and destroy the used structures
     113    */
     114    public void endTest() {}
    115115
    116116    /**
     
    124124        for (OsmPrimitive p : selection)
    125125        {
    126                 if( !p.deleted && !p.incomplete )
    127                         p.visit(this);
     126            if( !p.deleted && !p.incomplete )
     127                p.visit(this);
    128128        }
    129129    }
     
    131131    public void visit(Node n) {}
    132132
    133         public void visit(Way w) {}
    134 
    135         public void visit(Relation r) {}
    136 
    137         /**
    138         * Allow the tester to manage its own preferences
    139         * @param testPanel The panel to add any preferences component
    140         */
    141         public void addGui(JPanel testPanel)
    142         {
    143                 checkEnabled = new JCheckBox(name, enabled);
    144                 checkEnabled.setToolTipText(description);
    145                 testPanel.add(checkEnabled, GBC.std());
    146 
    147                 GBC a = GBC.eol();
    148                 a.anchor = GBC.EAST;
    149                 checkBeforeUpload = new JCheckBox();
    150                 checkBeforeUpload.setSelected(testBeforeUpload);
    151                 testPanel.add(checkBeforeUpload, a);
    152         }
    153 
    154         /**
    155         * Called when the used submits the preferences
    156         */
    157         public boolean ok()
    158         {
    159                 enabled = checkEnabled.isSelected();
    160                 testBeforeUpload = checkBeforeUpload.isSelected();
    161                 return false;
    162         }
    163        
    164         /**
    165         * Fixes the error with the appropiate command
    166         *
    167         * @param testError
    168         * @return The command to fix the error
    169         */
    170         public Command fixError(TestError testError)
    171         {
    172                 return null;
    173         }
    174        
    175         /**
    176         * Returns true if the given error can be fixed automatically
    177         *
    178         * @param testError The error to check if can be fixed
    179         * @return true if the error can be fixed
    180         */
    181         public boolean isFixable(TestError testError)
    182         {
    183                 return false;
    184         }
     133    public void visit(Way w) {}
     134
     135    public void visit(Relation r) {}
     136
     137    /**
     138    * Allow the tester to manage its own preferences
     139    * @param testPanel The panel to add any preferences component
     140    */
     141    public void addGui(JPanel testPanel)
     142    {
     143        checkEnabled = new JCheckBox(name, enabled);
     144        checkEnabled.setToolTipText(description);
     145        testPanel.add(checkEnabled, GBC.std());
     146
     147        GBC a = GBC.eol();
     148        a.anchor = GBC.EAST;
     149        checkBeforeUpload = new JCheckBox();
     150        checkBeforeUpload.setSelected(testBeforeUpload);
     151        testPanel.add(checkBeforeUpload, a);
     152    }
     153
     154    /**
     155    * Called when the used submits the preferences
     156    */
     157    public boolean ok()
     158    {
     159        enabled = checkEnabled.isSelected();
     160        testBeforeUpload = checkBeforeUpload.isSelected();
     161        return false;
     162    }
     163   
     164    /**
     165    * Fixes the error with the appropiate command
     166    *
     167    * @param testError
     168    * @return The command to fix the error
     169    */
     170    public Command fixError(TestError testError)
     171    {
     172        return null;
     173    }
     174   
     175    /**
     176    * Returns true if the given error can be fixed automatically
     177    *
     178    * @param testError The error to check if can be fixed
     179    * @return true if the error can be fixed
     180    */
     181    public boolean isFixable(TestError testError)
     182    {
     183        return false;
     184    }
    185185
    186186    /**
  • applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/TestError.java

    r10540 r12778  
    372372         * Checks if the given segment is in the visible area.
    373373         * NOTE: This will return true for a small number of non-visible
    374          *              segments.
     374         *      segments.
    375375         * @param ls The segment to check
    376376         * @return true if the segment is visible
  • applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/ValidateUploadHook.java

    r11530 r12778  
    2929public class ValidateUploadHook implements UploadHook
    3030{
    31         /** Serializable ID */
    32         private static final long serialVersionUID = -2304521273582574603L;
     31    /** Serializable ID */
     32    private static final long serialVersionUID = -2304521273582574603L;
    3333
    34         private OSMValidatorPlugin plugin;
     34    private OSMValidatorPlugin plugin;
    3535
    36         public ValidateUploadHook(OSMValidatorPlugin plugin)
    37         {
    38                 this.plugin = plugin;
    39         }
     36    public ValidateUploadHook(OSMValidatorPlugin plugin)
     37    {
     38        this.plugin = plugin;
     39    }
    4040
    41         /**
    42         * Validate the modified data before uploading
    43         */
    44         public boolean checkUpload(Collection<OsmPrimitive> add, Collection<OsmPrimitive> update, Collection<OsmPrimitive> delete)
    45         {
    46                 Collection<Test> tests = OSMValidatorPlugin.getEnabledTests(true);
    47                 if( tests.isEmpty() )
    48                         return true;
     41    /**
     42    * Validate the modified data before uploading
     43    */
     44    public boolean checkUpload(Collection<OsmPrimitive> add, Collection<OsmPrimitive> update, Collection<OsmPrimitive> delete)
     45    {
     46        Collection<Test> tests = OSMValidatorPlugin.getEnabledTests(true);
     47        if( tests.isEmpty() )
     48            return true;
    4949
    50                 AgregatePrimitivesVisitor v = new AgregatePrimitivesVisitor();
    51                 v.visit(add);
    52                 Collection<OsmPrimitive> selection = v.visit(update);
     50        AgregatePrimitivesVisitor v = new AgregatePrimitivesVisitor();
     51        v.visit(add);
     52        Collection<OsmPrimitive> selection = v.visit(update);
    5353
    54                 List<TestError> errors = new ArrayList<TestError>(30);
    55                 for(Test test : tests)
    56                 {
    57                         test.setBeforeUpload(true);
    58                         test.setPartialSelection(true);
    59                         test.startTest();
    60                         test.visit(selection);
    61                         test.endTest();
    62                         errors.addAll( test.getErrors() );
    63                 }
    64                 tests = null;
    65                 if(errors == null || errors.isEmpty())
    66                         return true;
     54        List<TestError> errors = new ArrayList<TestError>(30);
     55        for(Test test : tests)
     56        {
     57            test.setBeforeUpload(true);
     58            test.setPartialSelection(true);
     59            test.startTest();
     60            test.visit(selection);
     61            test.endTest();
     62            errors.addAll( test.getErrors() );
     63        }
     64        tests = null;
     65        if(errors == null || errors.isEmpty())
     66            return true;
    6767
    68                 if(Main.pref.getBoolean(PreferenceEditor.PREF_USE_IGNORE, true))
    69                 {
    70                         int nume = 0;
    71                         for(TestError error : errors)
    72                         {
    73                                 List<String> s = new ArrayList<String>();
    74                                 s.add(error.getIgnoreState());
    75                                 s.add(error.getIgnoreGroup());
    76                                 s.add(error.getIgnoreSubGroup());
    77                                 for(String state : s)
    78                                 {
    79                                         if(state != null && plugin.ignoredErrors.contains(state))
    80                                         {
    81                                                 error.setIgnored(true);
    82                                         }
    83                                 }
    84                                 if(!error.getIgnored())
    85                                         ++nume;
    86                         }
    87                         if(nume == 0)
    88                                 return true;
    89                 }
    90                 return displayErrorScreen(errors);
    91         }
     68        if(Main.pref.getBoolean(PreferenceEditor.PREF_USE_IGNORE, true))
     69        {
     70            int nume = 0;
     71            for(TestError error : errors)
     72            {
     73                List<String> s = new ArrayList<String>();
     74                s.add(error.getIgnoreState());
     75                s.add(error.getIgnoreGroup());
     76                s.add(error.getIgnoreSubGroup());
     77                for(String state : s)
     78                {
     79                    if(state != null && plugin.ignoredErrors.contains(state))
     80                    {
     81                        error.setIgnored(true);
     82                    }
     83                }
     84                if(!error.getIgnored())
     85                    ++nume;
     86            }
     87            if(nume == 0)
     88                return true;
     89        }
     90        return displayErrorScreen(errors);
     91    }
    9292
    93         /**
    94         * Displays a screen where the actions that would be taken are displayed and
    95         * give the user the possibility to cancel the upload.
    96         * @param errors The errors displayed in the screen
    97         * @return <code>true</code>, if the upload should continue. <code>false</code>
    98         *          if the user requested cancel.
    99         */
    100         private boolean displayErrorScreen(List<TestError> errors)
    101         {
    102                 JPanel p = new JPanel(new GridBagLayout());
    103                 ErrorTreePanel errorPanel = new ErrorTreePanel(errors);
    104                 errorPanel.expandAll();
    105                 p.add(new JScrollPane(errorPanel), GBC.eol());
     93    /**
     94    * Displays a screen where the actions that would be taken are displayed and
     95    * give the user the possibility to cancel the upload.
     96    * @param errors The errors displayed in the screen
     97    * @return <code>true</code>, if the upload should continue. <code>false</code>
     98    *          if the user requested cancel.
     99    */
     100    private boolean displayErrorScreen(List<TestError> errors)
     101    {
     102        JPanel p = new JPanel(new GridBagLayout());
     103        ErrorTreePanel errorPanel = new ErrorTreePanel(errors);
     104        errorPanel.expandAll();
     105        p.add(new JScrollPane(errorPanel), GBC.eol());
    106106
    107                 int res  = JOptionPane.showConfirmDialog(Main.parent, p,
    108                 tr("Data with errors. Upload anyway?"), JOptionPane.YES_NO_OPTION);
    109                 if(res == JOptionPane.NO_OPTION)
    110                 {
    111                         plugin.validationDialog.tree.setErrors(errors);
    112                         plugin.validationDialog.setVisible(true);
    113                         DataSet.fireSelectionChanged(Main.ds.getSelected());
    114                 }
    115                 return res == JOptionPane.YES_OPTION;
    116         }
     107        int res  = JOptionPane.showConfirmDialog(Main.parent, p,
     108        tr("Data with errors. Upload anyway?"), JOptionPane.YES_NO_OPTION);
     109        if(res == JOptionPane.NO_OPTION)
     110        {
     111            plugin.validationDialog.tree.setErrors(errors);
     112            plugin.validationDialog.setVisible(true);
     113            DataSet.fireSelectionChanged(Main.ds.getSelected());
     114        }
     115        return res == JOptionPane.YES_OPTION;
     116    }
    117117}
  • applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/ChangePropertyKeyCommand.java

    r7804 r12778  
    2222 */
    2323public class ChangePropertyKeyCommand extends Command {
    24         /**
    25         * All primitives, that are affected with this command.
    26         */
    27         private final List<OsmPrimitive> objects;
    28         /**
    29         * The key that is subject to change.
    30         */
    31         private final String key;
    32         /**
    33         * The mew key.
    34         */
    35         private final String newKey;
    36        
    37         /**
    38         * Constructor
    39         *
    40         * @param objects all objects subject to change replacement
    41         * @param key The key to replace
    42         * @param newKey the new value of the key
    43         */
    44         public ChangePropertyKeyCommand(Collection<? extends OsmPrimitive> objects, String key, String newKey) {
    45                 this.objects = new LinkedList<OsmPrimitive>(objects);
    46                 this.key = key;
    47                 this.newKey = newKey;
    48         }
    49        
    50         @Override public boolean executeCommand() {
    51                 if (!super.executeCommand()) return false; // save old
    52                 for (OsmPrimitive osm : objects) {
    53                         if(osm.keys != null)
    54                         {
    55                                 osm.modified = true;
    56                                 osm.put(newKey, osm.keys.remove(key) );
    57                         }
    58                 }
     24    /**
     25    * All primitives, that are affected with this command.
     26    */
     27    private final List<OsmPrimitive> objects;
     28    /**
     29    * The key that is subject to change.
     30    */
     31    private final String key;
     32    /**
     33    * The mew key.
     34    */
     35    private final String newKey;
     36   
     37    /**
     38    * Constructor
     39    *
     40    * @param objects all objects subject to change replacement
     41    * @param key The key to replace
     42    * @param newKey the new value of the key
     43    */
     44    public ChangePropertyKeyCommand(Collection<? extends OsmPrimitive> objects, String key, String newKey) {
     45        this.objects = new LinkedList<OsmPrimitive>(objects);
     46        this.key = key;
     47        this.newKey = newKey;
     48    }
     49   
     50    @Override public boolean executeCommand() {
     51        if (!super.executeCommand()) return false; // save old
     52        for (OsmPrimitive osm : objects) {
     53            if(osm.keys != null)
     54            {
     55                osm.modified = true;
     56                osm.put(newKey, osm.keys.remove(key) );
     57            }
     58        }
    5959        return true;
    60         }
     60    }
    6161
    62         @Override public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
    63                 modified.addAll(objects);
    64         }
     62    @Override public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
     63        modified.addAll(objects);
     64    }
    6565
    66         @Override public MutableTreeNode description() {
    67                 String text = tr( "Replace \"{0}\" by \"{1}\" for", key, newKey);
    68                 if (objects.size() == 1) {
    69                         NameVisitor v = new NameVisitor();
    70                         objects.iterator().next().visit(v);
    71                         text += " "+tr(v.className)+" "+v.name;
    72                 } else
    73                         text += " "+objects.size()+" "+trn("object","objects",objects.size());
    74                 DefaultMutableTreeNode root = new DefaultMutableTreeNode(new JLabel(text, ImageProvider.get("data", "key"), JLabel.HORIZONTAL));
    75                 if (objects.size() == 1)
    76                         return root;
    77                 NameVisitor v = new NameVisitor();
    78                 for (OsmPrimitive osm : objects) {
    79                         osm.visit(v);
    80                         root.add(new DefaultMutableTreeNode(v.toLabel()));
    81                 }
    82                 return root;
     66    @Override public MutableTreeNode description() {
     67        String text = tr( "Replace \"{0}\" by \"{1}\" for", key, newKey);
     68        if (objects.size() == 1) {
     69            NameVisitor v = new NameVisitor();
     70            objects.iterator().next().visit(v);
     71            text += " "+tr(v.className)+" "+v.name;
     72        } else
     73            text += " "+objects.size()+" "+trn("object","objects",objects.size());
     74        DefaultMutableTreeNode root = new DefaultMutableTreeNode(new JLabel(text, ImageProvider.get("data", "key"), JLabel.HORIZONTAL));
     75        if (objects.size() == 1)
     76            return root;
     77        NameVisitor v = new NameVisitor();
     78        for (OsmPrimitive osm : objects) {
     79            osm.visit(v);
     80            root.add(new DefaultMutableTreeNode(v.toLabel()));
     81        }
     82        return root;
    8383    }
    8484}
  • applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/Coastlines.java

    r9684 r12778  
    2121public class Coastlines extends Test
    2222{
    23         protected static int UNORDERED_COASTLINES = 901;
     23    protected static int UNORDERED_COASTLINES = 901;
    2424
    25         /** All ways, grouped by cells */
    26         Map<Point2D,List<Way>> _cellWays;
    27         /** The already detected errors */
    28         Bag<Way, Way> _errorWays;
     25    /** All ways, grouped by cells */
     26    Map<Point2D,List<Way>> _cellWays;
     27    /** The already detected errors */
     28    Bag<Way, Way> _errorWays;
    2929
    30         /**
    31         * Constructor
    32         */
    33         public Coastlines()
    34         {
    35                 super(tr("Coastlines."),
    36                           tr("This test checks that coastlines are correct."));
    37         }
     30    /**
     31    * Constructor
     32    */
     33    public Coastlines()
     34    {
     35        super(tr("Coastlines."),
     36              tr("This test checks that coastlines are correct."));
     37    }
    3838
    39         @Override
    40         public void startTest()
    41         {
    42                 _cellWays = new HashMap<Point2D,List<Way>>(1000);
    43                 _errorWays = new Bag<Way, Way>();
    44         }
     39    @Override
     40    public void startTest()
     41    {
     42        _cellWays = new HashMap<Point2D,List<Way>>(1000);
     43        _errorWays = new Bag<Way, Way>();
     44    }
    4545
    46         @Override
    47         public void endTest()
    48         {
    49                 _cellWays = null;
    50                 _errorWays = null;
    51         }
     46    @Override
     47    public void endTest()
     48    {
     49        _cellWays = null;
     50        _errorWays = null;
     51    }
    5252
    53         @Override
    54         public void visit(Way w)
    55         {
    56                 if( w.deleted || w.incomplete )
    57                         return;
     53    @Override
     54    public void visit(Way w)
     55    {
     56        if( w.deleted || w.incomplete )
     57            return;
    5858
    59                 String natural = w.get("natural");
    60                 if( natural == null || !natural.equals("coastline") )
    61                         return;
     59        String natural = w.get("natural");
     60        if( natural == null || !natural.equals("coastline") )
     61            return;
    6262
    63                 List<List<Way>> cellWays = Util.getWaysInCell(w, _cellWays);
    64                 for( List<Way> ways : cellWays)
    65                 {
    66                         for( Way w2 : ways)
    67                         {
    68                                 if( _errorWays.contains(w, w2) || _errorWays.contains(w2, w) )
    69                                         continue;
     63        List<List<Way>> cellWays = Util.getWaysInCell(w, _cellWays);
     64        for( List<Way> ways : cellWays)
     65        {
     66            for( Way w2 : ways)
     67            {
     68                if( _errorWays.contains(w, w2) || _errorWays.contains(w2, w) )
     69                    continue;
    7070
    71                                 String natural2 = w.get("natural");
    72                                 if( natural2 == null || !natural2.equals("coastline") )
    73                                         continue;
     71                String natural2 = w.get("natural");
     72                if( natural2 == null || !natural2.equals("coastline") )
     73                    continue;
    7474
    75                                 if( w.nodes.get(0).equals(w2.nodes.get(0)) || w.nodes.get(w.nodes.size() - 1).equals(w2.nodes.get(w2.nodes.size() - 1)))
    76                                 {
    77                                         List<OsmPrimitive> primitives = new ArrayList<OsmPrimitive>();
    78                                         primitives.add(w);
    79                                         primitives.add(w2);
    80                                         errors.add( new TestError(this, Severity.ERROR, tr("Unordered coastline"), UNORDERED_COASTLINES, primitives) );
    81                                         _errorWays.add(w, w2);
    82                                 }
    83                         }
    84                         ways.add(w);
    85                 }
    86         }
     75                if( w.nodes.get(0).equals(w2.nodes.get(0)) || w.nodes.get(w.nodes.size() - 1).equals(w2.nodes.get(w2.nodes.size() - 1)))
     76                {
     77                    List<OsmPrimitive> primitives = new ArrayList<OsmPrimitive>();
     78                    primitives.add(w);
     79                    primitives.add(w2);
     80                    errors.add( new TestError(this, Severity.ERROR, tr("Unordered coastline"), UNORDERED_COASTLINES, primitives) );
     81                    _errorWays.add(w, w2);
     82                }
     83            }
     84            ways.add(w);
     85        }
     86    }
    8787}
  • applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/CrossingWays.java

    r12257 r12778  
    2828public class CrossingWays extends Test
    2929{
    30         protected static int CROSSING_WAYS = 601;
    31 
    32         /** All way segments, grouped by cells */
    33         Map<Point2D,List<ExtendedSegment>> cellSegments;
    34         /** The already detected errors */
    35         HashSet<WaySegment> errorSegments;
    36         /** The already detected ways in error */
    37         Map<List<Way>, List<WaySegment>> ways_seen;
    38 
    39 
    40         /**
    41         * Constructor
    42         */
    43         public CrossingWays()
    44         {
    45                 super(tr("Crossing ways."),
    46                           tr("This test checks if two roads, railways or waterways crosses in the same layer, but are not connected by a node."));
    47         }
    48 
    49 
    50         @Override
    51         public void startTest()
    52         {
    53                 cellSegments = new HashMap<Point2D,List<ExtendedSegment>>(1000);
    54                 errorSegments = new HashSet<WaySegment>();
    55                 ways_seen = new HashMap<List<Way>, List<WaySegment>>(50);
    56         }
    57 
    58         @Override
    59         public void endTest()
    60         {
    61                 cellSegments = null;
    62                 errorSegments = null;
    63                 ways_seen = null;
    64         }
    65 
    66         @Override
    67         public void visit(Way w)
    68         {
    69                 if( w.deleted || w.incomplete )
    70                         return;
    71 
    72                 String coastline1 = w.get("natural");
    73                 boolean isCoastline1 = coastline1 != null && (coastline1.equals("water") || coastline1.equals("coastline"));
    74                 String railway1 = w.get("railway");
    75                 boolean isSubway1 = railway1 != null && railway1.equals("subway");
    76                 if( w.get("highway") == null && w.get("waterway") == null && (railway1 == null || isSubway1)  && !isCoastline1)
    77                         return;
    78 
    79                 String layer1 = w.get("layer");
    80 
    81                 int nodesSize = w.nodes.size();
    82                 for (int i = 0; i < nodesSize - 1; i++) {
    83                         WaySegment ws = new WaySegment(w, i);
    84                         ExtendedSegment es1 = new ExtendedSegment(ws, layer1, railway1, coastline1);
    85                         List<List<ExtendedSegment>> cellSegments = getSegments(es1.n1, es1.n2);
    86                         for( List<ExtendedSegment> segments : cellSegments)
    87                         {
    88                                 for( ExtendedSegment es2 : segments)
    89                                 {
    90                                         List<Way> prims;
    91                                         List<WaySegment> highlight;
    92 
    93                                         if (errorSegments.contains(ws) && errorSegments.contains(es2.ws))
    94                                                 continue;
    95 
    96                                         String layer2 = es2.layer;
    97                                         String railway2 = es2.railway;
    98                                         String coastline2 = es2.coastline;
    99                                         if (layer1 == null ? layer2 != null : !layer1.equals(layer2))
    100                                                 continue;
    101 
    102                                         if( !es1.intersects(es2) ) continue;
    103                                         if( isSubway1 && "subway".equals(railway2)) continue;
    104 
    105                                         boolean isCoastline2 = coastline2 != null && (coastline2.equals("water") || coastline2.equals("coastline"));
    106                                         if( isCoastline1 != isCoastline2 ) continue;
    107 
    108                                         prims = Arrays.asList(es1.ws.way, es2.ws.way);
    109                                         if ((highlight = ways_seen.get(prims)) == null)
    110                                         {
    111                                                 highlight = new ArrayList<WaySegment>();
    112                                                 highlight.add(es1.ws);
    113                                                 highlight.add(es2.ws);
    114 
    115                                                 errors.add(new TestError(this, Severity.WARNING,
    116                                                 tr("Crossing ways"), CROSSING_WAYS, prims, highlight));
    117                                                 ways_seen.put(prims, highlight);
    118                                         }
    119                                         else
    120                                         {
    121                                                 highlight.add(es1.ws);
    122                                                 highlight.add(es2.ws);
    123                                         }
    124                                 }
    125                                 segments.add(es1);
    126                         }
    127                 }
    128         }
    129 
    130         /**
    131         * Returns all the cells this segment crosses.  Each cell contains the list
    132         * of segments already processed
    133         *
    134         * @param n1 The first node
    135         * @param n2 The second node
    136         * @return A list with all the cells the segment crosses
    137         */
    138         public List<List<ExtendedSegment>> getSegments(Node n1, Node n2)
    139         {
    140                 List<List<ExtendedSegment>> cells = new ArrayList<List<ExtendedSegment>>();
    141                 for( Point2D cell : Util.getSegmentCells(n1, n2, OSMValidatorPlugin.griddetail) )
    142                 {
    143                         List<ExtendedSegment> segments = cellSegments.get( cell );
    144                         if( segments == null )
    145                         {
    146                                 segments = new ArrayList<ExtendedSegment>();
    147                                 cellSegments.put(cell, segments);
    148                         }
    149                         cells.add(segments);
    150                 }
    151 
    152                 return cells;
    153         }
    154 
    155         /**
    156         * A way segment with some additional information
    157         * @author frsantos
    158         */
    159         private class ExtendedSegment
    160         {
    161                 public Node n1, n2;
    162 
    163                 public WaySegment ws;
    164 
    165                 /** The layer */
    166                 public String layer;
    167 
    168                 /** The railway type */
    169                 public String railway;
    170 
    171                 /** The coastline type */
    172                 public String coastline;
    173 
    174                 /**
    175                 * Constructor
    176                 * @param ws The way segment
    177                 * @param layer The layer of the way this segment is in
    178                 * @param railway The railway type of the way this segment is in
    179                 * @param coastline The coastlyne typo of the way the segment is in
    180                 */
    181                 public ExtendedSegment(WaySegment ws, String layer, String railway, String coastline)
    182                 {
    183                         this.ws = ws;
    184                         this.n1 = ws.way.nodes.get(ws.lowerIndex);
    185                         this.n2 = ws.way.nodes.get(ws.lowerIndex + 1);
    186                         this.layer = layer;
    187                         this.railway = railway;
    188                         this.coastline = coastline;
    189                 }
    190 
    191                 /**
    192                 * Checks whether this segment crosses other segment
    193                 * @param s2 The other segment
    194                 * @return true if both segements crosses
    195                 */
    196                 public boolean intersects(ExtendedSegment s2)
    197                 {
    198                         if( n1.equals(s2.n1) || n2.equals(s2.n2) ||
    199                                 n1.equals(s2.n2)   || n2.equals(s2.n1) )
    200                         {
    201                                 return false;
    202                         }
    203 
    204                         return Line2D.linesIntersect(
    205                                 n1.eastNorth.east(), n1.eastNorth.north(),
    206                                 n2.eastNorth.east(), n2.eastNorth.north(),
    207                                 s2.n1.eastNorth.east(), s2.n1.eastNorth.north(),
    208                                 s2.n2.eastNorth.east(), s2.n2.eastNorth.north());
    209                 }
    210         }
     30    protected static int CROSSING_WAYS = 601;
     31
     32    /** All way segments, grouped by cells */
     33    Map<Point2D,List<ExtendedSegment>> cellSegments;
     34    /** The already detected errors */
     35    HashSet<WaySegment> errorSegments;
     36    /** The already detected ways in error */
     37    Map<List<Way>, List<WaySegment>> ways_seen;
     38
     39
     40    /**
     41    * Constructor
     42    */
     43    public CrossingWays()
     44    {
     45        super(tr("Crossing ways."),
     46              tr("This test checks if two roads, railways or waterways crosses in the same layer, but are not connected by a node."));
     47    }
     48
     49
     50    @Override
     51    public void startTest()
     52    {
     53        cellSegments = new HashMap<Point2D,List<ExtendedSegment>>(1000);
     54        errorSegments = new HashSet<WaySegment>();
     55        ways_seen = new HashMap<List<Way>, List<WaySegment>>(50);
     56    }
     57
     58    @Override
     59    public void endTest()
     60    {
     61        cellSegments = null;
     62        errorSegments = null;
     63        ways_seen = null;
     64    }
     65
     66    @Override
     67    public void visit(Way w)
     68    {
     69        if( w.deleted || w.incomplete )
     70            return;
     71
     72        String coastline1 = w.get("natural");
     73        boolean isCoastline1 = coastline1 != null && (coastline1.equals("water") || coastline1.equals("coastline"));
     74        String railway1 = w.get("railway");
     75        boolean isSubway1 = railway1 != null && railway1.equals("subway");
     76        if( w.get("highway") == null && w.get("waterway") == null && (railway1 == null || isSubway1)  && !isCoastline1)
     77            return;
     78
     79        String layer1 = w.get("layer");
     80
     81        int nodesSize = w.nodes.size();
     82        for (int i = 0; i < nodesSize - 1; i++) {
     83            WaySegment ws = new WaySegment(w, i);
     84            ExtendedSegment es1 = new ExtendedSegment(ws, layer1, railway1, coastline1);
     85            List<List<ExtendedSegment>> cellSegments = getSegments(es1.n1, es1.n2);
     86            for( List<ExtendedSegment> segments : cellSegments)
     87            {
     88                for( ExtendedSegment es2 : segments)
     89                {
     90                    List<Way> prims;
     91                    List<WaySegment> highlight;
     92
     93                    if (errorSegments.contains(ws) && errorSegments.contains(es2.ws))
     94                        continue;
     95
     96                    String layer2 = es2.layer;
     97                    String railway2 = es2.railway;
     98                    String coastline2 = es2.coastline;
     99                    if (layer1 == null ? layer2 != null : !layer1.equals(layer2))
     100                        continue;
     101
     102                    if( !es1.intersects(es2) ) continue;
     103                    if( isSubway1 && "subway".equals(railway2)) continue;
     104
     105                    boolean isCoastline2 = coastline2 != null && (coastline2.equals("water") || coastline2.equals("coastline"));
     106                    if( isCoastline1 != isCoastline2 ) continue;
     107
     108                    prims = Arrays.asList(es1.ws.way, es2.ws.way);
     109                    if ((highlight = ways_seen.get(prims)) == null)
     110                    {
     111                        highlight = new ArrayList<WaySegment>();
     112                        highlight.add(es1.ws);
     113                        highlight.add(es2.ws);
     114
     115                        errors.add(new TestError(this, Severity.WARNING,
     116                        tr("Crossing ways"), CROSSING_WAYS, prims, highlight));
     117                        ways_seen.put(prims, highlight);
     118                    }
     119                    else
     120                    {
     121                        highlight.add(es1.ws);
     122                        highlight.add(es2.ws);
     123                    }
     124                }
     125                segments.add(es1);
     126            }
     127        }
     128    }
     129
     130    /**
     131    * Returns all the cells this segment crosses.  Each cell contains the list
     132    * of segments already processed
     133    *
     134    * @param n1 The first node
     135    * @param n2 The second node
     136    * @return A list with all the cells the segment crosses
     137    */
     138    public List<List<ExtendedSegment>> getSegments(Node n1, Node n2)
     139    {
     140        List<List<ExtendedSegment>> cells = new ArrayList<List<ExtendedSegment>>();
     141        for( Point2D cell : Util.getSegmentCells(n1, n2, OSMValidatorPlugin.griddetail) )
     142        {
     143            List<ExtendedSegment> segments = cellSegments.get( cell );
     144            if( segments == null )
     145            {
     146                segments = new ArrayList<ExtendedSegment>();
     147                cellSegments.put(cell, segments);
     148            }
     149            cells.add(segments);
     150        }
     151
     152        return cells;
     153    }
     154
     155    /**
     156    * A way segment with some additional information
     157    * @author frsantos
     158    */
     159    private class ExtendedSegment
     160    {
     161        public Node n1, n2;
     162
     163        public WaySegment ws;
     164
     165        /** The layer */
     166        public String layer;
     167
     168        /** The railway type */
     169        public String railway;
     170
     171        /** The coastline type */
     172        public String coastline;
     173
     174        /**
     175        * Constructor
     176        * @param ws The way segment
     177        * @param layer The layer of the way this segment is in
     178        * @param railway The railway type of the way this segment is in
     179        * @param coastline The coastlyne typo of the way the segment is in
     180        */
     181        public ExtendedSegment(WaySegment ws, String layer, String railway, String coastline)
     182        {
     183            this.ws = ws;
     184            this.n1 = ws.way.nodes.get(ws.lowerIndex);
     185            this.n2 = ws.way.nodes.get(ws.lowerIndex + 1);
     186            this.layer = layer;
     187            this.railway = railway;
     188            this.coastline = coastline;
     189        }
     190
     191        /**
     192        * Checks whether this segment crosses other segment
     193        * @param s2 The other segment
     194        * @return true if both segements crosses
     195        */
     196        public boolean intersects(ExtendedSegment s2)
     197        {
     198            if( n1.equals(s2.n1) || n2.equals(s2.n2) ||
     199                n1.equals(s2.n2)   || n2.equals(s2.n1) )
     200            {
     201                return false;
     202            }
     203
     204            return Line2D.linesIntersect(
     205                n1.eastNorth.east(), n1.eastNorth.north(),
     206                n2.eastNorth.east(), n2.eastNorth.north(),
     207                s2.n1.eastNorth.east(), s2.n1.eastNorth.north(),
     208                s2.n2.eastNorth.east(), s2.n2.eastNorth.north());
     209        }
     210    }
    211211}
  • applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/DuplicateNode.java

    r12279 r12778  
    2020public class DuplicateNode extends Test
    2121{
    22         protected static int DUPLICATE_NODE = 1;
     22    protected static int DUPLICATE_NODE = 1;
    2323
    24         /** Bag of all nodes */
    25         Bag<LatLon, OsmPrimitive> nodes;
     24    /** Bag of all nodes */
     25    Bag<LatLon, OsmPrimitive> nodes;
    2626
    27         /**
    28         * Constructor
    29         */
    30         public DuplicateNode()
    31         {
    32                 super(tr("Duplicated nodes."),
    33                           tr("This test checks that there are no nodes at the very same location."));
    34         }
     27    /**
     28    * Constructor
     29    */
     30    public DuplicateNode()
     31    {
     32        super(tr("Duplicated nodes."),
     33              tr("This test checks that there are no nodes at the very same location."));
     34    }
    3535
    3636
    37         @Override
    38         public void startTest()
    39         {
    40                 nodes = new Bag<LatLon, OsmPrimitive>(1000);
    41         }
     37    @Override
     38    public void startTest()
     39    {
     40        nodes = new Bag<LatLon, OsmPrimitive>(1000);
     41    }
    4242
    43         @Override
    44         public void endTest()
    45         {
    46                 for(List<OsmPrimitive> duplicated : nodes.values() )
    47                 {
    48                         if( duplicated.size() > 1)
    49                         {
    50                                 TestError testError = new TestError(this, Severity.ERROR, tr("Duplicated nodes"), DUPLICATE_NODE, duplicated);
    51                                 errors.add( testError );
    52                         }
    53                 }
    54                 nodes = null;
    55         }
     43    @Override
     44    public void endTest()
     45    {
     46        for(List<OsmPrimitive> duplicated : nodes.values() )
     47        {
     48            if( duplicated.size() > 1)
     49            {
     50                TestError testError = new TestError(this, Severity.ERROR, tr("Duplicated nodes"), DUPLICATE_NODE, duplicated);
     51                errors.add( testError );
     52            }
     53        }
     54        nodes = null;
     55    }
    5656
    57         @Override
    58         public void visit(Node n)
    59         {
    60                 if(!n.deleted && !n.incomplete)
    61                         nodes.add(n.coor, n);
    62         }
     57    @Override
     58    public void visit(Node n)
     59    {
     60        if(!n.deleted && !n.incomplete)
     61            nodes.add(n.coor, n);
     62    }
    6363
    64         /**
    65         * Merge the nodes into one.
    66         * Copied from UtilsPlugin.MergePointsAction
    67         */
    68         @Override
    69         public Command fixError(TestError testError)
    70         {
    71                 Collection<? extends OsmPrimitive> sel = testError.getPrimitives();
    72                 LinkedList<Node> nodes = new LinkedList<Node>();
     64    /**
     65    * Merge the nodes into one.
     66    * Copied from UtilsPlugin.MergePointsAction
     67    */
     68    @Override
     69    public Command fixError(TestError testError)
     70    {
     71        Collection<? extends OsmPrimitive> sel = testError.getPrimitives();
     72        LinkedList<Node> nodes = new LinkedList<Node>();
    7373
    7474        for (OsmPrimitive osm : sel)
     
    8080
    8181        Node target = null;
    82                 // select the target node in the same way as in the core action MergeNodesAction, rev.1084
     82        // select the target node in the same way as in the core action MergeNodesAction, rev.1084
    8383        for (Node n: nodes) {
    8484            if (n.id > 0) {
     
    9393
    9494        return null; // undoRedo handling done in mergeNodes
    95         }
     95    }
    9696
    97         @Override
    98         public boolean isFixable(TestError testError)
    99         {
    100                 return (testError.getTester() instanceof DuplicateNode);
    101         }
     97    @Override
     98    public boolean isFixable(TestError testError)
     99    {
     100        return (testError.getTester() instanceof DuplicateNode);
     101    }
    102102}
  • applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/DuplicatedWayNodes.java

    r11530 r12778  
    1616
    1717public class DuplicatedWayNodes extends Test {
    18         protected static int DUPLICATE_WAY_NODE = 501;
     18    protected static int DUPLICATE_WAY_NODE = 501;
    1919
    20         public DuplicatedWayNodes() {
    21                 super(tr("Duplicated way nodes."),
    22                         tr("Checks for ways with identical consecutive nodes."));
    23         }
     20    public DuplicatedWayNodes() {
     21        super(tr("Duplicated way nodes."),
     22            tr("Checks for ways with identical consecutive nodes."));
     23    }
    2424
    25         @Override public void visit(Way w) {
    26                 if (w.deleted || w.incomplete) return;
     25    @Override public void visit(Way w) {
     26        if (w.deleted || w.incomplete) return;
    2727
    28                 Node lastN = null;
    29                 for (Node n : w.nodes) {
    30                         if (lastN == null) {
    31                                 lastN = n;
    32                                 continue;
    33                         }
    34                         if (lastN == n) {
    35                                 errors.add(new TestError(this, Severity.ERROR, tr("Duplicated way nodes"), DUPLICATE_WAY_NODE,
    36                                         Arrays.asList(w), Arrays.asList(n)));
    37                                 break;
    38                         }
    39                         lastN = n;
    40                 }
    41         }
     28        Node lastN = null;
     29        for (Node n : w.nodes) {
     30            if (lastN == null) {
     31                lastN = n;
     32                continue;
     33            }
     34            if (lastN == n) {
     35                errors.add(new TestError(this, Severity.ERROR, tr("Duplicated way nodes"), DUPLICATE_WAY_NODE,
     36                    Arrays.asList(w), Arrays.asList(n)));
     37                break;
     38            }
     39            lastN = n;
     40        }
     41    }
    4242
    43         @Override public Command fixError(TestError testError) {
    44                 Way w = (Way) testError.getPrimitives().iterator().next();
    45                 Way wnew = new Way(w);
    46                 wnew.nodes.clear();
    47                 Node lastN = null;
    48                 for (Node n : w.nodes) {
    49                         if (lastN == null) {
    50                                 wnew.nodes.add(n);
    51                         } else if (n == lastN) {
    52                                 // Skip this node
    53                         } else {
    54                                 wnew.nodes.add(n);
    55                         }
    56                         lastN = n;
    57                 }
    58                 if (wnew.nodes.size() < 2) {
    59                         // Empty way, delete
    60                         return DeleteCommand.delete(Collections.singleton(w));
    61                 } else {
    62                         return new ChangeCommand(w, wnew);
    63                 }
    64         }
     43    @Override public Command fixError(TestError testError) {
     44        Way w = (Way) testError.getPrimitives().iterator().next();
     45        Way wnew = new Way(w);
     46        wnew.nodes.clear();
     47        Node lastN = null;
     48        for (Node n : w.nodes) {
     49            if (lastN == null) {
     50                wnew.nodes.add(n);
     51            } else if (n == lastN) {
     52                // Skip this node
     53            } else {
     54                wnew.nodes.add(n);
     55            }
     56            lastN = n;
     57        }
     58        if (wnew.nodes.size() < 2) {
     59            // Empty way, delete
     60            return DeleteCommand.delete(Collections.singleton(w));
     61        } else {
     62            return new ChangeCommand(w, wnew);
     63        }
     64    }
    6565
    66         @Override public boolean isFixable(TestError testError) {
    67                 return testError.getTester() instanceof DuplicatedWayNodes;
    68         }       
     66    @Override public boolean isFixable(TestError testError) {
     67        return testError.getTester() instanceof DuplicatedWayNodes;
     68    }
    6969}
  • applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/NodesWithSameName.java

    r10520 r12778  
    1414
    1515public class NodesWithSameName extends Test {
    16         protected static int SAME_NAME = 801;
     16    protected static int SAME_NAME = 801;
    1717
    18         private Map<String, List<Node>> namesToNodes;
     18    private Map<String, List<Node>> namesToNodes;
    1919
    20         public NodesWithSameName() {
    21                 super(tr("Nodes with same name"),
    22                         tr("This test finds nodes that have the same name (might be duplicates)."));
    23         }
     20    public NodesWithSameName() {
     21        super(tr("Nodes with same name"),
     22            tr("This test finds nodes that have the same name (might be duplicates)."));
     23    }
    2424
    25         @Override public void startTest() {
    26                 namesToNodes = new HashMap<String, List<Node>>();
    27         }
     25    @Override public void startTest() {
     26        namesToNodes = new HashMap<String, List<Node>>();
     27    }
    2828
    29         @Override public void visit(Node n) {
    30                 if (n.deleted || n.incomplete) return;
     29    @Override public void visit(Node n) {
     30        if (n.deleted || n.incomplete) return;
    3131
    32                 String name = n.get("name");
    33                 String sign = n.get("traffic_sign");
    34                 if (name == null || (sign != null && sign.equals("city_limit"))) return;
     32        String name = n.get("name");
     33        String sign = n.get("traffic_sign");
     34        if (name == null || (sign != null && sign.equals("city_limit"))) return;
    3535
    36                 List<Node> nodes = namesToNodes.get(name);
    37                 if (nodes == null)
    38                         namesToNodes.put(name, nodes = new ArrayList<Node>());
     36        List<Node> nodes = namesToNodes.get(name);
     37        if (nodes == null)
     38            namesToNodes.put(name, nodes = new ArrayList<Node>());
    3939
    40                 nodes.add(n);
    41         }
     40        nodes.add(n);
     41    }
    4242
    43         @Override public void endTest() {
    44                 for (List<Node> nodes : namesToNodes.values()) {
    45                         if (nodes.size() > 1) {
    46                                 errors.add(new TestError(this, Severity.OTHER,
    47                                         tr("Nodes with same name"), SAME_NAME, nodes));
    48                         }
    49                 }
     43    @Override public void endTest() {
     44        for (List<Node> nodes : namesToNodes.values()) {
     45            if (nodes.size() > 1) {
     46                errors.add(new TestError(this, Severity.OTHER,
     47                    tr("Nodes with same name"), SAME_NAME, nodes));
     48            }
     49        }
    5050
    51                 namesToNodes = null;
    52         }
     51        namesToNodes = null;
     52    }
    5353}
  • applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/OverlappingWays.java

    r11530 r12778  
    2121/**
    2222 * Tests if there are overlapping ways
    23  * 
     23 *
    2424 * @author frsantos
    2525 */
    2626public class OverlappingWays extends Test
    2727{
    28         /** Bag of all way segments */
    29         Bag<Pair<Node,Node>, WaySegment> nodePairs;
     28    /** Bag of all way segments */
     29    Bag<Pair<Node,Node>, WaySegment> nodePairs;
    3030
    31         protected static int OVERLAPPING_HIGHWAY = 101;
    32         protected static int OVERLAPPING_RAILWAY = 102;
    33         protected static int OVERLAPPING_WAY = 103;
    34         protected static int OVERLAPPING_HIGHWAY_AREA = 111;
    35         protected static int OVERLAPPING_RAILWAY_AREA = 112;
    36         protected static int OVERLAPPING_WAY_AREA = 113;
    37         protected static int OVERLAPPING_AREA = 120;
     31    protected static int OVERLAPPING_HIGHWAY = 101;
     32    protected static int OVERLAPPING_RAILWAY = 102;
     33    protected static int OVERLAPPING_WAY = 103;
     34    protected static int OVERLAPPING_HIGHWAY_AREA = 111;
     35    protected static int OVERLAPPING_RAILWAY_AREA = 112;
     36    protected static int OVERLAPPING_WAY_AREA = 113;
     37    protected static int OVERLAPPING_AREA = 120;
    3838
    39         /** Constructor */
    40         public OverlappingWays()
    41         {
    42                 super(tr("Overlapping ways."),
    43                           tr("This test checks that a connection between two nodes "
    44                                 + "is not used by more than one way."));
    45                
    46         }
     39    /** Constructor */
     40    public OverlappingWays()
     41    {
     42        super(tr("Overlapping ways."),
     43              tr("This test checks that a connection between two nodes "
     44                + "is not used by more than one way."));
     45
     46    }
    4747
    4848
    49         @Override
    50         public void startTest()
    51         {
    52                 nodePairs = new Bag<Pair<Node,Node>, WaySegment>(1000);
    53         }
     49    @Override
     50    public void startTest()
     51    {
     52        nodePairs = new Bag<Pair<Node,Node>, WaySegment>(1000);
     53    }
    5454
    55         @Override
    56         public void endTest()
    57         {
    58                 Map<List<Way>, List<WaySegment>> ways_seen = new HashMap<List<Way>, List<WaySegment>>(500);
     55    @Override
     56    public void endTest()
     57    {
     58        Map<List<Way>, List<WaySegment>> ways_seen = new HashMap<List<Way>, List<WaySegment>>(500);
    5959
    60                 for (List<WaySegment> duplicated : nodePairs.values())
    61                 {
    62                         int ways = duplicated.size();
     60        for (List<WaySegment> duplicated : nodePairs.values())
     61        {
     62            int ways = duplicated.size();
    6363
    64                         if (ways > 1)
    65                         {
    66                                 List<OsmPrimitive> prims = new ArrayList<OsmPrimitive>();
    67                                 List<Way> current_ways = new ArrayList<Way>();
    68                                 List<WaySegment> highlight;
    69                                 int highway = 0;
    70                                 int railway = 0;
    71                                 int area = 0;
     64            if (ways > 1)
     65            {
     66                List<OsmPrimitive> prims = new ArrayList<OsmPrimitive>();
     67                List<Way> current_ways = new ArrayList<Way>();
     68                List<WaySegment> highlight;
     69                int highway = 0;
     70                int railway = 0;
     71                int area = 0;
    7272
    73                                 for (WaySegment ws : duplicated)
    74                                 {
    75                                         if (ws.way.get("highway") != null)
    76                                                 highway++;
    77                                         else if (ws.way.get("railway") != null)
    78                                                 railway++;
    79                                         Boolean ar = OsmUtils.getOsmBoolean(ws.way.get("area"));
    80                                         if (ar != null && ar)
    81                                                 area++;
    82                                         if (ws.way.get("landuse") != null || ws.way.get("natural") != null
    83                                         || ws.way.get("amenity") != null || ws.way.get("leisure") != null
    84                                         || ws.way.get("building") != null)
    85                                         {
    86                                                 area++; ways--;
    87                                         }
     73                for (WaySegment ws : duplicated)
     74                {
     75                    if (ws.way.get("highway") != null)
     76                        highway++;
     77                    else if (ws.way.get("railway") != null)
     78                        railway++;
     79                    Boolean ar = OsmUtils.getOsmBoolean(ws.way.get("area"));
     80                    if (ar != null && ar)
     81                        area++;
     82                    if (ws.way.get("landuse") != null || ws.way.get("natural") != null
     83                    || ws.way.get("amenity") != null || ws.way.get("leisure") != null
     84                    || ws.way.get("building") != null)
     85                    {
     86                        area++; ways--;
     87                    }
    8888
    89                                         prims.add(ws.way);
    90                                         current_ways.add(ws.way);
    91                                 }
    92                                 /* These ways not seen before
    93                                 * If two or more of the overlapping ways are
    94                                 * highways or railways mark a seperate error
    95                                 */
    96                                 if ((highlight = ways_seen.get(current_ways)) == null)
    97                                 {
    98                                         String errortype;
    99                                         int type;
     89                    prims.add(ws.way);
     90                    current_ways.add(ws.way);
     91                }
     92                /* These ways not seen before
     93                * If two or more of the overlapping ways are
     94                * highways or railways mark a seperate error
     95                */
     96                if ((highlight = ways_seen.get(current_ways)) == null)
     97                {
     98                    String errortype;
     99                    int type;
    100100
    101                                         if(area > 0)
    102                                         {
    103                                                 if (ways == 0 || duplicated.size() == area)
    104                                                 {
    105                                                         errortype = tr("Overlapping areas");
    106                                                         type = OVERLAPPING_AREA;
    107                                                 }
    108                                                 else if (highway == ways)
    109                                                 {
    110                                                         errortype = tr("Overlapping highways (with area)");
    111                                                         type = OVERLAPPING_HIGHWAY_AREA;
    112                                                 }
    113                                                 else if (railway == ways)
    114                                                 {
    115                                                         errortype = tr("Overlapping railways (with area)");
    116                                                         type = OVERLAPPING_RAILWAY_AREA;
    117                                                 }
    118                                                 else
    119                                                 {
    120                                                         errortype = tr("Overlapping ways (with area)");
    121                                                         type = OVERLAPPING_WAY_AREA;
    122                                                 }
    123                                         }
    124                                         else if (highway == ways)
    125                                         {
    126                                                 errortype = tr("Overlapping highways");
    127                                                 type = OVERLAPPING_HIGHWAY;
    128                                         }
    129                                         else if (railway == ways)
    130                                         {
    131                                                 errortype = tr("Overlapping railways");
    132                                                 type = OVERLAPPING_RAILWAY;
    133                                         }
    134                                         else
    135                                         {
    136                                                 errortype = tr("Overlapping ways");
    137                                                 type = OVERLAPPING_WAY;
    138                                         }
     101                    if(area > 0)
     102                    {
     103                        if (ways == 0 || duplicated.size() == area)
     104                        {
     105                            errortype = tr("Overlapping areas");
     106                            type = OVERLAPPING_AREA;
     107                        }
     108                        else if (highway == ways)
     109                        {
     110                            errortype = tr("Overlapping highways (with area)");
     111                            type = OVERLAPPING_HIGHWAY_AREA;
     112                        }
     113                        else if (railway == ways)
     114                        {
     115                            errortype = tr("Overlapping railways (with area)");
     116                            type = OVERLAPPING_RAILWAY_AREA;
     117                        }
     118                        else
     119                        {
     120                            errortype = tr("Overlapping ways (with area)");
     121                            type = OVERLAPPING_WAY_AREA;
     122                        }
     123                    }
     124                    else if (highway == ways)
     125                    {
     126                        errortype = tr("Overlapping highways");
     127                        type = OVERLAPPING_HIGHWAY;
     128                    }
     129                    else if (railway == ways)
     130                    {
     131                        errortype = tr("Overlapping railways");
     132                        type = OVERLAPPING_RAILWAY;
     133                    }
     134                    else
     135                    {
     136                        errortype = tr("Overlapping ways");
     137                        type = OVERLAPPING_WAY;
     138                    }
    139139
    140                                         errors.add(new TestError(this, type < OVERLAPPING_HIGHWAY_AREA
    141                                         ? Severity.WARNING : Severity.OTHER, tr(errortype), type, prims, duplicated));
    142                                         ways_seen.put(current_ways, duplicated);
    143                                 }
    144                                 else    /* way seen, mark highlight layer only */
    145                                 {
    146                                         for (WaySegment ws : duplicated)
    147                                                 highlight.add(ws);
    148                                 }
    149                         }
    150                 }
    151                 nodePairs = null;
    152         }
     140                    errors.add(new TestError(this, type < OVERLAPPING_HIGHWAY_AREA
     141                    ? Severity.WARNING : Severity.OTHER, tr(errortype), type, prims, duplicated));
     142                    ways_seen.put(current_ways, duplicated);
     143                }
     144                else    /* way seen, mark highlight layer only */
     145                {
     146                    for (WaySegment ws : duplicated)
     147                        highlight.add(ws);
     148                }
     149            }
     150        }
     151        nodePairs = null;
     152    }
    153153
    154         @Override
    155         public void visit(Way w)
    156         {
    157                 Node lastN = null;
    158                 int i = -2;
    159                 for (Node n : w.nodes) {
    160                         i++;
    161                         if (lastN == null) {
    162                                 lastN = n;
    163                                 continue;
    164                         }
    165                         nodePairs.add(Pair.sort(new Pair<Node,Node>(lastN, n)),
    166                                 new WaySegment(w, i));
    167                         lastN = n;
    168                 }
    169         }
     154    @Override
     155    public void visit(Way w)
     156    {
     157        Node lastN = null;
     158        int i = -2;
     159        for (Node n : w.nodes) {
     160            i++;
     161            if (lastN == null) {
     162                lastN = n;
     163                continue;
     164            }
     165            nodePairs.add(Pair.sort(new Pair<Node,Node>(lastN, n)),
     166                new WaySegment(w, i));
     167            lastN = n;
     168        }
     169    }
    170170}
  • applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/SelfIntersectingWay.java

    r10520 r12778  
    1616 */
    1717public class SelfIntersectingWay extends Test {
    18         protected static int SELF_INTERSECT = 401;
     18    protected static int SELF_INTERSECT = 401;
    1919
    20         public SelfIntersectingWay() {
    21                 super(tr("Self-intersecting ways"),
    22                           tr("This test checks for ways " +
    23                                 "that contain some of their nodes more than once."));
    24         }
     20    public SelfIntersectingWay() {
     21        super(tr("Self-intersecting ways"),
     22              tr("This test checks for ways " +
     23                "that contain some of their nodes more than once."));
     24    }
    2525
    26         @Override public void visit(Way w) {
    27                 HashSet<Node> nodes = new HashSet<Node>();
     26    @Override public void visit(Way w) {
     27        HashSet<Node> nodes = new HashSet<Node>();
    2828
    29                 for (int i = 1; i < w.nodes.size() - 1; i++) {
    30                         Node n = w.nodes.get(i);
    31                         if (nodes.contains(n)) {
    32                                 errors.add(new TestError(this,
    33                                         Severity.WARNING, tr("Self-intersecting ways"), SELF_INTERSECT,
    34                                         Arrays.asList(w), Arrays.asList(n)));
    35                                 break;
    36                         } else {
    37                                 nodes.add(n);
    38                         }
    39                 }
    40         }
     29        for (int i = 1; i < w.nodes.size() - 1; i++) {
     30            Node n = w.nodes.get(i);
     31            if (nodes.contains(n)) {
     32                errors.add(new TestError(this,
     33                    Severity.WARNING, tr("Self-intersecting ways"), SELF_INTERSECT,
     34                    Arrays.asList(w), Arrays.asList(n)));
     35                break;
     36            } else {
     37                nodes.add(n);
     38            }
     39        }
     40    }
    4141}
  • applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/SimilarNamedWays.java

    r9684 r12778  
    2222public class SimilarNamedWays extends Test
    2323{
    24         protected static int SIMILAR_NAMED = 701;
     24    protected static int SIMILAR_NAMED = 701;
    2525
    26         /** All ways, grouped by cells */
    27         Map<Point2D,List<Way>> cellWays;
    28         /** The already detected errors */
    29         Bag<Way, Way> errorWays;
     26    /** All ways, grouped by cells */
     27    Map<Point2D,List<Way>> cellWays;
     28    /** The already detected errors */
     29    Bag<Way, Way> errorWays;
    3030
    31         /**
    32         * Constructor
    33         */
    34         public SimilarNamedWays()
    35         {
    36                 super(tr("Similar named ways."),
    37                           tr("This test checks for ways with similar names that may have been misspelled."));
    38         }
     31    /**
     32    * Constructor
     33    */
     34    public SimilarNamedWays()
     35    {
     36        super(tr("Similar named ways."),
     37              tr("This test checks for ways with similar names that may have been misspelled."));
     38    }
    3939
    40         @Override
    41         public void startTest()
    42         {
    43                 cellWays = new HashMap<Point2D,List<Way>>(1000);
    44                 errorWays = new Bag<Way, Way>();
    45         }
     40    @Override
     41    public void startTest()
     42    {
     43        cellWays = new HashMap<Point2D,List<Way>>(1000);
     44        errorWays = new Bag<Way, Way>();
     45    }
    4646
    47         @Override
    48         public void endTest()
    49         {
    50                 cellWays = null;
    51                 errorWays = null;
    52         }
     47    @Override
     48    public void endTest()
     49    {
     50        cellWays = null;
     51        errorWays = null;
     52    }
    5353
    54         @Override
    55         public void visit(Way w)
    56         {
    57                 if( w.deleted || w.incomplete )
    58                         return;
     54    @Override
     55    public void visit(Way w)
     56    {
     57        if( w.deleted || w.incomplete )
     58            return;
    5959
    60                 String name = w.get("name");
    61                 if( name == null || name.length() < 6 )
    62                         return;
     60        String name = w.get("name");
     61        if( name == null || name.length() < 6 )
     62            return;
    6363
    64                 List<List<Way>> theCellWays = Util.getWaysInCell(w, cellWays);
    65                 for( List<Way> ways : theCellWays)
    66                 {
    67                         for( Way w2 : ways)
    68                         {
    69                                 if( errorWays.contains(w, w2) || errorWays.contains(w2, w) )
    70                                         continue;
     64        List<List<Way>> theCellWays = Util.getWaysInCell(w, cellWays);
     65        for( List<Way> ways : theCellWays)
     66        {
     67            for( Way w2 : ways)
     68            {
     69                if( errorWays.contains(w, w2) || errorWays.contains(w2, w) )
     70                    continue;
    7171
    72                                 String name2 = w2.get("name");
    73                                 if( name2 == null || name2.length() < 6 )
    74                                         continue;
     72                String name2 = w2.get("name");
     73                if( name2 == null || name2.length() < 6 )
     74                    continue;
    7575
    76                                 int levenshteinDistance = getLevenshteinDistance(name, name2);
    77                                 if( 0 < levenshteinDistance && levenshteinDistance <= 2 )
    78                                 {
    79                                         List<OsmPrimitive> primitives = new ArrayList<OsmPrimitive>();
    80                                         primitives.add(w);
    81                                         primitives.add(w2);
    82                                         errors.add( new TestError(this, Severity.WARNING, tr("Similar named ways"), SIMILAR_NAMED, primitives) );
    83                                         errorWays.add(w, w2);
    84                                 }
    85                         }
    86                         ways.add(w);
    87                 }
    88         }
     76                int levenshteinDistance = getLevenshteinDistance(name, name2);
     77                if( 0 < levenshteinDistance && levenshteinDistance <= 2 )
     78                {
     79                    List<OsmPrimitive> primitives = new ArrayList<OsmPrimitive>();
     80                    primitives.add(w);
     81                    primitives.add(w2);
     82                    errors.add( new TestError(this, Severity.WARNING, tr("Similar named ways"), SIMILAR_NAMED, primitives) );
     83                    errorWays.add(w, w2);
     84                }
     85            }
     86            ways.add(w);
     87        }
     88    }
    8989
    90         /**
    91         * Compute Levenshtein distance
    92         *
    93         * @param s First word
    94         * @param t Second word
    95         * @return The distance between words
    96         */
    97         public int getLevenshteinDistance(String s, String t)
    98         {
    99                 int d[][]; // matrix
    100                 int n; // length of s
    101                 int m; // length of t
    102                 int i; // iterates through s
    103                 int j; // iterates through t
    104                 char s_i; // ith character of s
    105                 char t_j; // jth character of t
    106                 int cost; // cost
     90    /**
     91    * Compute Levenshtein distance
     92    *
     93    * @param s First word
     94    * @param t Second word
     95    * @return The distance between words
     96    */
     97    public int getLevenshteinDistance(String s, String t)
     98    {
     99        int d[][]; // matrix
     100        int n; // length of s
     101        int m; // length of t
     102        int i; // iterates through s
     103        int j; // iterates through t
     104        char s_i; // ith character of s
     105        char t_j; // jth character of t
     106        int cost; // cost
    107107
    108                 // Step 1
     108        // Step 1
    109109
    110                 n = s.length();
    111                 m = t.length();
    112                 if (n == 0) return m;
    113                 if (m == 0) return n;
    114                 d = new int[n + 1][m + 1];
     110        n = s.length();
     111        m = t.length();
     112        if (n == 0) return m;
     113        if (m == 0) return n;
     114        d = new int[n + 1][m + 1];
    115115
    116                 // Step 2
    117                 for (i = 0; i <= n; i++) d[i][0] = i;
    118                 for (j = 0; j <= m; j++) d[0][j] = j;
     116        // Step 2
     117        for (i = 0; i <= n; i++) d[i][0] = i;
     118        for (j = 0; j <= m; j++) d[0][j] = j;
    119119
    120                 // Step 3
    121                 for (i = 1; i <= n; i++)
    122                 {
    123                         s_i = s.charAt(i - 1);
     120        // Step 3
     121        for (i = 1; i <= n; i++)
     122        {
     123            s_i = s.charAt(i - 1);
    124124
    125                         // Step 4
    126                         for (j = 1; j <= m; j++)
    127                         {
    128                                 t_j = t.charAt(j - 1);
     125            // Step 4
     126            for (j = 1; j <= m; j++)
     127            {
     128                t_j = t.charAt(j - 1);
    129129
    130                                 // Step 5
    131                                 if (s_i == t_j)
    132                                 {
    133                                         cost = 0;
    134                                 }
    135                                 else
    136                                 {
    137                                         cost = 1;
    138                                 }
     130                // Step 5
     131                if (s_i == t_j)
     132                {
     133                    cost = 0;
     134                }
     135                else
     136                {
     137                    cost = 1;
     138                }
    139139
    140                                 // Step 6
    141                                 d[i][j] = Minimum(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost);
    142                         }
    143                 }
     140                // Step 6
     141                d[i][j] = Minimum(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost);
     142            }
     143        }
    144144
    145                 // Step 7
    146                 return d[n][m];
    147         }
     145        // Step 7
     146        return d[n][m];
     147    }
    148148
    149         /**
    150         * Get minimum of three values
    151         * @param a First value
    152         * @param b Second value
    153         * @param c Third value
    154         * @return The minimum of the tre values
    155         */
    156         private static int Minimum(int a, int b, int c)
    157         {
    158                 int mi = a;
    159                 if (b < mi)
    160                 {
    161                         mi = b;
    162                 }
    163                 if (c < mi)
    164                 {
    165                         mi = c;
    166                 }
    167                 return mi;
    168         }
     149    /**
     150    * Get minimum of three values
     151    * @param a First value
     152    * @param b Second value
     153    * @param c Third value
     154    * @return The minimum of the tre values
     155    */
     156    private static int Minimum(int a, int b, int c)
     157    {
     158        int mi = a;
     159        if (b < mi)
     160        {
     161            mi = b;
     162        }
     163        if (c < mi)
     164        {
     165            mi = c;
     166        }
     167        return mi;
     168    }
    169169}
  • applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/TagChecker.java

    r12777 r12778  
    6363public class TagChecker extends Test
    6464{
    65         /** The default data files */
    66         public static final String DATA_FILE = "http://svn.openstreetmap.org/applications/editors/josm/plugins/validator/tagchecker.cfg";
    67         public static final String SPELL_FILE = "http://svn.openstreetmap.org/applications/utils/planet.osm/java/speller/words.cfg";
    68 
    69         /** The spell check key substitutions: the key should be substituted by the value */
    70         protected static Map<String, String> spellCheckKeyData;
    71         /** The spell check preset values */
    72         protected static Bag<String, String> presetsValueData;
    73         /** The TagChecker data */
    74         protected static List<CheckerData> checkerData = new ArrayList<CheckerData>();
    75 
    76         /** The preferences prefix */
    77         protected static final String PREFIX = PreferenceEditor.PREFIX + "." + TagChecker.class.getSimpleName();
    78 
    79         public static final String PREF_CHECK_VALUES = PREFIX + ".checkValues";
    80         public static final String PREF_CHECK_KEYS = PREFIX + ".checkKeys";
    81         public static final String PREF_CHECK_COMPLEX = PREFIX + ".checkComplex";
    82         public static final String PREF_CHECK_FIXMES = PREFIX + ".checkFixmes";
    83         public static final String PREF_CHECK_PAINT = PREFIX + ".paint";
    84 
    85         public static final String PREF_SOURCES = PREFIX + ".sources";
    86         public static final String PREF_USE_DATA_FILE = PREFIX + ".usedatafile";
    87         public static final String PREF_USE_SPELL_FILE = PREFIX + ".usespellfile";
    88 
    89         public static final String PREF_CHECK_KEYS_BEFORE_UPLOAD = PREF_CHECK_KEYS + "BeforeUpload";
    90         public static final String PREF_CHECK_VALUES_BEFORE_UPLOAD = PREF_CHECK_VALUES + "BeforeUpload";
    91         public static final String PREF_CHECK_COMPLEX_BEFORE_UPLOAD = PREF_CHECK_COMPLEX + "BeforeUpload";
    92         public static final String PREF_CHECK_FIXMES_BEFORE_UPLOAD = PREF_CHECK_FIXMES + "BeforeUpload";
    93         public static final String PREF_CHECK_PAINT_BEFORE_UPLOAD = PREF_CHECK_PAINT + "BeforeUpload";
    94 
    95         protected boolean checkKeys = false;
    96         protected boolean checkValues = false;
    97         protected boolean checkComplex = false;
    98         protected boolean checkFixmes = false;
    99         protected boolean checkPaint = false;
    100 
    101         protected JCheckBox prefCheckKeys;
    102         protected JCheckBox prefCheckValues;
    103         protected JCheckBox prefCheckComplex;
    104         protected JCheckBox prefCheckFixmes;
    105         protected JCheckBox prefCheckPaint;
    106 
    107         protected JCheckBox prefCheckKeysBeforeUpload;
    108         protected JCheckBox prefCheckValuesBeforeUpload;
    109         protected JCheckBox prefCheckComplexBeforeUpload;
    110         protected JCheckBox prefCheckFixmesBeforeUpload;
    111         protected JCheckBox prefCheckPaintBeforeUpload;
    112 
    113         protected JCheckBox prefUseDataFile;
    114         protected JCheckBox prefUseSpellFile;
    115 
    116         protected JButton addSrcButton;
    117         protected JButton editSrcButton;
    118         protected JButton deleteSrcButton;
    119 
    120         protected static int EMPTY_VALUES      = 1200;
    121         protected static int INVALID_KEY       = 1201;
    122         protected static int INVALID_VALUE     = 1202;
    123         protected static int FIXME             = 1203;
    124         protected static int INVALID_SPACE     = 1204;
    125         protected static int INVALID_KEY_SPACE = 1205;
    126         protected static int INVALID_HTML      = 1206;
    127         protected static int PAINT             = 1207;
    128         /** 1250 and up is used by tagcheck */
    129 
    130         /** List of sources for spellcheck data */
    131         protected JList Sources;
    132 
    133        
    134         protected static Entities entities = new Entities();
    135         /**
    136         * Constructor
    137         */
    138         public TagChecker()
    139         {
    140                 super(tr("Properties checker :"),
    141                           tr("This plugin checks for errors in property keys and values."));
    142         }
    143 
    144         public static void initialize(OSMValidatorPlugin plugin) throws Exception
    145         {
    146                 initializeData();
    147                 initializePresets();
    148         }
    149 
    150         /**
    151         * Reads the spellcheck file into a HashMap.
    152         * The data file is a list of words, beginning with +/-. If it starts with +,
    153         * the word is valid, but if it starts with -, the word should be replaced
    154         * by the nearest + word before this.
    155         *
    156         * @throws FileNotFoundException
    157         * @throws IOException
    158         */
    159         private static void initializeData() throws IOException
    160         {
    161                 spellCheckKeyData = new HashMap<String, String>();
    162                 String sources = Main.pref.get( PREF_SOURCES, "");
    163                 if(Main.pref.getBoolean(PREF_USE_DATA_FILE, true))
    164                 {
    165                         if( sources == null || sources.length() == 0)
    166                                 sources = DATA_FILE;
    167                         else
    168                                 sources = DATA_FILE + ";" + sources;
    169                 }
    170                 if(Main.pref.getBoolean(PREF_USE_SPELL_FILE, true))
    171                 {
    172                         if( sources == null || sources.length() == 0)
    173                                 sources = SPELL_FILE;
    174                         else
    175                                 sources = SPELL_FILE + ";" + sources;
    176                 }
    177 
    178                 String errorSources = "";
    179                 if(sources.length() == 0)
    180                         return;
    181                 for(String source: sources.split(";"))
    182                 {
    183                         try
    184                         {
    185                                 MirroredInputStream s = new MirroredInputStream(source, Util.getPluginDir(), -1);
    186                                 InputStreamReader r;
    187                                 try
    188                                 {
    189                                         r = new InputStreamReader(s, "UTF-8");
    190                                 }
    191                                 catch (UnsupportedEncodingException e)
    192                                 {
    193                                         r = new InputStreamReader(s);
    194                                 }
    195                                 BufferedReader reader = new BufferedReader(r);
    196 
    197                                 String okValue = null;
    198                                 Boolean tagcheckerfile = false;
    199                                 String line;
    200                                 while((line = reader.readLine()) != null && (tagcheckerfile || line.length() != 0))
    201                                 {
    202                                         if(line.startsWith("#"))
    203                                         {
    204                                                 if(line.startsWith("# JOSM TagChecker"))
    205                                                         tagcheckerfile = true;
    206                                         }
    207                                         else if(tagcheckerfile)
    208                                         {
    209                                                 if(line.length() > 0)
    210                                                 {
    211                                                         CheckerData d = new CheckerData();
    212                                                         String err = d.getData(line);
    213 
    214                                                         if(err == null)
    215                                                                 checkerData.add(d);
    216                                                         else
    217                                                                 System.err.println(tr("Invalid tagchecker line - {0}: {1}", err, line));
    218                                                 }
    219                                         }
    220                                         else if(line.charAt(0) == '+')
    221                                         {
    222                                                 okValue = line.substring(1);
    223                                         }
    224                                         else if(line.charAt(0) == '-' && okValue != null)
    225                                         {
    226                                                 spellCheckKeyData.put(line.substring(1), okValue);
    227                                         }
    228                                         else
    229                                         {
    230                                                 System.err.println(tr("Invalid spellcheck line: {0}", line));
    231                                         }
    232                                 }
    233                         }
    234                         catch (IOException e)
    235                         {
    236                                 errorSources += source + "\n";
    237                         }
    238                 }
    239 
    240                 if( errorSources.length() > 0 )
    241                         throw new IOException( tr("Could not access data file(s):\n{0}", errorSources) );
    242         }
    243 
    244         /**
    245         * Reads the presets data.
    246         *
    247         * @throws Exception
    248         */
    249         public static void initializePresets() throws Exception
    250         {
    251                 if( !Main.pref.getBoolean(PREF_CHECK_VALUES, true) )
    252                         return;
    253 
    254                 Collection<TaggingPreset> presets = TaggingPresetPreference.taggingPresets;
    255                 if(presets != null)
    256                 {
    257                         presetsValueData = new Bag<String, String>();
    258                         for(TaggingPreset p : presets)
    259                         {
    260                                 for(TaggingPreset.Item i : p.data)
    261                                 {
    262                                         if(i instanceof TaggingPreset.Combo)
    263                                         {
    264                                                 TaggingPreset.Combo combo = (TaggingPreset.Combo) i;
    265                                                 for(String value : combo.values.split(","))
    266                                                         presetsValueData.add(combo.key, value);
    267                                         }
    268                                         else if(i instanceof TaggingPreset.Key)
    269                                         {
    270                                                 TaggingPreset.Key k = (TaggingPreset.Key) i;
    271                                                 presetsValueData.add(k.key, k.value);
    272                                         }
    273                                 }
    274                         }
    275                 }
    276         }
    277 
    278         @Override
    279         public void visit(Node n)
    280         {
    281                 checkPrimitive(n);
    282         }
    283 
    284 
    285         @Override
    286         public void visit(Relation n)
    287         {
    288                 checkPrimitive(n);
    289         }
    290 
    291 
    292         @Override
    293         public void visit(Way w)
    294         {
    295                 checkPrimitive(w);
    296         }
    297 
    298         /**
    299         * Checks the primitive properties
    300         * @param p The primitive to check
    301         */
    302         private void checkPrimitive(OsmPrimitive p)
    303         {
    304                 // Just a collection to know if a primitive has been already marked with error
    305                 Bag<OsmPrimitive, String> withErrors = new Bag<OsmPrimitive, String>();
    306 
    307                 if(checkComplex)
    308                 {
    309                         for(CheckerData d : checkerData)
    310                         {
    311                                 if(d.match(p))
    312                                 {
    313                                         errors.add( new TestError(this, d.getSeverity(), tr("Illegal tag/value combinations"),
    314                                         d.getDescription(), d.getDescriptionOrig(), d.getCode(), p) );
    315                                         withErrors.add(p, "TC");
    316                                         break;
    317                                 }
    318                         }
    319                 }
    320                 if(checkPaint && p.errors != null)
    321                 {
    322                         for(String s: p.errors)
    323                         {
    324                                 /* passing translated text also to original string, as we already
    325                                 translated the stuff before. Makes the ignore file language dependend. */
    326                                 errors.add( new TestError(this, Severity.WARNING, tr("Painting problem"),
    327                                 s, s, PAINT, p) );
    328                                 withErrors.add(p, "P");
    329                         }
    330                 }
    331 
    332                 Map<String, String> props = (p.keys == null) ? Collections.<String, String>emptyMap() : p.keys;
    333                 for(Entry<String, String> prop: props.entrySet() )
    334                 {
    335                         String s = marktr("Key ''{0}'' invalid.");
    336                         String key = prop.getKey();
    337                         String value = prop.getValue();
    338                         if( checkValues && (value==null || value.trim().length() == 0) && !withErrors.contains(p, "EV"))
    339                         {
    340                                 errors.add( new TestError(this, Severity.WARNING, tr("Tags with empty values"),
    341                                 tr(s, key), MessageFormat.format(s, key), EMPTY_VALUES, p) );
    342                                 withErrors.add(p, "EV");
    343                         }
    344                         if( checkKeys && spellCheckKeyData.containsKey(key) && !withErrors.contains(p, "IPK"))
    345                         {
    346                                 errors.add( new TestError(this, Severity.WARNING, tr("Invalid property key"),
    347                                 tr(s, key), MessageFormat.format(s, key), INVALID_KEY, p) );
    348                                 withErrors.add(p, "IPK");
    349                         }
    350                         if( checkKeys && key.indexOf(" ") >= 0 && !withErrors.contains(p, "IPK"))
    351                         {
    352                                 errors.add( new TestError(this, Severity.WARNING, tr("Invalid white space in property key"),
    353                                 tr(s, key), MessageFormat.format(s, key), INVALID_KEY_SPACE, p) );
    354                                 withErrors.add(p, "IPK");
    355                         }
    356                         if( checkValues && value != null && (value.startsWith(" ") || value.endsWith(" ")) && !withErrors.contains(p, "SPACE"))
    357                         {
    358                                 errors.add( new TestError(this, Severity.OTHER, tr("Property values start or end with white space"),
    359                                 tr(s, key), MessageFormat.format(s, key), INVALID_SPACE, p) );
    360                                 withErrors.add(p, "SPACE");
    361                         }
    362                         if( checkValues && value != null && !value.equals(entities.unescape(value)) && !withErrors.contains(p, "HTML"))
    363                         {
    364                                 errors.add( new TestError(this, Severity.OTHER, tr("Property values contain HTML entity"),
    365                                 tr(s, key), MessageFormat.format(s, key), INVALID_HTML, p) );
    366                                 withErrors.add(p, "HTML");
    367                         }
    368                         if( checkValues && value != null && value.length() > 0 && presetsValueData != null)
    369                         {
    370                                 List<String> values = presetsValueData.get(key);
    371                                 if( values != null && !values.contains(prop.getValue()) && !withErrors.contains(p, "UPV"))
    372                                 {
    373                                         String i = marktr("Key ''{0}'' unknown.");
    374                                         errors.add( new TestError(this, Severity.OTHER, tr("Unknown property values"),
    375                                         tr(i, key), MessageFormat.format(i, key), INVALID_VALUE, p) );
    376                                         withErrors.add(p, "UPV");
    377                                 }
    378                         }
    379                         if( checkFixmes && value != null && value.length() > 0 )
    380                         {
    381                                 if( (value.contains("FIXME") || value.contains("check and delete") || key.contains("todo") || key.contains("fixme"))
    382                                 && !withErrors.contains(p, "FIXME"))
    383                                 {
    384                                         errors.add( new TestError(this, Severity.OTHER, tr("FIXMES"), FIXME, p) );
    385                                         withErrors.add(p, "FIXME");
    386                                 }
    387                         }
    388                 }
    389         }
    390 
    391         @Override
    392         public void startTest()
    393         {
    394                 checkKeys = Main.pref.getBoolean(PREF_CHECK_KEYS, true);
    395                 if( isBeforeUpload )
    396                         checkKeys = checkKeys && Main.pref.getBoolean(PREF_CHECK_KEYS_BEFORE_UPLOAD, true);
    397 
    398                 checkValues = Main.pref.getBoolean(PREF_CHECK_VALUES, true);
    399                 if( isBeforeUpload )
    400                         checkValues = checkValues && Main.pref.getBoolean(PREF_CHECK_VALUES_BEFORE_UPLOAD, true);
    401 
    402                 checkComplex = Main.pref.getBoolean(PREF_CHECK_COMPLEX, true);
    403                 if( isBeforeUpload )
    404                         checkComplex = checkValues && Main.pref.getBoolean(PREF_CHECK_COMPLEX_BEFORE_UPLOAD, true);
    405 
    406                 checkFixmes = Main.pref.getBoolean(PREF_CHECK_FIXMES, true);
    407                 if( isBeforeUpload )
    408                         checkFixmes = checkFixmes && Main.pref.getBoolean(PREF_CHECK_FIXMES_BEFORE_UPLOAD, true);
    409 
    410                 checkPaint = Main.pref.getBoolean(PREF_CHECK_PAINT, true);
    411                 if( isBeforeUpload )
    412                         checkPaint = checkPaint && Main.pref.getBoolean(PREF_CHECK_PAINT_BEFORE_UPLOAD, true);
    413         }
    414 
    415         @Override
    416         public void visit(Collection<OsmPrimitive> selection)
    417         {
    418                 if( checkKeys || checkValues || checkComplex)
    419                         super.visit(selection);
    420         }
    421 
    422         @Override
    423         public void addGui(JPanel testPanel)
    424         {
    425                 GBC a = GBC.eol();
    426                 a.anchor = GBC.EAST;
    427 
    428                 testPanel.add( new JLabel(name), GBC.eol().insets(3,0,0,0) );
    429 
    430                 prefCheckKeys = new JCheckBox(tr("Check property keys."), Main.pref.getBoolean(PREF_CHECK_KEYS, true));
    431                 prefCheckKeys.setToolTipText(tr("Validate that property keys are valid checking against list of words."));
    432                 testPanel.add(prefCheckKeys, GBC.std().insets(20,0,0,0));
    433 
    434                 prefCheckKeysBeforeUpload = new JCheckBox();
    435                 prefCheckKeysBeforeUpload.setSelected(Main.pref.getBoolean(PREF_CHECK_KEYS_BEFORE_UPLOAD, true));
    436                 testPanel.add(prefCheckKeysBeforeUpload, a);
    437 
    438                 prefCheckComplex = new JCheckBox(tr("Use complex property checker."), Main.pref.getBoolean(PREF_CHECK_COMPLEX, true));
    439                 prefCheckComplex.setToolTipText(tr("Validate property values and tags using complex rules."));
    440                 testPanel.add(prefCheckComplex, GBC.std().insets(20,0,0,0));
    441 
    442                 prefCheckComplexBeforeUpload = new JCheckBox();
    443                 prefCheckComplexBeforeUpload.setSelected(Main.pref.getBoolean(PREF_CHECK_COMPLEX_BEFORE_UPLOAD, true));
    444                 testPanel.add(prefCheckComplexBeforeUpload, a);
    445 
    446                 Sources = new JList(new DefaultListModel());
    447 
    448                 String sources = Main.pref.get( PREF_SOURCES );
    449                 if(sources != null && sources.length() > 0)
    450                 {
    451                         for(String source : sources.split(";"))
    452                                 ((DefaultListModel)Sources.getModel()).addElement(source);
    453                 }
    454 
    455                 addSrcButton = new JButton(tr("Add"));
    456                 addSrcButton.addActionListener(new ActionListener(){
    457                         public void actionPerformed(ActionEvent e) {
    458                                 String source = JOptionPane.showInputDialog(Main.parent, tr("TagChecker source"));
    459                                 if (source != null)
    460                                         ((DefaultListModel)Sources.getModel()).addElement(source);
    461                                 Sources.clearSelection();
    462                         }
    463                 });
    464 
    465                 editSrcButton = new JButton(tr("Edit"));
    466                 editSrcButton.addActionListener(new ActionListener(){
    467                         public void actionPerformed(ActionEvent e) {
    468                                 int row = Sources.getSelectedIndex();
    469                                 if(row == -1 && Sources.getModel().getSize() == 1)
    470                                 {
    471                                         Sources.setSelectedIndex(0);
    472                                         row = 0;
    473                                 }
    474                                 if (row == -1)
    475                                 {
    476                                         if(Sources.getModel().getSize() == 0)
    477                                         {
    478                                                 String source = JOptionPane.showInputDialog(Main.parent, tr("TagChecker source"));
    479                                                 if (source != null)
    480                                                         ((DefaultListModel)Sources.getModel()).addElement(source);
    481                                         }
    482                                         else
    483                                         {
    484                                                 JOptionPane.showMessageDialog(Main.parent, tr("Please select the row to edit."));
    485                                         }
    486                                 }
    487                                 else {
    488                                         String source = JOptionPane.showInputDialog(Main.parent, tr("TagChecker source"), Sources.getSelectedValue());
    489                                         if (source != null)
    490                                                 ((DefaultListModel)Sources.getModel()).setElementAt(source, row);
    491                                 }
    492                                 Sources.clearSelection();
    493                         }
    494                 });
    495 
    496                 deleteSrcButton = new JButton(tr("Delete"));
    497                 deleteSrcButton.addActionListener(new ActionListener(){
    498                         public void actionPerformed(ActionEvent e) {
    499                                 if (Sources.getSelectedIndex() == -1)
    500                                         JOptionPane.showMessageDialog(Main.parent, tr("Please select the row to delete."));
    501                                 else {
    502                                         ((DefaultListModel)Sources.getModel()).remove(Sources.getSelectedIndex());
    503                                 }
    504                         }
    505                 });
    506                 Sources.setMinimumSize(new Dimension(300,50));
    507                 Sources.setVisibleRowCount(3);
    508 
    509                 Sources.setToolTipText(tr("The sources (URL or filename) of spell check (see http://wiki.openstreetmap.org/index.php/User:JLS/speller) or tag checking data files."));
    510                 addSrcButton.setToolTipText(tr("Add a new source to the list."));
    511                 editSrcButton.setToolTipText(tr("Edit the selected source."));
    512                 deleteSrcButton.setToolTipText(tr("Delete the selected source from the list."));
    513 
    514                 testPanel.add(new JLabel(tr("Data sources")), GBC.eol().insets(23,0,0,0));
    515                 testPanel.add(new JScrollPane(Sources), GBC.eol().insets(23,0,0,0).fill(GBC.HORIZONTAL));
    516                 final JPanel buttonPanel = new JPanel(new GridBagLayout());
    517                 testPanel.add(buttonPanel, GBC.eol().fill(GBC.HORIZONTAL));
    518                 buttonPanel.add(addSrcButton, GBC.std().insets(0,5,0,0));
    519                 buttonPanel.add(editSrcButton, GBC.std().insets(5,5,5,0));
    520                 buttonPanel.add(deleteSrcButton, GBC.std().insets(0,5,0,0));
    521 
    522                 ActionListener disableCheckActionListener = new ActionListener(){
    523                         public void actionPerformed(ActionEvent e) {
    524                                 handlePrefEnable();
    525                         }
    526                 };
    527                 prefCheckKeys.addActionListener(disableCheckActionListener);
    528                 prefCheckKeysBeforeUpload.addActionListener(disableCheckActionListener);
    529                 prefCheckComplex.addActionListener(disableCheckActionListener);
    530                 prefCheckComplexBeforeUpload.addActionListener(disableCheckActionListener);
    531 
    532                 handlePrefEnable();
    533 
    534                 prefCheckValues = new JCheckBox(tr("Check property values."), Main.pref.getBoolean(PREF_CHECK_VALUES, true));
    535                 prefCheckValues.setToolTipText(tr("Validate that property values are valid checking against presets."));
    536                 testPanel.add(prefCheckValues, GBC.std().insets(20,0,0,0));
    537 
    538                 prefCheckValuesBeforeUpload = new JCheckBox();
    539                 prefCheckValuesBeforeUpload.setSelected(Main.pref.getBoolean(PREF_CHECK_VALUES_BEFORE_UPLOAD, true));
    540                 testPanel.add(prefCheckValuesBeforeUpload, a);
    541 
    542                 prefCheckFixmes = new JCheckBox(tr("Check for FIXMES."), Main.pref.getBoolean(PREF_CHECK_FIXMES, true));
    543                 prefCheckFixmes.setToolTipText(tr("Looks for nodes or ways with FIXME in any property value."));
    544                 testPanel.add(prefCheckFixmes, GBC.std().insets(20,0,0,0));
    545 
    546                 prefCheckFixmesBeforeUpload = new JCheckBox();
    547                 prefCheckFixmesBeforeUpload.setSelected(Main.pref.getBoolean(PREF_CHECK_FIXMES_BEFORE_UPLOAD, true));
    548                 testPanel.add(prefCheckFixmesBeforeUpload, a);
    549 
    550                 prefCheckPaint = new JCheckBox(tr("Check for paint notes."), Main.pref.getBoolean(PREF_CHECK_PAINT, true));
    551                 prefCheckPaint.setToolTipText(tr("Check if map paining found data errors."));
    552                 testPanel.add(prefCheckPaint, GBC.std().insets(20,0,0,0));
    553 
    554                 prefCheckPaintBeforeUpload = new JCheckBox();
    555                 prefCheckPaintBeforeUpload.setSelected(Main.pref.getBoolean(PREF_CHECK_PAINT_BEFORE_UPLOAD, true));
    556                 testPanel.add(prefCheckPaintBeforeUpload, a);
    557 
    558                 prefUseDataFile = new JCheckBox(tr("Use default data file."), Main.pref.getBoolean(PREF_USE_DATA_FILE, true));
    559                 prefUseDataFile.setToolTipText(tr("Use the default data file (recommended)."));
    560                 testPanel.add(prefUseDataFile, GBC.eol().insets(20,0,0,0));
    561 
    562                 prefUseSpellFile = new JCheckBox(tr("Use default spellcheck file."), Main.pref.getBoolean(PREF_USE_SPELL_FILE, true));
    563                 prefUseSpellFile.setToolTipText(tr("Use the default spellcheck file (recommended)."));
    564                 testPanel.add(prefUseSpellFile, GBC.eol().insets(20,0,0,0));
    565         }
    566 
    567         public void handlePrefEnable()
    568         {
    569                 boolean selected = prefCheckKeys.isSelected() || prefCheckKeysBeforeUpload.isSelected()
    570                 || prefCheckComplex.isSelected() || prefCheckComplexBeforeUpload.isSelected();
    571                 Sources.setEnabled( selected );
    572                 addSrcButton.setEnabled(selected);
    573                 editSrcButton.setEnabled(selected);
    574                 deleteSrcButton.setEnabled(selected);
    575         }
    576 
    577         @Override
    578         public boolean ok()
    579         {
    580                 enabled = prefCheckKeys.isSelected() || prefCheckValues.isSelected() || prefCheckComplex.isSelected() || prefCheckFixmes.isSelected();
    581                 testBeforeUpload = prefCheckKeysBeforeUpload.isSelected() || prefCheckValuesBeforeUpload.isSelected()
    582                 || prefCheckFixmesBeforeUpload.isSelected() || prefCheckComplexBeforeUpload.isSelected();
    583 
    584                 Main.pref.put(PREF_CHECK_VALUES, prefCheckValues.isSelected());
    585                 Main.pref.put(PREF_CHECK_COMPLEX, prefCheckComplex.isSelected());
    586                 Main.pref.put(PREF_CHECK_KEYS, prefCheckKeys.isSelected());
    587                 Main.pref.put(PREF_CHECK_FIXMES, prefCheckFixmes.isSelected());
    588                 Main.pref.put(PREF_CHECK_PAINT, prefCheckPaint.isSelected());
    589                 Main.pref.put(PREF_CHECK_VALUES_BEFORE_UPLOAD, prefCheckValuesBeforeUpload.isSelected());
    590                 Main.pref.put(PREF_CHECK_COMPLEX_BEFORE_UPLOAD, prefCheckComplexBeforeUpload.isSelected());
    591                 Main.pref.put(PREF_CHECK_KEYS_BEFORE_UPLOAD, prefCheckKeysBeforeUpload.isSelected());
    592                 Main.pref.put(PREF_CHECK_FIXMES_BEFORE_UPLOAD, prefCheckFixmesBeforeUpload.isSelected());
    593                 Main.pref.put(PREF_CHECK_PAINT_BEFORE_UPLOAD, prefCheckPaintBeforeUpload.isSelected());
    594                 Main.pref.put(PREF_USE_DATA_FILE, prefUseDataFile.isSelected());
    595                 Main.pref.put(PREF_USE_SPELL_FILE, prefUseSpellFile.isSelected());
    596                 String sources = "";
    597                 if( Sources.getModel().getSize() > 0 )
    598                 {
    599                         String sb = "";
    600                         for (int i = 0; i < Sources.getModel().getSize(); ++i)
    601                                 sb += ";"+Sources.getModel().getElementAt(i);
    602                         sources = sb.substring(1);
    603                 }
    604                 if(sources.length() == 0)
    605                         sources = null;
    606                 return Main.pref.put(PREF_SOURCES, sources);
    607         }
    608 
    609         @Override
    610         public Command fixError(TestError testError)
    611         {
    612                 List<Command> commands = new ArrayList<Command>(50);
    613 
    614                 int i = -1;
    615                 List<? extends OsmPrimitive> primitives = testError.getPrimitives();
    616                 for(OsmPrimitive p : primitives )
    617                 {
    618                         i++;
    619                         Map<String, String> tags = p.keys;
    620                         if( tags == null || tags.size() == 0 )
    621                                 continue;
    622 
    623                         for(Entry<String, String> prop: tags.entrySet() )
    624                         {
    625                                 String key = prop.getKey();
    626                                 String value = prop.getValue();
    627                                 if( value == null || value.trim().length() == 0 )
    628                                         commands.add( new ChangePropertyCommand(Collections.singleton(primitives.get(i)), key, null) );
    629                                 else if(value.startsWith(" ") || value.endsWith(" "))
    630                                         commands.add( new ChangePropertyCommand(Collections.singleton(primitives.get(i)), key, value.trim()) );
    631                                 else if(key.startsWith(" ") || key.endsWith(" "))
    632                                         commands.add( new ChangePropertyKeyCommand(Collections.singleton(primitives.get(i)), key, key.trim()) );
    633                                 else
    634                                 {
    635                                         String evalue = entities.unescape(value);
    636                                         if(!evalue.equals(value))
    637                                                 commands.add( new ChangePropertyCommand(Collections.singleton(primitives.get(i)), key, evalue) );
    638                                         else
    639                                         {
    640                                                 String replacementKey = spellCheckKeyData.get(key);
    641                                                 if( replacementKey != null )
    642                                                 {
    643                                                         commands.add( new ChangePropertyKeyCommand(Collections.singleton(primitives.get(i)),
    644                                                         key, replacementKey) );
    645                                                 }
    646                                         }
    647                                 }
    648                         }
    649                 }
    650 
    651                 if( commands.size() == 0 )
    652                         return null;
    653                 else if( commands.size() == 1 )
    654                         return commands.get(0);
    655                 else
    656                         return new SequenceCommand(tr("Fix properties"), commands);
    657         }
    658 
    659         @Override
    660         public boolean isFixable(TestError testError)
    661         {
    662                 if( testError.getTester() instanceof TagChecker)
    663                 {
    664                         int code = testError.getCode();
    665                         return code == INVALID_KEY || code == EMPTY_VALUES || code == INVALID_SPACE || code == INVALID_KEY_SPACE || code == INVALID_HTML;
    666                 }
    667 
    668                 return false;
    669         }
    670 
    671         private static class CheckerData {
    672                 private String description;
    673                 private List<CheckerElement> data = new ArrayList<CheckerElement>();
    674                 private Integer type = 0;
    675                 private Integer code;
    676                 protected Severity severity;
    677                 protected static int NODE = 1;
    678                 protected static int WAY = 2;
    679                 protected static int RELATION = 3;
    680                 protected static int ALL = 4;
    681                 protected static int TAG_CHECK_ERROR  = 1250;
    682                 protected static int TAG_CHECK_WARN   = 1260;
    683                 protected static int TAG_CHECK_INFO   = 1270;
    684 
    685                 private class CheckerElement {
    686                         public Object tag;
    687                         public Object value;
    688                         public Boolean noMatch;
    689                         public Boolean tagAll = false;
    690                         public Boolean valueAll = false;
    691                         public Boolean valueBool = false;
    692                         private Pattern getPattern(String str) throws IllegalStateException, PatternSyntaxException
    693                         {
    694                                 if(str.endsWith("/i"))
    695                                         return Pattern.compile(str.substring(1,str.length()-2), Pattern.CASE_INSENSITIVE);
    696                                 else if(str.endsWith("/"))
    697                                         return Pattern.compile(str.substring(1,str.length()-1));
    698                                 throw new IllegalStateException();
    699                         }
    700                         public CheckerElement(String exp) throws IllegalStateException, PatternSyntaxException
    701                         {
    702                                 Matcher m = Pattern.compile("(.+)([!=]=)(.+)").matcher(exp);
    703                                 m.matches();
    704 
    705                                 String n = m.group(1).trim();
    706                                 if(n.equals("*"))
    707                                         tagAll = true;
    708                                 else
    709                                         tag = n.startsWith("/") ? getPattern(n) : n;
    710                                 noMatch = m.group(2).equals("!=");
    711                                 n = m.group(3).trim();
    712                                 if(n.equals("*"))
    713                                         valueAll = true;
    714                                 else if(n.equals("BOOLEAN_TRUE"))
    715                                 {
    716                                         valueBool = true;
    717                                         value = OsmUtils.trueval;
    718                                 }
    719                                 else if(n.equals("BOOLEAN_FALSE"))
    720                                 {
    721                                         valueBool = true;
    722                                         value = OsmUtils.falseval;
    723                                 }
    724                                 else
    725                                         value = n.startsWith("/") ? getPattern(n) : n;
    726                         }
    727                         public Boolean match(OsmPrimitive osm)
    728                         {
    729                                 for(Entry<String, String> prop: osm.keys.entrySet())
    730                                 {
    731                                         String key = prop.getKey();
    732                                         String val = valueBool ? OsmUtils.getNamedOsmBoolean(prop.getValue()) : prop.getValue();
    733                                         if((tagAll || (tag instanceof Pattern ? ((Pattern)tag).matcher(key).matches() : key.equals(tag)))
    734                                         && (valueAll || (value instanceof Pattern ? ((Pattern)value).matcher(val).matches() : val.equals(value))))
    735                                                 return !noMatch;
    736                                 }
    737                                 return noMatch;
    738                         }
    739                 };
    740 
    741                 public String getData(String str)
    742                 {
    743                         Matcher m = Pattern.compile(" *# *([^#]+) *$").matcher(str);
    744                         str = m.replaceFirst("").trim();
    745                         try
    746                         {
    747                                 description = m.group(1);
    748                                 if(description != null && description.length() == 0)
    749                                         description = null;
    750                         }
    751                         catch (IllegalStateException e)
    752                         {
    753                                 description = null;
    754                         }
    755                         String[] n = str.split(" *: *", 3);
    756                         if(n[0].equals("way"))
    757                                 type = WAY;
    758                         else if(n[0].equals("node"))
    759                                 type = NODE;
    760                         else if(n[0].equals("relation"))
    761                                 type = RELATION;
    762                         else if(n[0].equals("*"))
    763                                 type = ALL;
    764                         if(type == 0 || n.length != 3)
    765                                 return tr("Could not find element type");
    766                         if(n[1].equals("W"))
    767                         {
    768                                 severity = Severity.WARNING;
    769                                 code = TAG_CHECK_WARN;
    770                         }
    771                         else if(n[1].equals("E"))
    772                         {
    773                                 severity = Severity.ERROR;
    774                                 code = TAG_CHECK_ERROR;
    775                         }
    776                         else if(n[1].equals("I"))
    777                         {
    778                                 severity = Severity.OTHER;
    779                                 code = TAG_CHECK_INFO;
    780                         }
    781                         else
    782                                 return tr("Could not find warning level");
    783                         for(String exp: n[2].split(" *&& *"))
    784                         {
    785                                 try
    786                                 {
    787                                         data.add(new CheckerElement(exp));
    788                                 }
    789                                 catch(IllegalStateException e)
    790                                 {
    791                                         return tr("Illegal expression ''{0}''", exp);
    792                                 }
    793                                 catch(PatternSyntaxException e)
    794                                 {
    795                                         return tr("Illegal regular expression ''{0}''", exp);
    796                                 }
    797                         }
    798                         return null;
    799                 }
    800                 public Boolean match(OsmPrimitive osm)
    801                 {
    802                         if(osm.keys == null || (type == NODE && !(osm instanceof Node))
    803                         || (type == RELATION && !(osm instanceof Relation)) || (type == WAY && !(osm instanceof Way)))
    804                                 return false;
    805                         for(CheckerElement ce : data)
    806                         {
    807                                 if(!ce.match(osm))
    808                                         return false;
    809                         }
    810                         return true;
    811                 }
    812                 public String getDescription()
    813                 {
    814                         return tr(description);
    815                 }
    816                 public String getDescriptionOrig()
    817                 {
    818                         return description;
    819                 }
    820                 public Severity getSeverity()
    821                 {
    822                         return severity;
    823                 }
    824                 public int getCode()
    825                 {
    826                         return code + type;
    827                 }
    828         }
     65    /** The default data files */
     66    public static final String DATA_FILE = "http://svn.openstreetmap.org/applications/editors/josm/plugins/validator/tagchecker.cfg";
     67    public static final String SPELL_FILE = "http://svn.openstreetmap.org/applications/utils/planet.osm/java/speller/words.cfg";
     68
     69    /** The spell check key substitutions: the key should be substituted by the value */
     70    protected static Map<String, String> spellCheckKeyData;
     71    /** The spell check preset values */
     72    protected static Bag<String, String> presetsValueData;
     73    /** The TagChecker data */
     74    protected static List<CheckerData> checkerData = new ArrayList<CheckerData>();
     75
     76    /** The preferences prefix */
     77    protected static final String PREFIX = PreferenceEditor.PREFIX + "." + TagChecker.class.getSimpleName();
     78
     79    public static final String PREF_CHECK_VALUES = PREFIX + ".checkValues";
     80    public static final String PREF_CHECK_KEYS = PREFIX + ".checkKeys";
     81    public static final String PREF_CHECK_COMPLEX = PREFIX + ".checkComplex";
     82    public static final String PREF_CHECK_FIXMES = PREFIX + ".checkFixmes";
     83    public static final String PREF_CHECK_PAINT = PREFIX + ".paint";
     84
     85    public static final String PREF_SOURCES = PREFIX + ".sources";
     86    public static final String PREF_USE_DATA_FILE = PREFIX + ".usedatafile";
     87    public static final String PREF_USE_SPELL_FILE = PREFIX + ".usespellfile";
     88
     89    public static final String PREF_CHECK_KEYS_BEFORE_UPLOAD = PREF_CHECK_KEYS + "BeforeUpload";
     90    public static final String PREF_CHECK_VALUES_BEFORE_UPLOAD = PREF_CHECK_VALUES + "BeforeUpload";
     91    public static final String PREF_CHECK_COMPLEX_BEFORE_UPLOAD = PREF_CHECK_COMPLEX + "BeforeUpload";
     92    public static final String PREF_CHECK_FIXMES_BEFORE_UPLOAD = PREF_CHECK_FIXMES + "BeforeUpload";
     93    public static final String PREF_CHECK_PAINT_BEFORE_UPLOAD = PREF_CHECK_PAINT + "BeforeUpload";
     94
     95    protected boolean checkKeys = false;
     96    protected boolean checkValues = false;
     97    protected boolean checkComplex = false;
     98    protected boolean checkFixmes = false;
     99    protected boolean checkPaint = false;
     100
     101    protected JCheckBox prefCheckKeys;
     102    protected JCheckBox prefCheckValues;
     103    protected JCheckBox prefCheckComplex;
     104    protected JCheckBox prefCheckFixmes;
     105    protected JCheckBox prefCheckPaint;
     106
     107    protected JCheckBox prefCheckKeysBeforeUpload;
     108    protected JCheckBox prefCheckValuesBeforeUpload;
     109    protected JCheckBox prefCheckComplexBeforeUpload;
     110    protected JCheckBox prefCheckFixmesBeforeUpload;
     111    protected JCheckBox prefCheckPaintBeforeUpload;
     112
     113    protected JCheckBox prefUseDataFile;
     114    protected JCheckBox prefUseSpellFile;
     115
     116    protected JButton addSrcButton;
     117    protected JButton editSrcButton;
     118    protected JButton deleteSrcButton;
     119
     120    protected static int EMPTY_VALUES      = 1200;
     121    protected static int INVALID_KEY       = 1201;
     122    protected static int INVALID_VALUE     = 1202;
     123    protected static int FIXME             = 1203;
     124    protected static int INVALID_SPACE     = 1204;
     125    protected static int INVALID_KEY_SPACE = 1205;
     126    protected static int INVALID_HTML      = 1206;
     127    protected static int PAINT             = 1207;
     128    /** 1250 and up is used by tagcheck */
     129
     130    /** List of sources for spellcheck data */
     131    protected JList Sources;
     132
     133
     134    protected static Entities entities = new Entities();
     135    /**
     136    * Constructor
     137    */
     138    public TagChecker()
     139    {
     140        super(tr("Properties checker :"),
     141              tr("This plugin checks for errors in property keys and values."));
     142    }
     143
     144    public static void initialize(OSMValidatorPlugin plugin) throws Exception
     145    {
     146        initializeData();
     147        initializePresets();
     148    }
     149
     150    /**
     151    * Reads the spellcheck file into a HashMap.
     152    * The data file is a list of words, beginning with +/-. If it starts with +,
     153    * the word is valid, but if it starts with -, the word should be replaced
     154    * by the nearest + word before this.
     155    *
     156    * @throws FileNotFoundException
     157    * @throws IOException
     158    */
     159    private static void initializeData() throws IOException
     160    {
     161        spellCheckKeyData = new HashMap<String, String>();
     162        String sources = Main.pref.get( PREF_SOURCES, "");
     163        if(Main.pref.getBoolean(PREF_USE_DATA_FILE, true))
     164        {
     165            if( sources == null || sources.length() == 0)
     166                sources = DATA_FILE;
     167            else
     168                sources = DATA_FILE + ";" + sources;
     169        }
     170        if(Main.pref.getBoolean(PREF_USE_SPELL_FILE, true))
     171        {
     172            if( sources == null || sources.length() == 0)
     173                sources = SPELL_FILE;
     174            else
     175                sources = SPELL_FILE + ";" + sources;
     176        }
     177
     178        String errorSources = "";
     179        if(sources.length() == 0)
     180            return;
     181        for(String source: sources.split(";"))
     182        {
     183            try
     184            {
     185                MirroredInputStream s = new MirroredInputStream(source, Util.getPluginDir(), -1);
     186                InputStreamReader r;
     187                try
     188                {
     189                    r = new InputStreamReader(s, "UTF-8");
     190                }
     191                catch (UnsupportedEncodingException e)
     192                {
     193                    r = new InputStreamReader(s);
     194                }
     195                BufferedReader reader = new BufferedReader(r);
     196
     197                String okValue = null;
     198                Boolean tagcheckerfile = false;
     199                String line;
     200                while((line = reader.readLine()) != null && (tagcheckerfile || line.length() != 0))
     201                {
     202                    if(line.startsWith("#"))
     203                    {
     204                        if(line.startsWith("# JOSM TagChecker"))
     205                            tagcheckerfile = true;
     206                    }
     207                    else if(tagcheckerfile)
     208                    {
     209                        if(line.length() > 0)
     210                        {
     211                            CheckerData d = new CheckerData();
     212                            String err = d.getData(line);
     213
     214                            if(err == null)
     215                                checkerData.add(d);
     216                            else
     217                                System.err.println(tr("Invalid tagchecker line - {0}: {1}", err, line));
     218                        }
     219                    }
     220                    else if(line.charAt(0) == '+')
     221                    {
     222                        okValue = line.substring(1);
     223                    }
     224                    else if(line.charAt(0) == '-' && okValue != null)
     225                    {
     226                        spellCheckKeyData.put(line.substring(1), okValue);
     227                    }
     228                    else
     229                    {
     230                        System.err.println(tr("Invalid spellcheck line: {0}", line));
     231                    }
     232                }
     233            }
     234            catch (IOException e)
     235            {
     236                errorSources += source + "\n";
     237            }
     238        }
     239
     240        if( errorSources.length() > 0 )
     241            throw new IOException( tr("Could not access data file(s):\n{0}", errorSources) );
     242    }
     243
     244    /**
     245    * Reads the presets data.
     246    *
     247    * @throws Exception
     248    */
     249    public static void initializePresets() throws Exception
     250    {
     251        if( !Main.pref.getBoolean(PREF_CHECK_VALUES, true) )
     252            return;
     253
     254        Collection<TaggingPreset> presets = TaggingPresetPreference.taggingPresets;
     255        if(presets != null)
     256        {
     257            presetsValueData = new Bag<String, String>();
     258            for(TaggingPreset p : presets)
     259            {
     260                for(TaggingPreset.Item i : p.data)
     261                {
     262                    if(i instanceof TaggingPreset.Combo)
     263                    {
     264                        TaggingPreset.Combo combo = (TaggingPreset.Combo) i;
     265                        for(String value : combo.values.split(","))
     266                            presetsValueData.add(combo.key, value);
     267                    }
     268                    else if(i instanceof TaggingPreset.Key)
     269                    {
     270                        TaggingPreset.Key k = (TaggingPreset.Key) i;
     271                        presetsValueData.add(k.key, k.value);
     272                    }
     273                }
     274            }
     275        }
     276    }
     277
     278    @Override
     279    public void visit(Node n)
     280    {
     281        checkPrimitive(n);
     282    }
     283
     284
     285    @Override
     286    public void visit(Relation n)
     287    {
     288        checkPrimitive(n);
     289    }
     290
     291
     292    @Override
     293    public void visit(Way w)
     294    {
     295        checkPrimitive(w);
     296    }
     297
     298    /**
     299    * Checks the primitive properties
     300    * @param p The primitive to check
     301    */
     302    private void checkPrimitive(OsmPrimitive p)
     303    {
     304        // Just a collection to know if a primitive has been already marked with error
     305        Bag<OsmPrimitive, String> withErrors = new Bag<OsmPrimitive, String>();
     306
     307        if(checkComplex)
     308        {
     309            for(CheckerData d : checkerData)
     310            {
     311                if(d.match(p))
     312                {
     313                    errors.add( new TestError(this, d.getSeverity(), tr("Illegal tag/value combinations"),
     314                    d.getDescription(), d.getDescriptionOrig(), d.getCode(), p) );
     315                    withErrors.add(p, "TC");
     316                    break;
     317                }
     318            }
     319        }
     320        if(checkPaint && p.errors != null)
     321        {
     322            for(String s: p.errors)
     323            {
     324                /* passing translated text also to original string, as we already
     325                translated the stuff before. Makes the ignore file language dependend. */
     326                errors.add( new TestError(this, Severity.WARNING, tr("Painting problem"),
     327                s, s, PAINT, p) );
     328                withErrors.add(p, "P");
     329            }
     330        }
     331
     332        Map<String, String> props = (p.keys == null) ? Collections.<String, String>emptyMap() : p.keys;
     333        for(Entry<String, String> prop: props.entrySet() )
     334        {
     335            String s = marktr("Key ''{0}'' invalid.");
     336            String key = prop.getKey();
     337            String value = prop.getValue();
     338            if( checkValues && (value==null || value.trim().length() == 0) && !withErrors.contains(p, "EV"))
     339            {
     340                errors.add( new TestError(this, Severity.WARNING, tr("Tags with empty values"),
     341                tr(s, key), MessageFormat.format(s, key), EMPTY_VALUES, p) );
     342                withErrors.add(p, "EV");
     343            }
     344            if( checkKeys && spellCheckKeyData.containsKey(key) && !withErrors.contains(p, "IPK"))
     345            {
     346                errors.add( new TestError(this, Severity.WARNING, tr("Invalid property key"),
     347                tr(s, key), MessageFormat.format(s, key), INVALID_KEY, p) );
     348                withErrors.add(p, "IPK");
     349            }
     350            if( checkKeys && key.indexOf(" ") >= 0 && !withErrors.contains(p, "IPK"))
     351            {
     352                errors.add( new TestError(this, Severity.WARNING, tr("Invalid white space in property key"),
     353                tr(s, key), MessageFormat.format(s, key), INVALID_KEY_SPACE, p) );
     354                withErrors.add(p, "IPK");
     355            }
     356            if( checkValues && value != null && (value.startsWith(" ") || value.endsWith(" ")) && !withErrors.contains(p, "SPACE"))
     357            {
     358                errors.add( new TestError(this, Severity.OTHER, tr("Property values start or end with white space"),
     359                tr(s, key), MessageFormat.format(s, key), INVALID_SPACE, p) );
     360                withErrors.add(p, "SPACE");
     361            }
     362            if( checkValues && value != null && !value.equals(entities.unescape(value)) && !withErrors.contains(p, "HTML"))
     363            {
     364                errors.add( new TestError(this, Severity.OTHER, tr("Property values contain HTML entity"),
     365                tr(s, key), MessageFormat.format(s, key), INVALID_HTML, p) );
     366                withErrors.add(p, "HTML");
     367            }
     368            if( checkValues && value != null && value.length() > 0 && presetsValueData != null)
     369            {
     370                List<String> values = presetsValueData.get(key);
     371                if( values != null && !values.contains(prop.getValue()) && !withErrors.contains(p, "UPV"))
     372                {
     373                    String i = marktr("Key ''{0}'' unknown.");
     374                    errors.add( new TestError(this, Severity.OTHER, tr("Unknown property values"),
     375                    tr(i, key), MessageFormat.format(i, key), INVALID_VALUE, p) );
     376                    withErrors.add(p, "UPV");
     377                }
     378            }
     379            if( checkFixmes && value != null && value.length() > 0 )
     380            {
     381                if( (value.contains("FIXME") || value.contains("check and delete") || key.contains("todo") || key.contains("fixme"))
     382                && !withErrors.contains(p, "FIXME"))
     383                {
     384                    errors.add( new TestError(this, Severity.OTHER, tr("FIXMES"), FIXME, p) );
     385                    withErrors.add(p, "FIXME");
     386                }
     387            }
     388        }
     389    }
     390
     391    @Override
     392    public void startTest()
     393    {
     394        checkKeys = Main.pref.getBoolean(PREF_CHECK_KEYS, true);
     395        if( isBeforeUpload )
     396            checkKeys = checkKeys && Main.pref.getBoolean(PREF_CHECK_KEYS_BEFORE_UPLOAD, true);
     397
     398        checkValues = Main.pref.getBoolean(PREF_CHECK_VALUES, true);
     399        if( isBeforeUpload )
     400            checkValues = checkValues && Main.pref.getBoolean(PREF_CHECK_VALUES_BEFORE_UPLOAD, true);
     401
     402        checkComplex = Main.pref.getBoolean(PREF_CHECK_COMPLEX, true);
     403        if( isBeforeUpload )
     404            checkComplex = checkValues && Main.pref.getBoolean(PREF_CHECK_COMPLEX_BEFORE_UPLOAD, true);
     405
     406        checkFixmes = Main.pref.getBoolean(PREF_CHECK_FIXMES, true);
     407        if( isBeforeUpload )
     408            checkFixmes = checkFixmes && Main.pref.getBoolean(PREF_CHECK_FIXMES_BEFORE_UPLOAD, true);
     409
     410        checkPaint = Main.pref.getBoolean(PREF_CHECK_PAINT, true);
     411        if( isBeforeUpload )
     412            checkPaint = checkPaint && Main.pref.getBoolean(PREF_CHECK_PAINT_BEFORE_UPLOAD, true);
     413    }
     414
     415    @Override
     416    public void visit(Collection<OsmPrimitive> selection)
     417    {
     418        if( checkKeys || checkValues || checkComplex)
     419            super.visit(selection);
     420    }
     421
     422    @Override
     423    public void addGui(JPanel testPanel)
     424    {
     425        GBC a = GBC.eol();
     426        a.anchor = GBC.EAST;
     427
     428        testPanel.add( new JLabel(name), GBC.eol().insets(3,0,0,0) );
     429
     430        prefCheckKeys = new JCheckBox(tr("Check property keys."), Main.pref.getBoolean(PREF_CHECK_KEYS, true));
     431        prefCheckKeys.setToolTipText(tr("Validate that property keys are valid checking against list of words."));
     432        testPanel.add(prefCheckKeys, GBC.std().insets(20,0,0,0));
     433
     434        prefCheckKeysBeforeUpload = new JCheckBox();
     435        prefCheckKeysBeforeUpload.setSelected(Main.pref.getBoolean(PREF_CHECK_KEYS_BEFORE_UPLOAD, true));
     436        testPanel.add(prefCheckKeysBeforeUpload, a);
     437
     438        prefCheckComplex = new JCheckBox(tr("Use complex property checker."), Main.pref.getBoolean(PREF_CHECK_COMPLEX, true));
     439        prefCheckComplex.setToolTipText(tr("Validate property values and tags using complex rules."));
     440        testPanel.add(prefCheckComplex, GBC.std().insets(20,0,0,0));
     441
     442        prefCheckComplexBeforeUpload = new JCheckBox();
     443        prefCheckComplexBeforeUpload.setSelected(Main.pref.getBoolean(PREF_CHECK_COMPLEX_BEFORE_UPLOAD, true));
     444        testPanel.add(prefCheckComplexBeforeUpload, a);
     445
     446        Sources = new JList(new DefaultListModel());
     447
     448        String sources = Main.pref.get( PREF_SOURCES );
     449        if(sources != null && sources.length() > 0)
     450        {
     451            for(String source : sources.split(";"))
     452                ((DefaultListModel)Sources.getModel()).addElement(source);
     453        }
     454
     455        addSrcButton = new JButton(tr("Add"));
     456        addSrcButton.addActionListener(new ActionListener(){
     457            public void actionPerformed(ActionEvent e) {
     458                String source = JOptionPane.showInputDialog(Main.parent, tr("TagChecker source"));
     459                if (source != null)
     460                    ((DefaultListModel)Sources.getModel()).addElement(source);
     461                Sources.clearSelection();
     462            }
     463        });
     464
     465        editSrcButton = new JButton(tr("Edit"));
     466        editSrcButton.addActionListener(new ActionListener(){
     467            public void actionPerformed(ActionEvent e) {
     468                int row = Sources.getSelectedIndex();
     469                if(row == -1 && Sources.getModel().getSize() == 1)
     470                {
     471                    Sources.setSelectedIndex(0);
     472                    row = 0;
     473                }
     474                if (row == -1)
     475                {
     476                    if(Sources.getModel().getSize() == 0)
     477                    {
     478                        String source = JOptionPane.showInputDialog(Main.parent, tr("TagChecker source"));
     479                        if (source != null)
     480                            ((DefaultListModel)Sources.getModel()).addElement(source);
     481                    }
     482                    else
     483                    {
     484                        JOptionPane.showMessageDialog(Main.parent, tr("Please select the row to edit."));
     485                    }
     486                }
     487                else {
     488                    String source = JOptionPane.showInputDialog(Main.parent, tr("TagChecker source"), Sources.getSelectedValue());
     489                    if (source != null)
     490                        ((DefaultListModel)Sources.getModel()).setElementAt(source, row);
     491                }
     492                Sources.clearSelection();
     493            }
     494        });
     495
     496        deleteSrcButton = new JButton(tr("Delete"));
     497        deleteSrcButton.addActionListener(new ActionListener(){
     498            public void actionPerformed(ActionEvent e) {
     499                if (Sources.getSelectedIndex() == -1)
     500                    JOptionPane.showMessageDialog(Main.parent, tr("Please select the row to delete."));
     501                else {
     502                    ((DefaultListModel)Sources.getModel()).remove(Sources.getSelectedIndex());
     503                }
     504            }
     505        });
     506        Sources.setMinimumSize(new Dimension(300,50));
     507        Sources.setVisibleRowCount(3);
     508
     509        Sources.setToolTipText(tr("The sources (URL or filename) of spell check (see http://wiki.openstreetmap.org/index.php/User:JLS/speller) or tag checking data files."));
     510        addSrcButton.setToolTipText(tr("Add a new source to the list."));
     511        editSrcButton.setToolTipText(tr("Edit the selected source."));
     512        deleteSrcButton.setToolTipText(tr("Delete the selected source from the list."));
     513
     514        testPanel.add(new JLabel(tr("Data sources")), GBC.eol().insets(23,0,0,0));
     515        testPanel.add(new JScrollPane(Sources), GBC.eol().insets(23,0,0,0).fill(GBC.HORIZONTAL));
     516        final JPanel buttonPanel = new JPanel(new GridBagLayout());
     517        testPanel.add(buttonPanel, GBC.eol().fill(GBC.HORIZONTAL));
     518        buttonPanel.add(addSrcButton, GBC.std().insets(0,5,0,0));
     519        buttonPanel.add(editSrcButton, GBC.std().insets(5,5,5,0));
     520        buttonPanel.add(deleteSrcButton, GBC.std().insets(0,5,0,0));
     521
     522        ActionListener disableCheckActionListener = new ActionListener(){
     523            public void actionPerformed(ActionEvent e) {
     524                handlePrefEnable();
     525            }
     526        };
     527        prefCheckKeys.addActionListener(disableCheckActionListener);
     528        prefCheckKeysBeforeUpload.addActionListener(disableCheckActionListener);
     529        prefCheckComplex.addActionListener(disableCheckActionListener);
     530        prefCheckComplexBeforeUpload.addActionListener(disableCheckActionListener);
     531
     532        handlePrefEnable();
     533
     534        prefCheckValues = new JCheckBox(tr("Check property values."), Main.pref.getBoolean(PREF_CHECK_VALUES, true));
     535        prefCheckValues.setToolTipText(tr("Validate that property values are valid checking against presets."));
     536        testPanel.add(prefCheckValues, GBC.std().insets(20,0,0,0));
     537
     538        prefCheckValuesBeforeUpload = new JCheckBox();
     539        prefCheckValuesBeforeUpload.setSelected(Main.pref.getBoolean(PREF_CHECK_VALUES_BEFORE_UPLOAD, true));
     540        testPanel.add(prefCheckValuesBeforeUpload, a);
     541
     542        prefCheckFixmes = new JCheckBox(tr("Check for FIXMES."), Main.pref.getBoolean(PREF_CHECK_FIXMES, true));
     543        prefCheckFixmes.setToolTipText(tr("Looks for nodes or ways with FIXME in any property value."));
     544        testPanel.add(prefCheckFixmes, GBC.std().insets(20,0,0,0));
     545
     546        prefCheckFixmesBeforeUpload = new JCheckBox();
     547        prefCheckFixmesBeforeUpload.setSelected(Main.pref.getBoolean(PREF_CHECK_FIXMES_BEFORE_UPLOAD, true));
     548        testPanel.add(prefCheckFixmesBeforeUpload, a);
     549
     550        prefCheckPaint = new JCheckBox(tr("Check for paint notes."), Main.pref.getBoolean(PREF_CHECK_PAINT, true));
     551        prefCheckPaint.setToolTipText(tr("Check if map paining found data errors."));
     552        testPanel.add(prefCheckPaint, GBC.std().insets(20,0,0,0));
     553
     554        prefCheckPaintBeforeUpload = new JCheckBox();
     555        prefCheckPaintBeforeUpload.setSelected(Main.pref.getBoolean(PREF_CHECK_PAINT_BEFORE_UPLOAD, true));
     556        testPanel.add(prefCheckPaintBeforeUpload, a);
     557
     558        prefUseDataFile = new JCheckBox(tr("Use default data file."), Main.pref.getBoolean(PREF_USE_DATA_FILE, true));
     559        prefUseDataFile.setToolTipText(tr("Use the default data file (recommended)."));
     560        testPanel.add(prefUseDataFile, GBC.eol().insets(20,0,0,0));
     561
     562        prefUseSpellFile = new JCheckBox(tr("Use default spellcheck file."), Main.pref.getBoolean(PREF_USE_SPELL_FILE, true));
     563        prefUseSpellFile.setToolTipText(tr("Use the default spellcheck file (recommended)."));
     564        testPanel.add(prefUseSpellFile, GBC.eol().insets(20,0,0,0));
     565    }
     566
     567    public void handlePrefEnable()
     568    {
     569        boolean selected = prefCheckKeys.isSelected() || prefCheckKeysBeforeUpload.isSelected()
     570        || prefCheckComplex.isSelected() || prefCheckComplexBeforeUpload.isSelected();
     571        Sources.setEnabled( selected );
     572        addSrcButton.setEnabled(selected);
     573        editSrcButton.setEnabled(selected);
     574        deleteSrcButton.setEnabled(selected);
     575    }
     576
     577    @Override
     578    public boolean ok()
     579    {
     580        enabled = prefCheckKeys.isSelected() || prefCheckValues.isSelected() || prefCheckComplex.isSelected() || prefCheckFixmes.isSelected();
     581        testBeforeUpload = prefCheckKeysBeforeUpload.isSelected() || prefCheckValuesBeforeUpload.isSelected()
     582        || prefCheckFixmesBeforeUpload.isSelected() || prefCheckComplexBeforeUpload.isSelected();
     583
     584        Main.pref.put(PREF_CHECK_VALUES, prefCheckValues.isSelected());
     585        Main.pref.put(PREF_CHECK_COMPLEX, prefCheckComplex.isSelected());
     586        Main.pref.put(PREF_CHECK_KEYS, prefCheckKeys.isSelected());
     587        Main.pref.put(PREF_CHECK_FIXMES, prefCheckFixmes.isSelected());
     588        Main.pref.put(PREF_CHECK_PAINT, prefCheckPaint.isSelected());
     589        Main.pref.put(PREF_CHECK_VALUES_BEFORE_UPLOAD, prefCheckValuesBeforeUpload.isSelected());
     590        Main.pref.put(PREF_CHECK_COMPLEX_BEFORE_UPLOAD, prefCheckComplexBeforeUpload.isSelected());
     591        Main.pref.put(PREF_CHECK_KEYS_BEFORE_UPLOAD, prefCheckKeysBeforeUpload.isSelected());
     592        Main.pref.put(PREF_CHECK_FIXMES_BEFORE_UPLOAD, prefCheckFixmesBeforeUpload.isSelected());
     593        Main.pref.put(PREF_CHECK_PAINT_BEFORE_UPLOAD, prefCheckPaintBeforeUpload.isSelected());
     594        Main.pref.put(PREF_USE_DATA_FILE, prefUseDataFile.isSelected());
     595        Main.pref.put(PREF_USE_SPELL_FILE, prefUseSpellFile.isSelected());
     596        String sources = "";
     597        if( Sources.getModel().getSize() > 0 )
     598        {
     599            String sb = "";
     600            for (int i = 0; i < Sources.getModel().getSize(); ++i)
     601                sb += ";"+Sources.getModel().getElementAt(i);
     602            sources = sb.substring(1);
     603        }
     604        if(sources.length() == 0)
     605            sources = null;
     606        return Main.pref.put(PREF_SOURCES, sources);
     607    }
     608
     609    @Override
     610    public Command fixError(TestError testError)
     611    {
     612        List<Command> commands = new ArrayList<Command>(50);
     613
     614        int i = -1;
     615        List<? extends OsmPrimitive> primitives = testError.getPrimitives();
     616        for(OsmPrimitive p : primitives )
     617        {
     618            i++;
     619            Map<String, String> tags = p.keys;
     620            if( tags == null || tags.size() == 0 )
     621                continue;
     622
     623            for(Entry<String, String> prop: tags.entrySet() )
     624            {
     625                String key = prop.getKey();
     626                String value = prop.getValue();
     627                if( value == null || value.trim().length() == 0 )
     628                    commands.add( new ChangePropertyCommand(Collections.singleton(primitives.get(i)), key, null) );
     629                else if(value.startsWith(" ") || value.endsWith(" "))
     630                    commands.add( new ChangePropertyCommand(Collections.singleton(primitives.get(i)), key, value.trim()) );
     631                else if(key.startsWith(" ") || key.endsWith(" "))
     632                    commands.add( new ChangePropertyKeyCommand(Collections.singleton(primitives.get(i)), key, key.trim()) );
     633                else
     634                {
     635                    String evalue = entities.unescape(value);
     636                    if(!evalue.equals(value))
     637                        commands.add( new ChangePropertyCommand(Collections.singleton(primitives.get(i)), key, evalue) );
     638                    else
     639                    {
     640                        String replacementKey = spellCheckKeyData.get(key);
     641                        if( replacementKey != null )
     642                        {
     643                            commands.add( new ChangePropertyKeyCommand(Collections.singleton(primitives.get(i)),
     644                            key, replacementKey) );
     645                        }
     646                    }
     647                }
     648            }
     649        }
     650
     651        if( commands.size() == 0 )
     652            return null;
     653        else if( commands.size() == 1 )
     654            return commands.get(0);
     655        else
     656            return new SequenceCommand(tr("Fix properties"), commands);
     657    }
     658
     659    @Override
     660    public boolean isFixable(TestError testError)
     661    {
     662        if( testError.getTester() instanceof TagChecker)
     663        {
     664            int code = testError.getCode();
     665            return code == INVALID_KEY || code == EMPTY_VALUES || code == INVALID_SPACE || code == INVALID_KEY_SPACE || code == INVALID_HTML;
     666        }
     667
     668        return false;
     669    }
     670
     671    private static class CheckerData {
     672        private String description;
     673        private List<CheckerElement> data = new ArrayList<CheckerElement>();
     674        private Integer type = 0;
     675        private Integer code;
     676        protected Severity severity;
     677        protected static int NODE = 1;
     678        protected static int WAY = 2;
     679        protected static int RELATION = 3;
     680        protected static int ALL = 4;
     681        protected static int TAG_CHECK_ERROR  = 1250;
     682        protected static int TAG_CHECK_WARN   = 1260;
     683        protected static int TAG_CHECK_INFO   = 1270;
     684
     685        private class CheckerElement {
     686            public Object tag;
     687            public Object value;
     688            public Boolean noMatch;
     689            public Boolean tagAll = false;
     690            public Boolean valueAll = false;
     691            public Boolean valueBool = false;
     692            private Pattern getPattern(String str) throws IllegalStateException, PatternSyntaxException
     693            {
     694                if(str.endsWith("/i"))
     695                    return Pattern.compile(str.substring(1,str.length()-2), Pattern.CASE_INSENSITIVE);
     696                else if(str.endsWith("/"))
     697                    return Pattern.compile(str.substring(1,str.length()-1));
     698                throw new IllegalStateException();
     699            }
     700            public CheckerElement(String exp) throws IllegalStateException, PatternSyntaxException
     701            {
     702                Matcher m = Pattern.compile("(.+)([!=]=)(.+)").matcher(exp);
     703                m.matches();
     704
     705                String n = m.group(1).trim();
     706                if(n.equals("*"))
     707                    tagAll = true;
     708                else
     709                    tag = n.startsWith("/") ? getPattern(n) : n;
     710                noMatch = m.group(2).equals("!=");
     711                n = m.group(3).trim();
     712                if(n.equals("*"))
     713                    valueAll = true;
     714                else if(n.equals("BOOLEAN_TRUE"))
     715                {
     716                    valueBool = true;
     717                    value = OsmUtils.trueval;
     718                }
     719                else if(n.equals("BOOLEAN_FALSE"))
     720                {
     721                    valueBool = true;
     722                    value = OsmUtils.falseval;
     723                }
     724                else
     725                    value = n.startsWith("/") ? getPattern(n) : n;
     726            }
     727            public Boolean match(OsmPrimitive osm)
     728            {
     729                for(Entry<String, String> prop: osm.keys.entrySet())
     730                {
     731                    String key = prop.getKey();
     732                    String val = valueBool ? OsmUtils.getNamedOsmBoolean(prop.getValue()) : prop.getValue();
     733                    if((tagAll || (tag instanceof Pattern ? ((Pattern)tag).matcher(key).matches() : key.equals(tag)))
     734                    && (valueAll || (value instanceof Pattern ? ((Pattern)value).matcher(val).matches() : val.equals(value))))
     735                        return !noMatch;
     736                }
     737                return noMatch;
     738            }
     739        };
     740
     741        public String getData(String str)
     742        {
     743            Matcher m = Pattern.compile(" *# *([^#]+) *$").matcher(str);
     744            str = m.replaceFirst("").trim();
     745            try
     746            {
     747                description = m.group(1);
     748                if(description != null && description.length() == 0)
     749                    description = null;
     750            }
     751            catch (IllegalStateException e)
     752            {
     753                description = null;
     754            }
     755            String[] n = str.split(" *: *", 3);
     756            if(n[0].equals("way"))
     757                type = WAY;
     758            else if(n[0].equals("node"))
     759                type = NODE;
     760            else if(n[0].equals("relation"))
     761                type = RELATION;
     762            else if(n[0].equals("*"))
     763                type = ALL;
     764            if(type == 0 || n.length != 3)
     765                return tr("Could not find element type");
     766            if(n[1].equals("W"))
     767            {
     768                severity = Severity.WARNING;
     769                code = TAG_CHECK_WARN;
     770            }
     771            else if(n[1].equals("E"))
     772            {
     773                severity = Severity.ERROR;
     774                code = TAG_CHECK_ERROR;
     775            }
     776            else if(n[1].equals("I"))
     777            {
     778                severity = Severity.OTHER;
     779                code = TAG_CHECK_INFO;
     780            }
     781            else
     782                return tr("Could not find warning level");
     783            for(String exp: n[2].split(" *&& *"))
     784            {
     785                try
     786                {
     787                    data.add(new CheckerElement(exp));
     788                }
     789                catch(IllegalStateException e)
     790                {
     791                    return tr("Illegal expression ''{0}''", exp);
     792                }
     793                catch(PatternSyntaxException e)
     794                {
     795                    return tr("Illegal regular expression ''{0}''", exp);
     796                }
     797            }
     798            return null;
     799        }
     800        public Boolean match(OsmPrimitive osm)
     801        {
     802            if(osm.keys == null || (type == NODE && !(osm instanceof Node))
     803            || (type == RELATION && !(osm instanceof Relation)) || (type == WAY && !(osm instanceof Way)))
     804                return false;
     805            for(CheckerElement ce : data)
     806            {
     807                if(!ce.match(osm))
     808                    return false;
     809            }
     810            return true;
     811        }
     812        public String getDescription()
     813        {
     814            return tr(description);
     815        }
     816        public String getDescriptionOrig()
     817        {
     818            return description;
     819        }
     820        public Severity getSeverity()
     821        {
     822            return severity;
     823        }
     824        public int getCode()
     825        {
     826            return code + type;
     827        }
     828    }
    829829}
  • applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/UnconnectedWays.java

    r10774 r12778  
    2525public class UnconnectedWays extends Test
    2626{
    27         protected static int UNCONNECTED_WAYS = 1301;
    28         protected static final String PREFIX = PreferenceEditor.PREFIX + "." + UnconnectedWays.class.getSimpleName();
    29 
    30         Set<MyWaySegment> ways;
    31         Set<Node> endnodes; // nodes at end of way
    32         Set<Node> endnodes_highway; // nodes at end of way
    33         Set<Node> middlenodes; // nodes in middle of way
    34         Set<Node> othernodes; // nodes appearing at least twice
    35 
    36         double mindist;
    37         double minmiddledist;
    38         /**
    39         * Constructor
    40         */
    41         public UnconnectedWays()
    42         {
    43                 super(tr("Unconnected ways."),
    44                           tr("This test checks if a way has an endpoint very near to another way."));
    45         }
    46 
    47         @Override
    48         public void startTest()
    49         {
    50                 ways = new HashSet<MyWaySegment>();
    51                 endnodes = new HashSet<Node>();
    52                 endnodes_highway = new HashSet<Node>();
    53                 middlenodes = new HashSet<Node>();
    54                 othernodes = new HashSet<Node>();
    55                 mindist = Main.pref.getDouble(PREFIX + ".node_way_distance", 10.0)/6378135.0;
    56                 minmiddledist = Main.pref.getDouble(PREFIX + ".way_way_distance", 0.0)/6378135.0;
    57         }
    58 
    59         @Override
    60         public void endTest()
    61         {
    62                 Map<Node, Way> map = new HashMap<Node, Way>();
    63                 for(Node en : endnodes_highway)
    64                 {
    65                         for(MyWaySegment s : ways)
    66                         {
    67                                 if(s.highway && s.nearby(en, mindist))
    68                                         map.put(en, s.w);
    69                         }
    70                 }
    71                 if(map.size() > 0)
    72                 {
    73                         for(Map.Entry<Node, Way> error : map.entrySet())
    74                         {
    75                                 errors.add(new TestError(this, Severity.WARNING,
    76                                 tr("Way end node near other highway"), UNCONNECTED_WAYS,
    77                                 Arrays.asList(error.getKey(), error.getValue())));
    78                         }
    79                 }
    80                 map.clear();
    81                 for(Node en : endnodes_highway)
    82                 {
    83                         for(MyWaySegment s : ways)
    84                         {
    85                                 if(!s.highway && s.nearby(en, mindist))
    86                                         map.put(en, s.w);
    87                         }
    88                 }
    89                 for(Node en : endnodes)
    90                 {
    91                         for(MyWaySegment s : ways)
    92                         {
    93                                 if(s.nearby(en, mindist))
    94                                         map.put(en, s.w);
    95                         }
    96                 }
    97                 if(map.size() > 0)
    98                 {
    99                         for(Map.Entry<Node, Way> error : map.entrySet())
    100                         {
    101                                 errors.add(new TestError(this, Severity.WARNING,
    102                                 tr("Way end node near other way"), UNCONNECTED_WAYS,
    103                                 Arrays.asList(error.getKey(), error.getValue())));
    104                         }
    105                 }
    106                 /* the following two use a shorter distance */
    107                 if(minmiddledist > 0.0)
    108                 {
    109                         map.clear();
    110                         for(Node en : middlenodes)
    111                         {
    112                                 for(MyWaySegment s : ways)
    113                                 {
    114                                         if(s.nearby(en, minmiddledist))
    115                                                 map.put(en, s.w);
    116                                 }
    117                         }
    118                         if(map.size() > 0)
    119                         {
    120                                 for(Map.Entry<Node, Way> error : map.entrySet())
    121                                 {
    122                                         errors.add(new TestError(this, Severity.OTHER,
    123                                         tr("Way node near other way"), UNCONNECTED_WAYS,
    124                                         Arrays.asList(error.getKey(), error.getValue())));
    125                                 }
    126                         }
    127                         map.clear();
    128                         for(Node en : othernodes)
    129                         {
    130                                 for(MyWaySegment s : ways)
    131                                 {
    132                                         if(s.nearby(en, minmiddledist))
    133                                                 map.put(en, s.w);
    134                                 }
    135                         }
    136                         if(map.size() > 0)
    137                         {
    138                                 for(Map.Entry<Node, Way> error : map.entrySet())
    139                                 {
    140                                         errors.add(new TestError(this, Severity.OTHER,
    141                                         tr("Connected way end node near other way"), UNCONNECTED_WAYS,
    142                                         Arrays.asList(error.getKey(), error.getValue())));
    143                                 }
    144                         }
    145                 }
    146                 ways = null;
    147                 endnodes = null;
    148         }
    149 
    150         private class MyWaySegment
    151         {
    152                 private Line2D line;
    153                 public Way w;
    154                 public Boolean highway;
    155 
    156                 public MyWaySegment(Way w, Node n1, Node n2)
    157                 {
    158                         this.w = w;
    159                         this.highway = w.get("highway") != null || w.get("railway") != null;
    160                         line = new Line2D.Double(n1.eastNorth.east(), n1.eastNorth.north(),
    161                         n2.eastNorth.east(), n2.eastNorth.north());
    162                 }
    163 
    164                 public boolean nearby(Node n, double dist)
    165                 {
    166                         return !w.nodes.contains(n)
    167                         && line.ptSegDist(n.eastNorth.east(), n.eastNorth.north()) < dist;
    168                 }
    169         }
    170 
    171         @Override
    172         public void visit(Way w)
    173         {
    174                 if( w.deleted || w.incomplete )
    175                         return;
    176                 int size = w.nodes.size();
    177                 if(size < 2)
    178                         return;
    179                 for(int i = 1; i < size; ++i)
    180                 {
    181                         if(i < size-1)
    182                                 addNode(w.nodes.get(i), middlenodes);
    183                         ways.add(new MyWaySegment(w, w.nodes.get(i-1), w.nodes.get(i)));
    184                 }
    185                 Set<Node> set = endnodes;
    186                 if(w.get("highway") != null || w.get("railway") != null)
    187                         set = endnodes_highway;
    188                 addNode(w.nodes.get(0), set);
    189                 addNode(w.nodes.get(size-1), set);
    190         }
    191         private void addNode(Node n, Set<Node> s)
    192         {
    193                 Boolean m = middlenodes.contains(n);
    194                 Boolean e = endnodes.contains(n);
    195                 Boolean eh = endnodes_highway.contains(n);
    196                 Boolean o = othernodes.contains(n);
    197                 if(!m && !e && !o && !eh)
    198                         s.add(n);
    199                 else if(!o)
    200                 {
    201                         othernodes.add(n);
    202                         if(e)
    203                                 endnodes.remove(n);
    204                         else if(eh)
    205                                 endnodes_highway.remove(n);
    206                         else
    207                                 middlenodes.remove(n);
    208                 }
    209         }
     27    protected static int UNCONNECTED_WAYS = 1301;
     28    protected static final String PREFIX = PreferenceEditor.PREFIX + "." + UnconnectedWays.class.getSimpleName();
     29
     30    Set<MyWaySegment> ways;
     31    Set<Node> endnodes; // nodes at end of way
     32    Set<Node> endnodes_highway; // nodes at end of way
     33    Set<Node> middlenodes; // nodes in middle of way
     34    Set<Node> othernodes; // nodes appearing at least twice
     35
     36    double mindist;
     37    double minmiddledist;
     38    /**
     39    * Constructor
     40    */
     41    public UnconnectedWays()
     42    {
     43        super(tr("Unconnected ways."),
     44              tr("This test checks if a way has an endpoint very near to another way."));
     45    }
     46
     47    @Override
     48    public void startTest()
     49    {
     50        ways = new HashSet<MyWaySegment>();
     51        endnodes = new HashSet<Node>();
     52        endnodes_highway = new HashSet<Node>();
     53        middlenodes = new HashSet<Node>();
     54        othernodes = new HashSet<Node>();
     55        mindist = Main.pref.getDouble(PREFIX + ".node_way_distance", 10.0)/6378135.0;
     56        minmiddledist = Main.pref.getDouble(PREFIX + ".way_way_distance", 0.0)/6378135.0;
     57    }
     58
     59    @Override
     60    public void endTest()
     61    {
     62        Map<Node, Way> map = new HashMap<Node, Way>();
     63        for(Node en : endnodes_highway)
     64        {
     65            for(MyWaySegment s : ways)
     66            {
     67                if(s.highway && s.nearby(en, mindist))
     68                    map.put(en, s.w);
     69            }
     70        }
     71        if(map.size() > 0)
     72        {
     73            for(Map.Entry<Node, Way> error : map.entrySet())
     74            {
     75                errors.add(new TestError(this, Severity.WARNING,
     76                tr("Way end node near other highway"), UNCONNECTED_WAYS,
     77                Arrays.asList(error.getKey(), error.getValue())));
     78            }
     79        }
     80        map.clear();
     81        for(Node en : endnodes_highway)
     82        {
     83            for(MyWaySegment s : ways)
     84            {
     85                if(!s.highway && s.nearby(en, mindist))
     86                    map.put(en, s.w);
     87            }
     88        }
     89        for(Node en : endnodes)
     90        {
     91            for(MyWaySegment s : ways)
     92            {
     93                if(s.nearby(en, mindist))
     94                    map.put(en, s.w);
     95            }
     96        }
     97        if(map.size() > 0)
     98        {
     99            for(Map.Entry<Node, Way> error : map.entrySet())
     100            {
     101                errors.add(new TestError(this, Severity.WARNING,
     102                tr("Way end node near other way"), UNCONNECTED_WAYS,
     103                Arrays.asList(error.getKey(), error.getValue())));
     104            }
     105        }
     106        /* the following two use a shorter distance */
     107        if(minmiddledist > 0.0)
     108        {
     109            map.clear();
     110            for(Node en : middlenodes)
     111            {
     112                for(MyWaySegment s : ways)
     113                {
     114                    if(s.nearby(en, minmiddledist))
     115                        map.put(en, s.w);
     116                }
     117            }
     118            if(map.size() > 0)
     119            {
     120                for(Map.Entry<Node, Way> error : map.entrySet())
     121                {
     122                    errors.add(new TestError(this, Severity.OTHER,
     123                    tr("Way node near other way"), UNCONNECTED_WAYS,
     124                    Arrays.asList(error.getKey(), error.getValue())));
     125                }
     126            }
     127            map.clear();
     128            for(Node en : othernodes)
     129            {
     130                for(MyWaySegment s : ways)
     131                {
     132                    if(s.nearby(en, minmiddledist))
     133                        map.put(en, s.w);
     134                }
     135            }
     136            if(map.size() > 0)
     137            {
     138                for(Map.Entry<Node, Way> error : map.entrySet())
     139                {
     140                    errors.add(new TestError(this, Severity.OTHER,
     141                    tr("Connected way end node near other way"), UNCONNECTED_WAYS,
     142                    Arrays.asList(error.getKey(), error.getValue())));
     143                }
     144            }
     145        }
     146        ways = null;
     147        endnodes = null;
     148    }
     149
     150    private class MyWaySegment
     151    {
     152        private Line2D line;
     153        public Way w;
     154        public Boolean highway;
     155
     156        public MyWaySegment(Way w, Node n1, Node n2)
     157        {
     158            this.w = w;
     159            this.highway = w.get("highway") != null || w.get("railway") != null;
     160            line = new Line2D.Double(n1.eastNorth.east(), n1.eastNorth.north(),
     161            n2.eastNorth.east(), n2.eastNorth.north());
     162        }
     163
     164        public boolean nearby(Node n, double dist)
     165        {
     166            return !w.nodes.contains(n)
     167            && line.ptSegDist(n.eastNorth.east(), n.eastNorth.north()) < dist;
     168        }
     169    }
     170
     171    @Override
     172    public void visit(Way w)
     173    {
     174        if( w.deleted || w.incomplete )
     175            return;
     176        int size = w.nodes.size();
     177        if(size < 2)
     178            return;
     179        for(int i = 1; i < size; ++i)
     180        {
     181            if(i < size-1)
     182                addNode(w.nodes.get(i), middlenodes);
     183            ways.add(new MyWaySegment(w, w.nodes.get(i-1), w.nodes.get(i)));
     184        }
     185        Set<Node> set = endnodes;
     186        if(w.get("highway") != null || w.get("railway") != null)
     187            set = endnodes_highway;
     188        addNode(w.nodes.get(0), set);
     189        addNode(w.nodes.get(size-1), set);
     190    }
     191    private void addNode(Node n, Set<Node> s)
     192    {
     193        Boolean m = middlenodes.contains(n);
     194        Boolean e = endnodes.contains(n);
     195        Boolean eh = endnodes_highway.contains(n);
     196        Boolean o = othernodes.contains(n);
     197        if(!m && !e && !o && !eh)
     198            s.add(n);
     199        else if(!o)
     200        {
     201            othernodes.add(n);
     202            if(e)
     203                endnodes.remove(n);
     204            else if(eh)
     205                endnodes_highway.remove(n);
     206            else
     207                middlenodes.remove(n);
     208        }
     209    }
    210210}
  • applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/UntaggedNode.java

    r10774 r12778  
    2222public class UntaggedNode extends Test
    2323{
    24         protected static int UNTAGGED_NODE = 201;
     24    protected static int UNTAGGED_NODE = 201;
    2525
    26         /** Bag of all nodes */
    27         Set<Node> emptyNodes;
     26    /** Bag of all nodes */
     27    Set<Node> emptyNodes;
    2828
    29         /**
    30         * Constructor
    31         */
    32         public UntaggedNode()
    33         {
    34                 super(tr("Untagged nodes."),
    35                           tr("This test checks for untagged nodes that are not part of any way."));
    36         }
     29    /**
     30    * Constructor
     31    */
     32    public UntaggedNode()
     33    {
     34        super(tr("Untagged nodes."),
     35              tr("This test checks for untagged nodes that are not part of any way."));
     36    }
    3737
    38         @Override
    39         public void startTest()
    40         {
    41                 emptyNodes = new HashSet<Node>(100);
    42         }
     38    @Override
     39    public void startTest()
     40    {
     41        emptyNodes = new HashSet<Node>(100);
     42    }
    4343
    44         @Override
    45         public void visit(Collection<OsmPrimitive> selection)
    46         {
    47                 // If there is a partial selection, it may be false positives if a
    48                 // node is selected, but not the container way. So, in this
    49                 // case, we must visit all ways, selected or not.
    50                 if (partialSelection) {
    51                         for (OsmPrimitive p : selection) {
    52                                 if (!p.deleted && !p.incomplete && p instanceof Node) {
    53                                         p.visit(this);
    54                                 }
    55                         }
    56                         for (Way w : Main.ds.ways) {
    57                                 visit(w);
    58                         }
    59                 } else {
    60                         for (OsmPrimitive p : selection) {
    61                                 if (!p.deleted && !p.incomplete) {
    62                                         p.visit(this);
    63                                 }
    64                         }
    65                 }
    66         }
     44    @Override
     45    public void visit(Collection<OsmPrimitive> selection)
     46    {
     47        // If there is a partial selection, it may be false positives if a
     48        // node is selected, but not the container way. So, in this
     49        // case, we must visit all ways, selected or not.
     50        if (partialSelection) {
     51            for (OsmPrimitive p : selection) {
     52                if (!p.deleted && !p.incomplete && p instanceof Node) {
     53                    p.visit(this);
     54                }
     55            }
     56            for (Way w : Main.ds.ways) {
     57                visit(w);
     58            }
     59        } else {
     60            for (OsmPrimitive p : selection) {
     61                if (!p.deleted && !p.incomplete) {
     62                    p.visit(this);
     63                }
     64            }
     65        }
     66    }
    6767
    68         @Override
    69         public void visit(Node n)
    70         {
    71                 if(!n.incomplete && !n.deleted && !n.tagged)
    72                         emptyNodes.add(n);
    73         }
     68    @Override
     69    public void visit(Node n)
     70    {
     71        if(!n.incomplete && !n.deleted && !n.tagged)
     72            emptyNodes.add(n);
     73    }
    7474
    75         @Override
    76         public void visit(Way w)
    77         {
    78                 for (Node n : w.nodes) {
    79                         emptyNodes.remove(n);
    80                 }
    81         }
     75    @Override
     76    public void visit(Way w)
     77    {
     78        for (Node n : w.nodes) {
     79            emptyNodes.remove(n);
     80        }
     81    }
    8282
    83         @Override
    84         public void endTest()
    85         {
    86                 for(Node node : emptyNodes)
    87                 {
    88                         errors.add( new TestError(this, Severity.OTHER, tr("Untagged and unconnected nodes"), UNTAGGED_NODE, node) );
    89                 }
    90                 emptyNodes = null;
    91         }
     83    @Override
     84    public void endTest()
     85    {
     86        for(Node node : emptyNodes)
     87        {
     88            errors.add( new TestError(this, Severity.OTHER, tr("Untagged and unconnected nodes"), UNTAGGED_NODE, node) );
     89        }
     90        emptyNodes = null;
     91    }
    9292
    93         @Override
    94         public Command fixError(TestError testError)
    95         {
    96                 return DeleteCommand.delete(testError.getPrimitives());
    97         }
     93    @Override
     94    public Command fixError(TestError testError)
     95    {
     96        return DeleteCommand.delete(testError.getPrimitives());
     97    }
    9898
    99         @Override
    100         public boolean isFixable(TestError testError)
    101         {
    102                 return (testError.getTester() instanceof UntaggedNode);
    103         }
     99    @Override
     100    public boolean isFixable(TestError testError)
     101    {
     102        return (testError.getTester() instanceof UntaggedNode);
     103    }
    104104}
  • applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/UntaggedWay.java

    r10774 r12778  
    2121public class UntaggedWay extends Test
    2222{
    23         /** Empty way error */
    24         protected static final int EMPTY_WAY    = 301;
    25         /** Untagged way error */
    26         protected static final int UNTAGGED_WAY = 302;
    27         /** Unnamed way error */
    28         protected static final int UNNAMED_WAY  = 303;
    29         /** One node way error */
    30         protected static final int ONE_NODE_WAY = 304;
     23    /** Empty way error */
     24    protected static final int EMPTY_WAY    = 301;
     25    /** Untagged way error */
     26    protected static final int UNTAGGED_WAY = 302;
     27    /** Unnamed way error */
     28    protected static final int UNNAMED_WAY  = 303;
     29    /** One node way error */
     30    protected static final int ONE_NODE_WAY = 304;
    3131
    32         /** Ways that must have a name */
    33         public static final Set<String> NAMED_WAYS = new HashSet<String>();
    34         static
    35         {
    36                 NAMED_WAYS.add( "motorway" );
    37                 NAMED_WAYS.add( "trunk" );
    38                 NAMED_WAYS.add( "primary" );
    39                 NAMED_WAYS.add( "secondary" );
    40                 NAMED_WAYS.add( "tertiary" );
    41                 NAMED_WAYS.add( "residential" );
    42                 NAMED_WAYS.add( "pedestrian" ); ;
    43         }
     32    /** Ways that must have a name */
     33    public static final Set<String> NAMED_WAYS = new HashSet<String>();
     34    static
     35    {
     36        NAMED_WAYS.add( "motorway" );
     37        NAMED_WAYS.add( "trunk" );
     38        NAMED_WAYS.add( "primary" );
     39        NAMED_WAYS.add( "secondary" );
     40        NAMED_WAYS.add( "tertiary" );
     41        NAMED_WAYS.add( "residential" );
     42        NAMED_WAYS.add( "pedestrian" ); ;
     43    }
    4444
    45         /**
    46         * Constructor
    47         */
    48         public UntaggedWay()
    49         {
    50                 super(tr("Untagged, empty, and one node ways."),
    51                           tr("This test checks for untagged, empty and one node ways."));
    52         }
     45    /**
     46    * Constructor
     47    */
     48    public UntaggedWay()
     49    {
     50        super(tr("Untagged, empty, and one node ways."),
     51              tr("This test checks for untagged, empty and one node ways."));
     52    }
    5353
    54         @Override
    55         public void visit(Way w)
    56         {
    57                 if (w.deleted || w.incomplete) return;
     54    @Override
     55    public void visit(Way w)
     56    {
     57        if (w.deleted || w.incomplete) return;
    5858
    59                 Map<String, String> tags = w.keys;
    60                 if( tags != null )
    61                 {
    62                         String highway = tags.get("highway");
    63                         if(highway != null && NAMED_WAYS.contains(highway))
    64                         {
    65                                 if( !tags.containsKey("name") && !tags.containsKey("ref") )
    66                                 {
    67                                         boolean hasName = false;
    68                                         for( String key : w.keySet())
    69                                         {
    70                                                 hasName = key.startsWith("name:") || key.endsWith("_name") || key.endsWith("_ref");
    71                                                 if( hasName )
    72                                                         break;
    73                                         }
     59        Map<String, String> tags = w.keys;
     60        if( tags != null )
     61        {
     62            String highway = tags.get("highway");
     63            if(highway != null && NAMED_WAYS.contains(highway))
     64            {
     65                if( !tags.containsKey("name") && !tags.containsKey("ref") )
     66                {
     67                    boolean hasName = false;
     68                    for( String key : w.keySet())
     69                    {
     70                        hasName = key.startsWith("name:") || key.endsWith("_name") || key.endsWith("_ref");
     71                        if( hasName )
     72                            break;
     73                    }
    7474
    75                                         if( !hasName)
    76                                                 errors.add( new TestError(this, Severity.WARNING, tr("Unnamed ways"), UNNAMED_WAY, w) );
    77                                 }
    78                         }
    79                 }
     75                    if( !hasName)
     76                        errors.add( new TestError(this, Severity.WARNING, tr("Unnamed ways"), UNNAMED_WAY, w) );
     77                }
     78            }
     79        }
    8080
    81                 if(!w.tagged)
    82                 {
    83                         errors.add( new TestError(this, Severity.WARNING, tr("Untagged ways"), UNTAGGED_WAY, w) );
    84                 }
     81        if(!w.tagged)
     82        {
     83            errors.add( new TestError(this, Severity.WARNING, tr("Untagged ways"), UNTAGGED_WAY, w) );
     84        }
    8585
    86                 if( w.nodes.size() == 0 )
    87                 {
    88                         errors.add( new TestError(this, Severity.ERROR, tr("Empty ways"), EMPTY_WAY, w) );
    89                 }
    90                 else if( w.nodes.size() == 1 )
    91                 {
    92                         errors.add( new TestError(this, Severity.ERROR, tr("One node ways"), ONE_NODE_WAY, w) );
    93                 }
     86        if( w.nodes.size() == 0 )
     87        {
     88            errors.add( new TestError(this, Severity.ERROR, tr("Empty ways"), EMPTY_WAY, w) );
     89        }
     90        else if( w.nodes.size() == 1 )
     91        {
     92            errors.add( new TestError(this, Severity.ERROR, tr("One node ways"), ONE_NODE_WAY, w) );
     93        }
    9494
    95         }
     95    }
    9696
    97         @Override
    98         public boolean isFixable(TestError testError)
    99         {
    100                 if( testError.getTester() instanceof UntaggedWay )
    101                 {
    102                         return testError.getCode() == EMPTY_WAY
    103                                 || testError.getCode() == ONE_NODE_WAY;
    104                 }
     97    @Override
     98    public boolean isFixable(TestError testError)
     99    {
     100        if( testError.getTester() instanceof UntaggedWay )
     101        {
     102            return testError.getCode() == EMPTY_WAY
     103                || testError.getCode() == ONE_NODE_WAY;
     104        }
    105105
    106                 return false;
    107         }
     106        return false;
     107    }
    108108
    109         @Override
    110         public Command fixError(TestError testError)
    111         {
    112                 return DeleteCommand.delete(testError.getPrimitives());
    113         }
     109    @Override
     110    public Command fixError(TestError testError)
     111    {
     112        return DeleteCommand.delete(testError.getPrimitives());
     113    }
    114114}
  • applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/WronglyOrderedWays.java

    r11530 r12778  
    1919 */
    2020public class WronglyOrderedWays extends Test  {
    21         protected static int WRONGLY_ORDERED_COAST = 1001;
    22         protected static int WRONGLY_ORDERED_WATER = 1002;
    23         protected static int WRONGLY_ORDERED_LAND  = 1003;
     21    protected static int WRONGLY_ORDERED_COAST = 1001;
     22    protected static int WRONGLY_ORDERED_WATER = 1002;
     23    protected static int WRONGLY_ORDERED_LAND  = 1003;
    2424
    25         /** The already detected errors */
    26         Bag<Way, Way> _errorWays;
     25    /** The already detected errors */
     26    Bag<Way, Way> _errorWays;
    2727
    28         /**
    29         * Constructor
    30         */
    31         public WronglyOrderedWays()
    32         {
    33                 super(tr("Wrongly Ordered Ways."),
    34                           tr("This test checks the direction of water, land and coastline ways."));
    35         }
     28    /**
     29    * Constructor
     30    */
     31    public WronglyOrderedWays()
     32    {
     33        super(tr("Wrongly Ordered Ways."),
     34              tr("This test checks the direction of water, land and coastline ways."));
     35    }
    3636
    37         @Override
    38         public void startTest()
    39         {
    40                 _errorWays = new Bag<Way, Way>();
    41         }
     37    @Override
     38    public void startTest()
     39    {
     40        _errorWays = new Bag<Way, Way>();
     41    }
    4242
    43         @Override
    44         public void endTest()
    45         {
    46                 _errorWays = null;
    47         }
     43    @Override
     44    public void endTest()
     45    {
     46        _errorWays = null;
     47    }
    4848
    49         @Override
    50         public void visit(Way w)
    51         {
    52                 String errortype = "";
    53                 int type;
     49    @Override
     50    public void visit(Way w)
     51    {
     52        String errortype = "";
     53        int type;
    5454
    55                 if( w.deleted || w.incomplete )
    56                         return;
     55        if( w.deleted || w.incomplete )
     56            return;
    5757
    58                 String natural = w.get("natural");
    59                 if( natural == null)
    60                         return;
     58        String natural = w.get("natural");
     59        if( natural == null)
     60            return;
    6161
    62                 if( natural.equals("coastline") )
    63                 {
    64                         errortype = tr("Reversed coastline: land not on left side");
    65                         type= WRONGLY_ORDERED_COAST;
    66                 }
    67                 else if(natural.equals("water") )
    68                 {
    69                         errortype = tr("Reversed water: land not on left side");
    70                         type= WRONGLY_ORDERED_WATER;
    71                 }
    72                 else if( natural.equals("land") )
    73                 {
    74                         errortype = tr("Reversed land: land not on left side");
    75                         type= WRONGLY_ORDERED_LAND;
    76                 }
    77                 else
    78                         return;
     62        if( natural.equals("coastline") )
     63        {
     64            errortype = tr("Reversed coastline: land not on left side");
     65            type= WRONGLY_ORDERED_COAST;
     66        }
     67        else if(natural.equals("water") )
     68        {
     69            errortype = tr("Reversed water: land not on left side");
     70            type= WRONGLY_ORDERED_WATER;
     71        }
     72        else if( natural.equals("land") )
     73        {
     74            errortype = tr("Reversed land: land not on left side");
     75            type= WRONGLY_ORDERED_LAND;
     76        }
     77        else
     78            return;
    7979
    8080
    81                 /**
    82                 * Test the directionality of the way
    83                 *
    84                 * Assuming a closed non-looping way, compute twice the area
    85                 * of the polygon using the formula 2*a = sum (Xn * Yn+1 - Xn+1 * Yn)
    86                 * If the area is negative the way is ordered in a clockwise direction
    87                 *
    88                 */
     81        /**
     82        * Test the directionality of the way
     83        *
     84        * Assuming a closed non-looping way, compute twice the area
     85        * of the polygon using the formula 2*a = sum (Xn * Yn+1 - Xn+1 * Yn)
     86        * If the area is negative the way is ordered in a clockwise direction
     87        *
     88        */
    8989
    90                 if(w.nodes.get(0) == w.nodes.get(w.nodes.size()-1))
    91                 {
    92                         double area2 = 0;
     90        if(w.nodes.get(0) == w.nodes.get(w.nodes.size()-1))
     91        {
     92            double area2 = 0;
    9393
    94                         for (int node = 1; node < w.nodes.size(); node++)
    95                         {
    96                                 area2 += (w.nodes.get(node-1).coor.lon() * w.nodes.get(node).coor.lat()
    97                                 - w.nodes.get(node).coor.lon() * w.nodes.get(node-1).coor.lat());
    98                         }
     94            for (int node = 1; node < w.nodes.size(); node++)
     95            {
     96                area2 += (w.nodes.get(node-1).coor.lon() * w.nodes.get(node).coor.lat()
     97                - w.nodes.get(node).coor.lon() * w.nodes.get(node-1).coor.lat());
     98            }
    9999
    100                         if(((natural.equals("coastline") || natural.equals("land")) && area2 < 0.)
    101                         || (natural.equals("water") && area2 > 0.))
    102                         {
    103                                 List<OsmPrimitive> primitives = new ArrayList<OsmPrimitive>();
    104                                 primitives.add(w);
    105                                 errors.add( new TestError(this, Severity.WARNING, errortype, type, primitives) );
    106                                 _errorWays.add(w,w);
    107                         }
    108                 }
    109         }
     100            if(((natural.equals("coastline") || natural.equals("land")) && area2 < 0.)
     101            || (natural.equals("water") && area2 > 0.))
     102            {
     103                List<OsmPrimitive> primitives = new ArrayList<OsmPrimitive>();
     104                primitives.add(w);
     105                errors.add( new TestError(this, Severity.WARNING, errortype, type, primitives) );
     106                _errorWays.add(w,w);
     107            }
     108        }
     109    }
    110110}
  • applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/util/AgregatePrimitivesVisitor.java

    r12777 r12778  
    1212 * <p>
    1313 * The primitives are sorted according to their type: first nodes, then ways.
    14  * 
     14 *
    1515 * @author frsantos
    1616 */
    1717public class AgregatePrimitivesVisitor implements Visitor
    1818{
    19         /** Aggregated data */
    20         Collection<OsmPrimitive> aggregatedData;
     19    /** Aggregated data */
     20    Collection<OsmPrimitive> aggregatedData;
    2121
    22         /**
    23         * Constructor
    24         */
    25         public AgregatePrimitivesVisitor()
    26         {
    27                 aggregatedData = new LinkedList<OsmPrimitive>();
    28         }
     22    /**
     23    * Constructor
     24    */
     25    public AgregatePrimitivesVisitor()
     26    {
     27        aggregatedData = new LinkedList<OsmPrimitive>();
     28    }
    2929
    30         /**
    31          * Visits a collection of primitives
    32          * @param data The collection of primitives
    33          * @return The aggregated primitives
    34          */
    35         public Collection<OsmPrimitive> visit(Collection<OsmPrimitive> data)
    36         {
    37                 for (OsmPrimitive osm : data)
    38                 {
    39                         osm.visit(this);
    40                 }
    41                
    42                 return aggregatedData;
    43         }
     30    /**
     31     * Visits a collection of primitives
     32     * @param data The collection of primitives
     33     * @return The aggregated primitives
     34     */
     35    public Collection<OsmPrimitive> visit(Collection<OsmPrimitive> data)
     36    {
     37        for (OsmPrimitive osm : data)
     38        {
     39            osm.visit(this);
     40        }
    4441
    45         public void visit(Node n)
    46         {
    47                 if(!aggregatedData.contains(n))
    48                         aggregatedData.add(n);
    49         }
     42        return aggregatedData;
     43    }
    5044
    51         public void visit(Way w)
    52         {
    53                 if(!aggregatedData.contains(w))
    54                 {
    55                         aggregatedData.add(w);
    56                         for (Node n : w.nodes)
    57                                 visit(n);
    58                 }
    59         }
     45    public void visit(Node n)
     46    {
     47        if(!aggregatedData.contains(n))
     48            aggregatedData.add(n);
     49    }
    6050
    61         public void visit(Relation r) {
    62                 if (!aggregatedData.contains(r)) {
    63                         aggregatedData.add(r);
    64                         for (RelationMember m : r.members) {
    65                                 m.member.visit(this);
    66                         }
    67                 }
    68         }
     51    public void visit(Way w)
     52    {
     53        if(!aggregatedData.contains(w))
     54        {
     55            aggregatedData.add(w);
     56            for (Node n : w.nodes)
     57                visit(n);
     58        }
     59    }
     60
     61    public void visit(Relation r) {
     62        if (!aggregatedData.contains(r)) {
     63            aggregatedData.add(r);
     64            for (RelationMember m : r.members) {
     65                m.member.visit(this);
     66            }
     67        }
     68    }
    6969}
  • applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/util/Bag.java

    r2453 r12778  
    66
    77/**
    8  * 
     8 *
    99 * A very simple bag to store multiple occurences of a same key.
    1010 * <p>
    1111 * The bag will keep, for each key, a list of values.
    12  * 
     12 *
    1313 * @author frsantos
    1414 *
     
    1616 * @param <V> The value class
    1717 */
    18 public class Bag<K,V> extends HashMap<K, List<V>> 
     18public class Bag<K,V> extends HashMap<K, List<V>>
    1919{
    2020    /** Serializable ID */
     
    2222
    2323    /**
    24         * Returns the list of elements with the same key
    25         * @param key The key to obtain the elements
    26         * @return the list of elements with the same key
    27         */
    28         public List<V> get(K key)
    29         {
    30                 return super.get(key);
    31         }
     24    * Returns the list of elements with the same key
     25    * @param key The key to obtain the elements
     26    * @return the list of elements with the same key
     27    */
     28    public List<V> get(K key)
     29    {
     30        return super.get(key);
     31    }
    3232
    33         /**
    34         * Adds an element to the bag
    35         * @param key The key of the element
    36         * @param value The element to add
    37         */
    38         public void add(K key, V value)
    39         {
    40                 List<V> values = get(key);
    41                 if( values == null )
    42                 {
    43                         values = new ArrayList<V>();
    44                         put(key, values);
    45                 }
    46                 values.add(value);
    47         }
     33    /**
     34    * Adds an element to the bag
     35    * @param key The key of the element
     36    * @param value The element to add
     37    */
     38    public void add(K key, V value)
     39    {
     40        List<V> values = get(key);
     41        if( values == null )
     42        {
     43            values = new ArrayList<V>();
     44            put(key, values);
     45        }
     46        values.add(value);
     47    }
    4848
    49         /**
    50         * Constructor
    51         */
    52         public Bag()
    53         {
    54                 super();
    55         }
     49    /**
     50    * Constructor
     51    */
     52    public Bag()
     53    {
     54        super();
     55    }
    5656
    57         /**
    58         * Constructor
    59          *
    60         * @param initialCapacity The initial capacity
    61         */
    62         public Bag(int initialCapacity)
    63         {
    64                 super(initialCapacity);
    65         }
     57    /**
     58    * Constructor
     59     *
     60    * @param initialCapacity The initial capacity
     61    */
     62    public Bag(int initialCapacity)
     63    {
     64        super(initialCapacity);
     65    }
    6666
    67         /**
    68         * Returns true if the bag contains a value for a key
    69         * @param key The key
    70         * @param value The value
    71         * @return true if the key contains the value
    72         */
    73         public boolean contains(K key, V value)
    74         {
    75                 List<V> values = get(key);
    76                 return (values == null) ? false : values.contains(value);
    77         }
     67    /**
     68    * Returns true if the bag contains a value for a key
     69    * @param key The key
     70    * @param value The value
     71    * @return true if the key contains the value
     72    */
     73    public boolean contains(K key, V value)
     74    {
     75        List<V> values = get(key);
     76        return (values == null) ? false : values.contains(value);
     77    }
    7878}
  • applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/util/Entities.java

    r10532 r12778  
    66 * (the "License"); you may not use this file except in compliance with
    77 * the License.  You may obtain a copy of the License at
    8  * 
     8 *
    99 *      http://www.apache.org/licenses/LICENSE-2.0
    10  * 
     10 *
    1111 * Unless required by applicable law or agreed to in writing, software
    1212 * distributed under the License is distributed on an "AS IS" BASIS,
  • applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/util/MultipleNameVisitor.java

    r9598 r12778  
    1515/**
    1616 * Able to create a name and an icon for a collection of elements.
    17  * 
     17 *
    1818 * @author frsantos
    1919 */
    20 public class MultipleNameVisitor extends NameVisitor 
     20public class MultipleNameVisitor extends NameVisitor
    2121{
    22         /** The class name of the combined primitives */
    23         String multipleClassname;
    24         /* name to be displayed */
    25         String displayName;
    26         /** Size of the collection */
    27         int size;
    28        
    29         /**
    30          * Visits a collection of primitives
    31          * @param data The collection of primitives
    32          */
    33         public void visit(Collection<? extends OsmPrimitive> data)
    34         {
    35                 String multipleName = null;
    36                 String multiplePluralClassname = null;
    37                 String firstName = null;
    38                 boolean initializedname = false;
    39                 size = data.size();
     22    /** The class name of the combined primitives */
     23    String multipleClassname;
     24    /* name to be displayed */
     25    String displayName;
     26    /** Size of the collection */
     27    int size;
    4028
    41                 multipleClassname = null;
    42                 for (OsmPrimitive osm : data)
    43                 {
    44                         String name = osm.get("name");
    45                         if(name == null) name = osm.get("ref");
    46                         if(!initializedname)
    47                         {
    48                                 multipleName = name; initializedname = true;
    49                         }
    50                         else if(multipleName != null && (name == null  || !name.equals(multipleName)))
    51                         {
    52                                 multipleName = null;
    53                         }
     29    /**
     30     * Visits a collection of primitives
     31     * @param data The collection of primitives
     32     */
     33    public void visit(Collection<? extends OsmPrimitive> data)
     34    {
     35        String multipleName = null;
     36        String multiplePluralClassname = null;
     37        String firstName = null;
     38        boolean initializedname = false;
     39        size = data.size();
    5440
    55                         if(firstName == null && name != null)
    56                                 firstName = name;
    57                         osm.visit(this);
    58                         if (multipleClassname == null)
    59                         {
    60                                 multipleClassname = className;
    61                                 multiplePluralClassname = classNamePlural;
    62                         }
    63                         else if (!multipleClassname.equals(className))
    64                         {
    65                                 multipleClassname = "object";
    66                                 multiplePluralClassname = trn("object", "objects", 2);
    67                         }
    68                 }
     41        multipleClassname = null;
     42        for (OsmPrimitive osm : data)
     43        {
     44            String name = osm.get("name");
     45            if(name == null) name = osm.get("ref");
     46            if(!initializedname)
     47            {
     48                multipleName = name; initializedname = true;
     49            }
     50            else if(multipleName != null && (name == null  || !name.equals(multipleName)))
     51            {
     52                multipleName = null;
     53            }
    6954
    70                 if( size == 1 )
    71                         displayName = name;
    72                 else if(multipleName != null)
    73                         displayName = size + " " + trn(multipleClassname, multiplePluralClassname, size) + ": " + multipleName;
    74                 else if(firstName != null)
    75                         displayName = size + " " + trn(multipleClassname, multiplePluralClassname, size) + ": " + tr("{0}, ...", firstName);
    76                 else
    77                         displayName = size + " " + trn(multipleClassname, multiplePluralClassname, size);
    78         }
     55            if(firstName == null && name != null)
     56                firstName = name;
     57            osm.visit(this);
     58            if (multipleClassname == null)
     59            {
     60                multipleClassname = className;
     61                multiplePluralClassname = classNamePlural;
     62            }
     63            else if (!multipleClassname.equals(className))
     64            {
     65                multipleClassname = "object";
     66                multiplePluralClassname = trn("object", "objects", 2);
     67            }
     68        }
    7969
    80         @Override
    81         public JLabel toLabel()
    82         {
    83                 return new JLabel(getText(), getIcon(), JLabel.HORIZONTAL);
    84         }
     70        if( size == 1 )
     71            displayName = name;
     72        else if(multipleName != null)
     73            displayName = size + " " + trn(multipleClassname, multiplePluralClassname, size) + ": " + multipleName;
     74        else if(firstName != null)
     75            displayName = size + " " + trn(multipleClassname, multiplePluralClassname, size) + ": " + tr("{0}, ...", firstName);
     76        else
     77            displayName = size + " " + trn(multipleClassname, multiplePluralClassname, size);
     78    }
    8579
    86         /**
    87          * Gets the name of the items
    88          * @return the name of the items
    89          */
    90         public String getText()
    91         {
    92                 return displayName;
    93         }
     80    @Override
     81    public JLabel toLabel()
     82    {
     83        return new JLabel(getText(), getIcon(), JLabel.HORIZONTAL);
     84    }
    9485
    95         /**
    96          * Gets the icon of the items
    97          * @return the icon of the items
    98          */
    99         public Icon getIcon()
    100         {
    101                 if( size == 1 )
    102                         return icon;
    103                 else
    104                         return ImageProvider.get("data", multipleClassname);
    105         }
     86    /**
     87     * Gets the name of the items
     88     * @return the name of the items
     89     */
     90    public String getText()
     91    {
     92        return displayName;
     93    }
     94
     95    /**
     96     * Gets the icon of the items
     97     * @return the icon of the items
     98     */
     99    public Icon getIcon()
     100    {
     101        if( size == 1 )
     102            return icon;
     103        else
     104            return ImageProvider.get("data", multipleClassname);
     105    }
    106106}
  • applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/util/Util.java

    r12257 r12778  
    2222public class Util
    2323{
    24         /**
    25         * Returns the plugin's directory of the plugin
    26         *
    27         * @return The directory of the plugin
    28         */
    29         public static String getPluginDir()
    30         {
    31                 return Main.pref.getPreferencesDir() + "plugins/validator/";
    32         }
    33 
    34         /**
    35         * Returns the version
    36         * @return The version of the application
    37         */
    38         public static Version getVersion()
    39         {
    40                 PluginInformation info = PluginInformation.getLoaded("validator");
    41                 if( info == null )
    42                         return null;
    43 
    44                 return new Version(info.version, info.attr.get("Plugin-Date"));
    45         }
    46 
    47         /**
    48         * Utility class for displaying versions
    49         *
    50         * @author frsantos
    51         */
    52         public static class Version
    53         {
    54                 /** The revision */
    55                 public String revision;
    56                 /** The build time */
    57                 public String time;
    58 
    59                 /**
    60                 * Constructor
    61                 * @param revision
    62                 * @param time
    63                 */
    64                 public Version(String revision, String time)
    65                 {
    66                         this.revision = revision;
    67                         this.time = time;
    68                 }
    69         }
    70 
    71         /**
    72         * Returns the start and end cells of a way.
    73         * @param w The way
    74         * @param cellWays The map with all cells
    75         * @return A list with all the cells the way starts or ends
    76         */
    77         public static List<List<Way>> getWaysInCell(Way w, Map<Point2D,List<Way>> cellWays)
    78         {
    79                 if (w.nodes.size() == 0)
    80                         return Collections.emptyList();
    81 
    82                 Node n1 = w.nodes.get(0);
    83                 Node n2 = w.nodes.get(w.nodes.size() - 1);
    84 
    85                 List<List<Way>> cells = new ArrayList<List<Way>>(2);
    86                 Set<Point2D> cellNodes = new HashSet<Point2D>();
    87                 Point2D cell;
    88 
    89                 // First, round coordinates
    90                 long x0 = Math.round(n1.eastNorth.east()  * OSMValidatorPlugin.griddetail);
    91                 long y0 = Math.round(n1.eastNorth.north() * OSMValidatorPlugin.griddetail);
    92                 long x1 = Math.round(n2.eastNorth.east()  * OSMValidatorPlugin.griddetail);
    93                 long y1 = Math.round(n2.eastNorth.north() * OSMValidatorPlugin.griddetail);
    94 
    95                 // Start of the way
    96                 cell = new Point2D.Double(x0, y0);
    97                 cellNodes.add(cell);
    98                 List<Way> ways = cellWays.get( cell );
    99                 if( ways == null )
    100                 {
    101                         ways = new ArrayList<Way>();
    102                         cellWays.put(cell, ways);
    103                 }
    104                 cells.add(ways);
    105 
    106                 // End of the way
    107                 cell = new Point2D.Double(x1, y1);
    108                 if( !cellNodes.contains(cell) )
    109                 {
    110                         cellNodes.add(cell);
    111                         ways = cellWays.get( cell );
    112                         if( ways == null )
    113                         {
    114                                 ways = new ArrayList<Way>();
    115                                 cellWays.put(cell, ways);
    116                         }
    117                         cells.add(ways);
    118                 }
    119 
    120                 // Then floor coordinates, in case the way is in the border of the cell.
    121                 x0 = (long)Math.floor(n1.eastNorth.east()  * OSMValidatorPlugin.griddetail);
    122                 y0 = (long)Math.floor(n1.eastNorth.north() * OSMValidatorPlugin.griddetail);
    123                 x1 = (long)Math.floor(n2.eastNorth.east()  * OSMValidatorPlugin.griddetail);
    124                 y1 = (long)Math.floor(n2.eastNorth.north() * OSMValidatorPlugin.griddetail);
    125 
    126                 // Start of the way
    127                 cell = new Point2D.Double(x0, y0);
    128                 if( !cellNodes.contains(cell) )
    129                 {
    130                         cellNodes.add(cell);
    131                         ways = cellWays.get( cell );
    132                         if( ways == null )
    133                         {
    134                                 ways = new ArrayList<Way>();
    135                                 cellWays.put(cell, ways);
    136                         }
    137                         cells.add(ways);
    138                 }
    139 
    140                 // End of the way
    141                 cell = new Point2D.Double(x1, y1);
    142                 if( !cellNodes.contains(cell) )
    143                 {
    144                         cellNodes.add(cell);
    145                         ways = cellWays.get( cell );
    146                         if( ways == null )
    147                         {
    148                                 ways = new ArrayList<Way>();
    149                                 cellWays.put(cell, ways);
    150                         }
    151                         cells.add(ways);
    152                 }
    153 
    154                 return cells;
    155         }
    156 
    157         /**
    158         * Returns the coordinates of all cells in a grid that a line between 2
    159         * nodes intersects with.
    160         *
    161         * @param n1 The first node.
    162         * @param n2 The second node.
    163         * @param gridDetail The detail of the grid. Bigger values give smaller
    164         * cells, but a bigger number of them.
    165         * @return A list with the coordinates of all cells
    166         */
    167         public static List<Point2D> getSegmentCells(Node n1, Node n2, double gridDetail)
    168         {
    169                 List<Point2D> cells = new ArrayList<Point2D>();
    170                 double x0 = n1.eastNorth.east() * gridDetail;
    171                 double x1 = n2.eastNorth.east() * gridDetail;
    172                 double y0 = n1.eastNorth.north() * gridDetail + 1;
    173                 double y1 = n2.eastNorth.north() * gridDetail + 1;
    174 
    175                 if( x0 > x1 )
    176                 {
    177                         // Move to 1st-4th cuadrants
    178                         double aux;
    179                         aux = x0; x0 = x1; x1 = aux;
    180                         aux = y0; y0 = y1; y1 = aux;
    181                 }
    182 
    183                 double dx  = x1 - x0;
    184                 double dy  = y1 - y0;
    185                 long stepY = y0 <= y1 ? 1 : -1;
    186                 long gridX0 = (long)Math.floor(x0);
    187                 long gridX1 = (long)Math.floor(x1);
    188                 long gridY0 = (long)Math.floor(y0);
    189                 long gridY1 = (long)Math.floor(y1);
    190 
    191                 long maxSteps = (gridX1 - gridX0) + Math.abs(gridY1 - gridY0) + 1;
    192                 while( (gridX0 <= gridX1 && (gridY0 - gridY1)*stepY <= 0) && maxSteps-- > 0)
    193                 {
    194                         cells.add( new Point2D.Double(gridX0, gridY0) );
    195 
    196                         // Is the cross between the segment and next vertical line nearer than the cross with next horizontal line?
    197                         // Note: segment line formula: y=dy/dx(x-x1)+y1
    198                         // Note: if dy < 0, must use *bottom* line. If dy > 0, must use upper line
    199                         double scanY = dy/dx * (gridX0 + 1 - x1) + y1 + (dy < 0 ? -1 : 0);
    200                         double scanX = dx/dy * (gridY0 + (dy < 0 ? 0 : 1)*stepY - y1) + x1;
    201 
    202                         double distX = Math.pow(gridX0 + 1 - x0, 2) + Math.pow(scanY - y0, 2);
    203                         double distY = Math.pow(scanX - x0, 2) + Math.pow(gridY0 + stepY - y0, 2);
    204 
    205                         if( distX < distY)
    206                                 gridX0 += 1;
    207                         else
    208                                 gridY0 += stepY;
    209                 }
    210 
    211                 return cells;
    212         }
     24    /**
     25    * Returns the plugin's directory of the plugin
     26    *
     27    * @return The directory of the plugin
     28    */
     29    public static String getPluginDir()
     30    {
     31        return Main.pref.getPreferencesDir() + "plugins/validator/";
     32    }
     33
     34    /**
     35    * Returns the version
     36    * @return The version of the application
     37    */
     38    public static Version getVersion()
     39    {
     40        PluginInformation info = PluginInformation.getLoaded("validator");
     41        if( info == null )
     42            return null;
     43
     44        return new Version(info.version, info.attr.get("Plugin-Date"));
     45    }
     46
     47    /**
     48    * Utility class for displaying versions
     49    *
     50    * @author frsantos
     51    */
     52    public static class Version
     53    {
     54        /** The revision */
     55        public String revision;
     56        /** The build time */
     57        public String time;
     58
     59        /**
     60        * Constructor
     61        * @param revision
     62        * @param time
     63        */
     64        public Version(String revision, String time)
     65        {
     66            this.revision = revision;
     67            this.time = time;
     68        }
     69    }
     70
     71    /**
     72    * Returns the start and end cells of a way.
     73    * @param w The way
     74    * @param cellWays The map with all cells
     75    * @return A list with all the cells the way starts or ends
     76    */
     77    public static List<List<Way>> getWaysInCell(Way w, Map<Point2D,List<Way>> cellWays)
     78    {
     79        if (w.nodes.size() == 0)
     80            return Collections.emptyList();
     81
     82        Node n1 = w.nodes.get(0);
     83        Node n2 = w.nodes.get(w.nodes.size() - 1);
     84
     85        List<List<Way>> cells = new ArrayList<List<Way>>(2);
     86        Set<Point2D> cellNodes = new HashSet<Point2D>();
     87        Point2D cell;
     88
     89        // First, round coordinates
     90        long x0 = Math.round(n1.eastNorth.east()  * OSMValidatorPlugin.griddetail);
     91        long y0 = Math.round(n1.eastNorth.north() * OSMValidatorPlugin.griddetail);
     92        long x1 = Math.round(n2.eastNorth.east()  * OSMValidatorPlugin.griddetail);
     93        long y1 = Math.round(n2.eastNorth.north() * OSMValidatorPlugin.griddetail);
     94
     95        // Start of the way
     96        cell = new Point2D.Double(x0, y0);
     97        cellNodes.add(cell);
     98        List<Way> ways = cellWays.get( cell );
     99        if( ways == null )
     100        {
     101            ways = new ArrayList<Way>();
     102            cellWays.put(cell, ways);
     103        }
     104        cells.add(ways);
     105
     106        // End of the way
     107        cell = new Point2D.Double(x1, y1);
     108        if( !cellNodes.contains(cell) )
     109        {
     110            cellNodes.add(cell);
     111            ways = cellWays.get( cell );
     112            if( ways == null )
     113            {
     114                ways = new ArrayList<Way>();
     115                cellWays.put(cell, ways);
     116            }
     117            cells.add(ways);
     118        }
     119
     120        // Then floor coordinates, in case the way is in the border of the cell.
     121        x0 = (long)Math.floor(n1.eastNorth.east()  * OSMValidatorPlugin.griddetail);
     122        y0 = (long)Math.floor(n1.eastNorth.north() * OSMValidatorPlugin.griddetail);
     123        x1 = (long)Math.floor(n2.eastNorth.east()  * OSMValidatorPlugin.griddetail);
     124        y1 = (long)Math.floor(n2.eastNorth.north() * OSMValidatorPlugin.griddetail);
     125
     126        // Start of the way
     127        cell = new Point2D.Double(x0, y0);
     128        if( !cellNodes.contains(cell) )
     129        {
     130            cellNodes.add(cell);
     131            ways = cellWays.get( cell );
     132            if( ways == null )
     133            {
     134                ways = new ArrayList<Way>();
     135                cellWays.put(cell, ways);
     136            }
     137            cells.add(ways);
     138        }
     139
     140        // End of the way
     141        cell = new Point2D.Double(x1, y1);
     142        if( !cellNodes.contains(cell) )
     143        {
     144            cellNodes.add(cell);
     145            ways = cellWays.get( cell );
     146            if( ways == null )
     147            {
     148                ways = new ArrayList<Way>();
     149                cellWays.put(cell, ways);
     150            }
     151            cells.add(ways);
     152        }
     153
     154        return cells;
     155    }
     156
     157    /**
     158    * Returns the coordinates of all cells in a grid that a line between 2
     159    * nodes intersects with.
     160    *
     161    * @param n1 The first node.
     162    * @param n2 The second node.
     163    * @param gridDetail The detail of the grid. Bigger values give smaller
     164    * cells, but a bigger number of them.
     165    * @return A list with the coordinates of all cells
     166    */
     167    public static List<Point2D> getSegmentCells(Node n1, Node n2, double gridDetail)
     168    {
     169        List<Point2D> cells = new ArrayList<Point2D>();
     170        double x0 = n1.eastNorth.east() * gridDetail;
     171        double x1 = n2.eastNorth.east() * gridDetail;
     172        double y0 = n1.eastNorth.north() * gridDetail + 1;
     173        double y1 = n2.eastNorth.north() * gridDetail + 1;
     174
     175        if( x0 > x1 )
     176        {
     177            // Move to 1st-4th cuadrants
     178            double aux;
     179            aux = x0; x0 = x1; x1 = aux;
     180            aux = y0; y0 = y1; y1 = aux;
     181        }
     182
     183        double dx  = x1 - x0;
     184        double dy  = y1 - y0;
     185        long stepY = y0 <= y1 ? 1 : -1;
     186        long gridX0 = (long)Math.floor(x0);
     187        long gridX1 = (long)Math.floor(x1);
     188        long gridY0 = (long)Math.floor(y0);
     189        long gridY1 = (long)Math.floor(y1);
     190
     191        long maxSteps = (gridX1 - gridX0) + Math.abs(gridY1 - gridY0) + 1;
     192        while( (gridX0 <= gridX1 && (gridY0 - gridY1)*stepY <= 0) && maxSteps-- > 0)
     193        {
     194            cells.add( new Point2D.Double(gridX0, gridY0) );
     195
     196            // Is the cross between the segment and next vertical line nearer than the cross with next horizontal line?
     197            // Note: segment line formula: y=dy/dx(x-x1)+y1
     198            // Note: if dy < 0, must use *bottom* line. If dy > 0, must use upper line
     199            double scanY = dy/dx * (gridX0 + 1 - x1) + y1 + (dy < 0 ? -1 : 0);
     200            double scanX = dx/dy * (gridY0 + (dy < 0 ? 0 : 1)*stepY - y1) + x1;
     201
     202            double distX = Math.pow(gridX0 + 1 - x0, 2) + Math.pow(scanY - y0, 2);
     203            double distY = Math.pow(scanX - x0, 2) + Math.pow(gridY0 + stepY - y0, 2);
     204
     205            if( distX < distY)
     206                gridX0 += 1;
     207            else
     208                gridY0 += stepY;
     209        }
     210
     211        return cells;
     212    }
    213213}
Note: See TracChangeset for help on using the changeset viewer.