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