001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.io.session;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.io.IOException;
007import java.io.InputStream;
008
009import javax.xml.xpath.XPath;
010import javax.xml.xpath.XPathConstants;
011import javax.xml.xpath.XPathExpression;
012import javax.xml.xpath.XPathExpressionException;
013import javax.xml.xpath.XPathFactory;
014
015import org.openstreetmap.josm.gui.io.importexport.OsmImporter;
016import org.openstreetmap.josm.gui.layer.Layer;
017import org.openstreetmap.josm.gui.layer.OsmDataLayer;
018import org.openstreetmap.josm.gui.progress.ProgressMonitor;
019import org.openstreetmap.josm.io.IllegalDataException;
020import org.openstreetmap.josm.io.session.SessionReader.ImportSupport;
021import org.openstreetmap.josm.tools.Utils;
022import org.w3c.dom.Element;
023
024/**
025 * Session importer for {@link OsmDataLayer}.
026 * @since 4685
027 */
028public class OsmDataSessionImporter implements SessionLayerImporter {
029
030    @Override
031    public Layer load(Element elem, ImportSupport support, ProgressMonitor progressMonitor) throws IOException, IllegalDataException {
032        checkMetaVersion(elem);
033        String fileStr = extractFileName(elem, support);
034        return importData(new OsmImporter(), support, fileStr, progressMonitor);
035    }
036
037    /**
038     * Checks that element defines the expected version number.
039     * @param elem element to check
040     * @throws IllegalDataException if version is not the expected one
041     * @since 15377
042     */
043    public static void checkMetaVersion(Element elem) throws IllegalDataException {
044        String version = elem.getAttribute("version");
045        if (!"0.1".equals(version)) {
046            throw new IllegalDataException(tr("Version ''{0}'' of meta data for osm data layer is not supported. Expected: 0.1", version));
047        }
048    }
049
050    /**
051     * Extract file name from element.
052     * @param elem element to parse
053     * @param support import/export support
054     * @return file name, if present
055     * @throws IllegalDataException if file name missing or empty
056     * @since 15377
057     */
058    public static String extractFileName(Element elem, ImportSupport support) throws IllegalDataException {
059        try {
060            XPathFactory xPathFactory = XPathFactory.newInstance();
061            XPath xpath = xPathFactory.newXPath();
062            XPathExpression fileExp = xpath.compile("file/text()");
063            String fileStr = (String) fileExp.evaluate(elem, XPathConstants.STRING);
064            if (Utils.isEmpty(fileStr)) {
065                throw new IllegalDataException(tr("File name expected for layer no. {0}", support.getLayerIndex()));
066            }
067            return fileStr;
068        } catch (XPathExpressionException e) {
069            throw new IllegalDataException(e);
070        }
071    }
072
073    /**
074     * Import data as a new layer.
075     * @param osmImporter OSM importer
076     * @param support import/export support
077     * @param fileStr file name to import
078     * @param progressMonitor progress monitor
079     * @return new layer
080     * @throws IOException in case of I/O error
081     * @throws IllegalDataException in case of illegal data
082     * @since 15377
083     */
084    public static Layer importData(OsmImporter osmImporter, ImportSupport support, String fileStr, ProgressMonitor progressMonitor)
085            throws IOException, IllegalDataException {
086        try (InputStream in = support.getInputStream(fileStr)) {
087            OsmImporter.OsmImporterData importData = osmImporter.loadLayer(
088                    in, support.getFile(fileStr), support.getLayerName(), progressMonitor);
089
090            support.addPostLayersTask(importData.getPostLayerTask());
091            return importData.getLayer();
092        }
093    }
094}