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.util.HashMap; 008import java.util.Map; 009 010import org.openstreetmap.josm.data.StructUtils; 011import org.openstreetmap.josm.data.imagery.ImageryInfo; 012import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryPreferenceEntry; 013import org.openstreetmap.josm.data.imagery.OffsetBookmark; 014import org.openstreetmap.josm.gui.layer.AbstractTileSourceLayer; 015import org.openstreetmap.josm.gui.layer.ImageryLayer; 016import org.openstreetmap.josm.gui.layer.Layer; 017import org.openstreetmap.josm.gui.layer.TMSLayer; 018import org.openstreetmap.josm.gui.layer.WMSLayer; 019import org.openstreetmap.josm.gui.layer.WMTSLayer; 020import org.openstreetmap.josm.gui.layer.imagery.ImageryFilterSettings; 021import org.openstreetmap.josm.gui.progress.ProgressMonitor; 022import org.openstreetmap.josm.io.IllegalDataException; 023import org.openstreetmap.josm.io.session.SessionReader.ImportSupport; 024import org.openstreetmap.josm.tools.Logging; 025import org.openstreetmap.josm.tools.Utils; 026import org.w3c.dom.Element; 027import org.w3c.dom.Node; 028import org.w3c.dom.NodeList; 029 030/** 031 * Session importer for {@link TMSLayer}, {@link WMSLayer} and {@link WMTSLayer}. 032 * @since 5391 033 */ 034public class ImagerySessionImporter implements SessionLayerImporter { 035 036 @Override 037 public Layer load(Element elem, ImportSupport support, ProgressMonitor progressMonitor) throws IOException, IllegalDataException { 038 String version = elem.getAttribute("version"); 039 if (!"0.1".equals(version)) { 040 throw new IllegalDataException(tr("Version ''{0}'' of meta data for imagery layer is not supported. Expected: 0.1", version)); 041 } 042 Map<String, String> attributes = readProperties(elem); 043 044 ImageryPreferenceEntry prefEntry = StructUtils.deserializeStruct(attributes, ImageryPreferenceEntry.class); 045 ImageryInfo info = new ImageryInfo(prefEntry); 046 ImageryLayer layer = ImageryLayer.create(info); 047 Utils.instanceOfThen(layer, AbstractTileSourceLayer.class, tsLayer -> { 048 tsLayer.getDisplaySettings().applyFromPropertiesMap(attributes); 049 if (!tsLayer.getDisplaySettings().isAutoZoom()) { 050 String zoomStr = attributes.get("zoom-level"); 051 if (zoomStr != null) { 052 support.addPostLayersTask(() -> { 053 try { 054 tsLayer.setZoomLevel(Integer.parseInt(zoomStr)); 055 } catch (NumberFormatException e) { 056 Logging.warn(e); 057 } 058 }); 059 } 060 } 061 Element offsetEl = getFirstElementByTagName(elem, "offset"); 062 if (offsetEl != null) { 063 Map<String, String> offsetAttributes = readProperties(offsetEl); 064 OffsetBookmark offset = OffsetBookmark.fromPropertiesMap(offsetAttributes); 065 tsLayer.getDisplaySettings().setOffsetBookmark(offset); 066 } 067 }); 068 Element filtersEl = getFirstElementByTagName(elem, "filters"); 069 if (filtersEl != null) { 070 ImageryFilterSettings filterSettings = layer.getFilterSettings(); 071 if (filterSettings != null) { 072 Map<String, String> filtersProps = readProperties(filtersEl); 073 filterSettings.getProcessors().stream() 074 .flatMap(Utils.castToStream(SessionAwareReadApply.class)) 075 .forEach(proc -> proc.applyFromPropertiesMap(filtersProps)); 076 } 077 } 078 return layer; 079 } 080 081 private static Element getFirstElementByTagName(Element el, String name) { 082 NodeList nl = el.getElementsByTagName(name); 083 if (nl.getLength() == 0) 084 return null; 085 return (Element) nl.item(0); 086 } 087 088 private static Map<String, String> readProperties(Element elem) { 089 Map<String, String> attributes = new HashMap<>(); 090 NodeList nodes = elem.getChildNodes(); 091 for (int i = 0; i < nodes.getLength(); ++i) { 092 Node node = nodes.item(i); 093 if (node.getNodeType() == Node.ELEMENT_NODE && node.getChildNodes().getLength() <= 1) { 094 Element e = (Element) node; 095 attributes.put(e.getTagName(), e.getTextContent()); 096 } 097 } 098 return attributes; 099 } 100}