Ticket #18249: 18249.3.patch

File 18249.3.patch, 9.7 KB (added by taylor.smock, 5 years ago)

Remove switch statement in favor of directly calling each required attribute, to ensure that errors are thrown.

  • src/org/openstreetmap/josm/io/OsmReader.java

     
    66import java.io.InputStream;
    77import java.util.Collection;
    88import java.util.Objects;
     9import java.util.Set;
     10import java.util.TreeSet;
    911import java.util.regex.Matcher;
    1012import java.util.regex.Pattern;
    1113
     
    3941
    4042    protected XMLStreamReader parser;
    4143
     44    protected boolean convertUnknownToTags;
     45
     46    private static final Set<String> COMMON_XML_ATTRIBUTES = new TreeSet<>();
     47
     48    static {
     49        COMMON_XML_ATTRIBUTES.add("id");
     50        COMMON_XML_ATTRIBUTES.add("timestamp");
     51        COMMON_XML_ATTRIBUTES.add("user");
     52        COMMON_XML_ATTRIBUTES.add("uid");
     53        COMMON_XML_ATTRIBUTES.add("visible");
     54        COMMON_XML_ATTRIBUTES.add("version");
     55        COMMON_XML_ATTRIBUTES.add("action");
     56        COMMON_XML_ATTRIBUTES.add("changeset");
     57        COMMON_XML_ATTRIBUTES.add("lat");
     58        COMMON_XML_ATTRIBUTES.add("lon");
     59    }
     60
    4261    /**
    4362     * constructor (for private and subclasses use only)
    4463     *
     
    4564     * @see #parseDataSet(InputStream, ProgressMonitor)
    4665     */
    4766    protected OsmReader() {
     67        this(false);
     68    }
     69
     70    /**
     71     * constructor (for private and subclasses use only)
     72     * @param convertUnknownToTags if true, keep unknown xml attributes as tags
     73     *
     74     * @see #parseDataSet(InputStream, ProgressMonitor)
     75     * @since xxx
     76     */
     77    protected OsmReader(boolean convertUnknownToTags) {
    4878        // Restricts visibility
     79        this.convertUnknownToTags = convertUnknownToTags;
    4980    }
    5081
    5182    protected void setParser(XMLStreamReader parser) {
     
    393424            parseVersion(current, parser.getAttributeValue(null, "version"));
    394425            parseAction(current, parser.getAttributeValue(null, "action"));
    395426            parseChangeset(current, parser.getAttributeValue(null, "changeset"));
     427
     428            if (convertUnknownToTags) {
     429                for (int i = 0; i < parser.getAttributeCount(); i++) {
     430                    if (!COMMON_XML_ATTRIBUTES.contains(parser.getAttributeLocalName(i))) {
     431                        parseTag(current, parser.getAttributeLocalName(i), parser.getAttributeValue(i));
     432                    }
     433                }
     434            }
    396435        } catch (UncheckedParseException | XMLStreamException e) {
    397436            throw new IllegalDataException(e);
    398437        }
     
    457496     * @throws IllegalArgumentException if source is null
    458497     */
    459498    public static DataSet parseDataSet(InputStream source, ProgressMonitor progressMonitor) throws IllegalDataException {
    460         return new OsmReader().doParseDataSet(source, progressMonitor);
     499        return parseDataSet(source, progressMonitor, false);
    461500    }
     501
     502    /**
     503     * Parse the given input source and return the dataset.
     504     *
     505     * @param source the source input stream. Must not be null.
     506     * @param progressMonitor the progress monitor. If null, {@link NullProgressMonitor#INSTANCE} is assumed
     507     * @param convertUnknownToTags true if unknown xml attributes should be kept as tags
     508     *
     509     * @return the dataset with the parsed data
     510     * @throws IllegalDataException if an error was found while parsing the data from the source
     511     * @throws IllegalArgumentException if source is null
     512     * @since xxx
     513     */
     514    public static DataSet parseDataSet(InputStream source, ProgressMonitor progressMonitor, boolean convertUnknownToTags)
     515            throws IllegalDataException {
     516        return new OsmReader(convertUnknownToTags).doParseDataSet(source, progressMonitor);
     517    }
    462518}
  • test/unit/org/openstreetmap/josm/io/OsmReaderTest.java

     
    1212import java.nio.charset.StandardCharsets;
    1313import java.nio.file.Files;
    1414import java.nio.file.Paths;
     15import java.util.Arrays;
    1516
    1617import org.junit.Rule;
    1718import org.junit.Test;
    1819import org.openstreetmap.josm.TestUtils;
    1920import org.openstreetmap.josm.data.osm.DataSet;
     21import org.openstreetmap.josm.data.osm.Node;
    2022import org.openstreetmap.josm.data.osm.Way;
    2123import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
    2224import org.openstreetmap.josm.gui.progress.ProgressMonitor;
     
    7375                ("<?xml version='1.0' encoding='UTF-8'?>" + osm).getBytes(StandardCharsets.UTF_8))) {
    7476            assertTrue(OsmReader.parseDataSet(in, NullProgressMonitor.INSTANCE).allPrimitives().isEmpty());
    7577        }
     78        testUnknown(osm, true);
     79        testUnknown(osm, false);
    7680    }
    7781
     82    private static void testUnknown(String osm, boolean parseUnknownAttributes) throws Exception {
     83        try (InputStream in = new ByteArrayInputStream(
     84                ("<?xml version='1.0' encoding='UTF-8'?>" + osm).getBytes(StandardCharsets.UTF_8))) {
     85            assertTrue(OsmReader.parseDataSet(in, NullProgressMonitor.INSTANCE, parseUnknownAttributes).allPrimitives()
     86                    .isEmpty());
     87        }
     88    }
     89
    7890    /**
    7991     * Unit test of {@link OsmReader#parseUnknown} - root case.
    8092     * @throws Exception if any error occurs
     
    126138    }
    127139
    128140    /**
     141     * Test valid data.
     142     * @param osm OSM data without XML prefix
     143     * @param parseUnknownAttributes if true, attempt to parse unknown xml attributes
     144     * @return parsed data set
     145     * @throws Exception if any error occurs
     146     */
     147    private static DataSet testValidData(String osm, boolean parseUnknownAttributes) throws Exception {
     148        try (InputStream in = new ByteArrayInputStream(
     149                ("<?xml version='1.0' encoding='UTF-8'?>" + osm).getBytes(StandardCharsets.UTF_8))) {
     150            return OsmReader.parseDataSet(in, NullProgressMonitor.INSTANCE, parseUnknownAttributes);
     151        }
     152    }
     153
     154    /**
    129155     * Test invalid data.
    130156     * @param osm OSM data without XML prefix
    131157     * @param expectedError expected error message
     
    139165        } catch (IllegalDataException e) {
    140166            assertEquals(expectedError, e.getMessage());
    141167        }
     168        testInvalidData(osm, expectedError, true);
     169        testInvalidData(osm, expectedError, false);
    142170    }
    143171
    144172    /**
     173     * Test invalid data.
     174     *
     175     * @param osm                    OSM data without XML prefix
     176     * @param expectedError          expected error message
     177     * @param parseUnknownAttributes if true, attempt to parse unknown xml
     178     *                               attributes
     179     * @throws Exception if any error occurs
     180     */
     181    private static void testInvalidData(String osm, String expectedError, boolean parseUnknownAttributes)
     182            throws Exception {
     183        try (InputStream in = new ByteArrayInputStream(
     184                ("<?xml version='1.0' encoding='UTF-8'?>" + osm).getBytes(StandardCharsets.UTF_8))) {
     185            OsmReader.parseDataSet(in, NullProgressMonitor.INSTANCE, parseUnknownAttributes);
     186            fail("should throw exception");
     187        } catch (IllegalDataException e) {
     188            assertEquals(expectedError, e.getMessage());
     189        }
     190    }
     191
     192    /**
    145193     * Test invalid UID.
    146194     * @throws Exception if any error occurs
    147195     */
     
    274322     */
    275323    @Test
    276324    public void testGdprChangeset() throws Exception {
    277         testValidData("<osm version='0.6'><node id='1' version='1' changeset='0'/></osm>");
     325        String gdprChangeset = "<osm version='0.6'><node id='1' version='1' changeset='0'/></osm>";
     326        testValidData(gdprChangeset);
     327        testValidData(gdprChangeset, true);
     328        testValidData(gdprChangeset, false);
    278329    }
    279330
    280331    /**
     
    349400     */
    350401    @Test
    351402    public void testRemark() throws Exception {
    352         DataSet ds = testValidData(
    353                 "<osm version=\"0.6\" generator=\"Overpass API 0.7.55.4 3079d8ea\">\r\n" +
     403        String query = "<osm version=\"0.6\" generator=\"Overpass API 0.7.55.4 3079d8ea\">\r\n" +
    354404                "<note>The data included in this document is from www.openstreetmap.org. The data is made available under ODbL.</note>\r\n" +
    355405                "<meta osm_base=\"2018-08-30T12:46:02Z\" areas=\"2018-08-30T12:40:02Z\"/>\r\n" +
    356406                "<remark>runtime error: Query ran out of memory in \"query\" at line 5.</remark>\r\n" +
    357                 "</osm>");
    358         assertEquals("runtime error: Query ran out of memory in \"query\" at line 5.", ds.getRemark());
     407                "</osm>";
     408        for (DataSet ds : Arrays.asList(testValidData(query), testValidData(query, true), testValidData(query, false))) {
     409            assertEquals("runtime error: Query ran out of memory in \"query\" at line 5.", ds.getRemark());
     410        }
    359411    }
     412
     413    /**
     414     * Test reading a file with unknown attributes in osm primitives
     415     * @throws Exception if any error occurs
     416     */
     417    @Test
     418    public void testUnknownAttributeTags() throws Exception {
     419        String testData = "<osm version=\"0.6\" generator=\"fake generator\">"
     420                + "<node id='1' version='1' visible='true' changeset='82' randomkey='randomvalue'></node>" + "</osm>";
     421        DataSet ds = testValidData(testData);
     422        assertEquals(0, ds.getNodes().iterator().next().getKeys().size());
     423
     424        ds = testValidData(testData, true);
     425        Node firstNode = ds.getNodes().iterator().next();
     426        assertEquals(1, firstNode.getKeys().size());
     427        assertEquals("randomvalue", firstNode.get("randomkey"));
     428
     429        ds = testValidData(testData, false);
     430        assertEquals(0, ds.getNodes().iterator().next().getKeys().size());
     431    }
    360432}