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.File;
007import java.io.IOException;
008import java.util.ArrayList;
009import java.util.Date;
010import java.util.List;
011
012import org.openstreetmap.josm.data.coor.LatLon;
013import org.openstreetmap.josm.gui.layer.GpxLayer;
014import org.openstreetmap.josm.gui.layer.Layer;
015import org.openstreetmap.josm.gui.layer.geoimage.GeoImageLayer;
016import org.openstreetmap.josm.gui.layer.geoimage.ImageEntry;
017import org.openstreetmap.josm.gui.progress.ProgressMonitor;
018import org.openstreetmap.josm.io.IllegalDataException;
019import org.openstreetmap.josm.tools.Logging;
020import org.w3c.dom.Element;
021import org.w3c.dom.Node;
022import org.w3c.dom.NodeList;
023
024/**
025 * Session importer for {@link GeoImageLayer}.
026 * @since 5505
027 */
028public class GeoImageSessionImporter implements SessionLayerImporter {
029
030    @Override
031    public Layer load(Element elem, SessionReader.ImportSupport support, ProgressMonitor progressMonitor)
032            throws IOException, IllegalDataException {
033        String version = elem.getAttribute("version");
034        if (!"0.1".equals(version)) {
035            throw new IllegalDataException(tr("Version ''{0}'' of meta data for geoimage layer is not supported. Expected: 0.1", version));
036        }
037
038        List<ImageEntry> entries = new ArrayList<>();
039        NodeList imgNodes = elem.getChildNodes();
040        boolean useThumbs = false;
041        for (int i = 0; i < imgNodes.getLength(); ++i) {
042            Node imgNode = imgNodes.item(i);
043            if (imgNode.getNodeType() == Node.ELEMENT_NODE) {
044                Element imgElem = (Element) imgNode;
045                if ("geoimage".equals(imgElem.getTagName())) {
046                    ImageEntry entry = new ImageEntry();
047                    NodeList attrNodes = imgElem.getChildNodes();
048                    for (int j = 0; j < attrNodes.getLength(); ++j) {
049                        Node attrNode = attrNodes.item(j);
050                        if (attrNode.getNodeType() == Node.ELEMENT_NODE) {
051                            handleElement(entry, (Element) attrNode);
052                        }
053                    }
054                    entries.add(entry);
055                } else if ("show-thumbnails".equals(imgElem.getTagName())) {
056                    useThumbs = Boolean.parseBoolean(imgElem.getTextContent());
057                }
058            }
059        }
060
061        GpxLayer gpxLayer = null;
062        List<SessionReader.LayerDependency> deps = support.getLayerDependencies();
063        if (!deps.isEmpty()) {
064            Layer layer = deps.get(0).getLayer();
065            if (layer instanceof GpxLayer) {
066                gpxLayer = (GpxLayer) layer;
067            }
068        }
069
070        return new GeoImageLayer(entries, gpxLayer, useThumbs);
071    }
072
073    private static void handleElement(ImageEntry entry, Element attrElem) {
074        try {
075            switch(attrElem.getTagName()) {
076            case "file":
077                entry.setFile(new File(attrElem.getTextContent()));
078                break;
079            case "position":
080                double lat = Double.parseDouble(attrElem.getAttribute("lat"));
081                double lon = Double.parseDouble(attrElem.getAttribute("lon"));
082                entry.setPos(new LatLon(lat, lon));
083                break;
084            case "speed":
085                entry.setSpeed(Double.valueOf(attrElem.getTextContent()));
086                break;
087            case "elevation":
088                entry.setElevation(Double.valueOf(attrElem.getTextContent()));
089                break;
090            case "gps-time":
091                entry.setGpsTime(new Date(Long.parseLong(attrElem.getTextContent())));
092                break;
093            case "exif-orientation":
094                entry.setExifOrientation(Integer.valueOf(attrElem.getTextContent()));
095                break;
096            case "exif-time":
097                entry.setExifTime(new Date(Long.parseLong(attrElem.getTextContent())));
098                break;
099            case "exif-gps-time":
100                entry.setExifGpsTime(new Date(Long.parseLong(attrElem.getTextContent())));
101                break;
102            case "exif-coordinates":
103                entry.setExifCoor(new LatLon(
104                        Double.parseDouble(attrElem.getAttribute("lat")),
105                        Double.parseDouble(attrElem.getAttribute("lon"))));
106                break;
107            case "exif-image-direction":
108                entry.setExifImgDir(Double.valueOf(attrElem.getTextContent()));
109                break;
110            case "is-new-gps-data":
111                if (Boolean.parseBoolean(attrElem.getTextContent())) {
112                    entry.flagNewGpsData();
113                }
114                break;
115            default: // Do nothing
116            }
117            // TODO: handle thumbnail loading
118        } catch (NumberFormatException e) {
119            Logging.trace(e);
120        }
121    }
122}