001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.layer.markerlayer;
003
004import java.io.File;
005import java.net.MalformedURLException;
006import java.net.URL;
007import java.util.Arrays;
008import java.util.Collection;
009import java.util.Collections;
010import java.util.Optional;
011
012import org.openstreetmap.josm.data.gpx.Extensions;
013import org.openstreetmap.josm.data.gpx.GpxConstants;
014import org.openstreetmap.josm.data.gpx.GpxLink;
015import org.openstreetmap.josm.data.gpx.WayPoint;
016import org.openstreetmap.josm.tools.Logging;
017import org.openstreetmap.josm.tools.Utils;
018
019/**
020 * Marker specifying the default behaviour.
021 * @since 11892 (extracted from Marker)
022 */
023public final class DefaultMarkerProducers implements MarkerProducers {
024
025    @Override
026    public Collection<Marker> createMarkers(WayPoint wpt, File relativePath, MarkerLayer parentLayer, double time,
027            double offset) {
028        String uri = null;
029        // cheapest way to check whether "link" object exists and is a non-empty collection of GpxLink objects...
030        Collection<GpxLink> links = wpt.<GpxLink>getCollection(GpxConstants.META_LINKS);
031        if (links != null) {
032            for (GpxLink oneLink : links) {
033                uri = oneLink.uri;
034                break;
035            }
036        }
037
038        URL url = uriToUrl(uri, relativePath);
039        String urlStr = url == null ? "" : url.toString();
040        String symbolName = Optional.ofNullable(wpt.getString("symbol"))
041                .orElseGet(() -> wpt.getString(GpxConstants.PT_SYM));
042        // text marker is returned in every case, see #10208
043        final Marker marker = new Marker(wpt.getCoor(), wpt, symbolName, parentLayer, time, offset);
044        if (url == null) {
045            return Collections.singleton(marker);
046        } else if (Utils.hasExtension(urlStr, "wav", "mp3", "aac", "aif", "aiff")) {
047            final AudioMarker audioMarker = new AudioMarker(wpt.getCoor(), wpt, url, parentLayer, time, offset);
048            Extensions exts = (Extensions) wpt.get(GpxConstants.META_EXTENSIONS);
049            if (exts != null && exts.containsKey("offset")) {
050                try {
051                    audioMarker.syncOffset = Double.parseDouble(exts.get("sync-offset"));
052                } catch (NumberFormatException nfe) {
053                    Logging.warn(nfe);
054                }
055            }
056            return Arrays.asList(marker, audioMarker);
057        } else if (Utils.hasExtension(urlStr, "png", "jpg", "jpeg", "gif")) {
058            return Arrays.asList(marker, new ImageMarker(wpt.getCoor(), url, parentLayer, time, offset));
059        } else {
060            return Arrays.asList(marker, new WebMarker(wpt.getCoor(), url, parentLayer, time, offset));
061        }
062    }
063
064    private static URL uriToUrl(String uri, File relativePath) {
065        URL url = null;
066        if (uri != null) {
067            try {
068                url = new URL(uri);
069            } catch (MalformedURLException e) {
070                // Try a relative file:// url, if the link is not in an URL-compatible form
071                if (relativePath != null) {
072                    url = Utils.fileToURL(new File(relativePath.getParentFile(), uri));
073                }
074            }
075        }
076        return url;
077    }
078}