001    // License: GPL. See LICENSE file for details.
002    package org.openstreetmap.josm.data.validation.tests;
003    
004    import static org.openstreetmap.josm.tools.I18n.marktr;
005    import static org.openstreetmap.josm.tools.I18n.tr;
006    
007    import java.text.MessageFormat;
008    import java.util.Arrays;
009    
010    import org.openstreetmap.josm.data.osm.OsmPrimitive;
011    import org.openstreetmap.josm.data.osm.OsmUtils;
012    import org.openstreetmap.josm.data.osm.Relation;
013    import org.openstreetmap.josm.data.osm.Way;
014    import org.openstreetmap.josm.data.validation.Severity;
015    import org.openstreetmap.josm.data.validation.Test;
016    import org.openstreetmap.josm.data.validation.TestError;
017    import org.openstreetmap.josm.gui.progress.ProgressMonitor;
018    
019    /**
020     * Check area type ways for errors
021     *
022     * @author stoecker
023     */
024    public class UnclosedWays extends Test {
025    
026        /**
027         * Constructor
028         */
029        public UnclosedWays() {
030            super(tr("Unclosed Ways"), tr("This tests if ways which should be circular are closed."));
031        }
032    
033        @Override
034        public void startTest(ProgressMonitor monitor) {
035            super.startTest(monitor);
036        }
037    
038        @Override
039        public void endTest() {
040            super.endTest();
041        }
042    
043        private String type;
044        private String etype;
045        private int mode;
046    
047        public void set(int m, String text, String desc) {
048            etype = MessageFormat.format(text, desc);
049            type = tr(text, tr(desc));
050            mode = m;
051        }
052    
053        public void set(int m, String text) {
054            etype = text;
055            type = tr(text);
056            mode = m;
057        }
058    
059        @Override
060        public void visit(Way w) {
061            String test;
062            type = etype = null;
063            mode = 0;
064    
065            if (!w.isUsable())
066                return;
067    
068            test = w.get("natural");
069            if (test != null && !"coastline".equals(test) && !"cliff".equals(test) && !"tree_row".equals(test)) {
070                set(1101, marktr("natural type {0}"), test);
071            }
072            test = w.get("landuse");
073            if (test != null) {
074                set(1102, marktr("landuse type {0}"), test);
075            }
076            test = w.get("amenities");
077            if (test != null) {
078                set(1103, marktr("amenities type {0}"), test);
079            }
080            test = w.get("sport");
081            if (test != null && !test.equals("water_slide")) {
082                set(1104, marktr("sport type {0}"), test);
083            }
084            test = w.get("tourism");
085            if (test != null) {
086                set(1105, marktr("tourism type {0}"), test);
087            }
088            test = w.get("shop");
089            if (test != null) {
090                set(1106, marktr("shop type {0}"), test);
091            }
092            test = w.get("leisure");
093            if (test != null && !"track".contains(test)) {
094                set(1107, marktr("leisure type {0}"), test);
095            }
096            test = w.get("waterway");
097            if (test != null && test.equals("riverbank")) {
098                set(1108, marktr("waterway type {0}"), test);
099            }
100            Boolean btest = OsmUtils.getOsmBoolean(w.get("building"));
101            if (btest != null && btest) {
102                set(1120, marktr("building"));
103            }
104            btest = OsmUtils.getOsmBoolean(w.get("area"));
105            if (btest != null && btest) {
106                set(1130, marktr("area"));
107            }
108    
109            if (type != null && !w.isClosed()) {
110                for (OsmPrimitive parent: w.getReferrers()) {
111                    if (parent instanceof Relation && ((Relation)parent).isMultipolygon())
112                        return;
113                }
114    
115                errors.add(new TestError(this, Severity.WARNING, tr("Unclosed way"),
116                        type, etype, mode,
117                        Arrays.asList(w),
118                        // The important parts of an unclosed way are the first and
119                        // the last node which should be connected, therefore we highlight them
120                        Arrays.asList(w.firstNode(), w.lastNode())));
121            }
122        }
123    }