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