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.w3c.dom.Element;
022
023/**
024 * Session importer for {@link OsmDataLayer}.
025 * @since 4685
026 */
027public class OsmDataSessionImporter implements SessionLayerImporter {
028
029    @Override
030    public Layer load(Element elem, ImportSupport support, ProgressMonitor progressMonitor) throws IOException, IllegalDataException {
031        checkMetaVersion(elem);
032        String fileStr = extractFileName(elem, support);
033        return importData(new OsmImporter(), support, fileStr, progressMonitor);
034    }
035
036    /**
037     * Checks that element defines the expected version number.
038     * @param elem element to check
039     * @throws IllegalDataException if version is not the expected one
040     * @since 15377
041     */
042    public static void checkMetaVersion(Element elem) throws IllegalDataException {
043        String version = elem.getAttribute("version");
044        if (!"0.1".equals(version)) {
045            throw new IllegalDataException(tr("Version ''{0}'' of meta data for osm data layer is not supported. Expected: 0.1", version));
046        }
047    }
048
049    /**
050     * Extract file name from element.
051     * @param elem element to parse
052     * @param support import/export support
053     * @return file name, if present
054     * @throws IllegalDataException if file name missing or empty
055     * @since 15377
056     */
057    public static String extractFileName(Element elem, ImportSupport support) throws IllegalDataException {
058        try {
059            XPathFactory xPathFactory = XPathFactory.newInstance();
060            XPath xpath = xPathFactory.newXPath();
061            XPathExpression fileExp = xpath.compile("file/text()");
062            String fileStr = (String) fileExp.evaluate(elem, XPathConstants.STRING);
063            if (fileStr == null || fileStr.isEmpty()) {
064                throw new IllegalDataException(tr("File name expected for layer no. {0}", support.getLayerIndex()));
065            }
066            return fileStr;
067        } catch (XPathExpressionException e) {
068            throw new IllegalDataException(e);
069        }
070    }
071
072    /**
073     * Import data as a new layer.
074     * @param osmImporter OSM importer
075     * @param support import/export support
076     * @param fileStr file name to import
077     * @param progressMonitor progress monitor
078     * @return new layer
079     * @throws IOException in case of I/O error
080     * @throws IllegalDataException in case of illegal data
081     * @since 15377
082     */
083    public static Layer importData(OsmImporter osmImporter, ImportSupport support, String fileStr, ProgressMonitor progressMonitor)
084            throws IOException, IllegalDataException {
085        try (InputStream in = support.getInputStream(fileStr)) {
086            OsmImporter.OsmImporterData importData = osmImporter.loadLayer(
087                    in, support.getFile(fileStr), support.getLayerName(), progressMonitor);
088
089            support.addPostLayersTask(importData.getPostLayerTask());
090            return importData.getLayer();
091        }
092    }
093}