source: josm/trunk/src/org/openstreetmap/josm/io/session/SessionWriter.java@ 5391

Last change on this file since 5391 was 5391, checked in by bastiK, 12 years ago

add session support for imagery layers

  • Property svn:eol-style set to native
File size: 7.5 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.io.session;
3
4import java.io.BufferedOutputStream;
5import java.io.File;
6import java.io.FileNotFoundException;
7import java.io.FileOutputStream;
8import java.io.IOException;
9import java.io.OutputStream;
10import java.io.OutputStreamWriter;
11import java.lang.reflect.Constructor;
12import java.util.ArrayList;
13import java.util.HashMap;
14import java.util.List;
15import java.util.Map;
16import java.util.Set;
17import java.util.zip.ZipEntry;
18import java.util.zip.ZipOutputStream;
19
20import javax.xml.parsers.DocumentBuilder;
21import javax.xml.parsers.DocumentBuilderFactory;
22import javax.xml.parsers.ParserConfigurationException;
23import javax.xml.transform.OutputKeys;
24import javax.xml.transform.Transformer;
25import javax.xml.transform.TransformerException;
26import javax.xml.transform.TransformerFactory;
27import javax.xml.transform.dom.DOMSource;
28import javax.xml.transform.stream.StreamResult;
29
30import org.w3c.dom.Document;
31import org.w3c.dom.Element;
32import org.w3c.dom.Text;
33
34import org.openstreetmap.josm.gui.layer.Layer;
35import org.openstreetmap.josm.gui.layer.OsmDataLayer;
36import org.openstreetmap.josm.gui.layer.TMSLayer;
37import org.openstreetmap.josm.gui.layer.WMSLayer;
38import org.openstreetmap.josm.tools.MultiMap;
39import org.openstreetmap.josm.tools.Utils;
40
41public class SessionWriter {
42
43 private static Map<Class<? extends Layer>, Class<? extends SessionLayerExporter>> sessionLayerExporters =
44 new HashMap<Class<? extends Layer>, Class<? extends SessionLayerExporter>>();
45 static {
46 registerSessionLayerExporter(OsmDataLayer.class , OsmDataSessionExporter.class);
47 registerSessionLayerExporter(TMSLayer.class , ImagerySessionExporter.class);
48 registerSessionLayerExporter(WMSLayer.class , ImagerySessionExporter.class);
49 }
50
51 /**
52 * Register a session layer exporter.
53 *
54 * The exporter class must have an one-argument constructor with layerClass as formal parameter type.
55 */
56 public static void registerSessionLayerExporter(Class<? extends Layer> layerClass, Class<? extends SessionLayerExporter> exporter) {
57 sessionLayerExporters.put(layerClass, exporter);
58 }
59
60 public static SessionLayerExporter getSessionLayerExporter(Layer layer) {
61 Class<? extends Layer> layerClass = layer.getClass();
62 Class<? extends SessionLayerExporter> exporterClass = sessionLayerExporters.get(layerClass);
63 if (exporterClass == null) return null;
64 try {
65 @SuppressWarnings("unchecked")
66 Constructor<? extends SessionLayerExporter> constructor = (Constructor) exporterClass.getConstructor(layerClass);
67 return constructor.newInstance(layer);
68 } catch (Exception e) {
69 throw new RuntimeException(e);
70 }
71 }
72
73 private List<Layer> layers;
74 private Map<Layer, SessionLayerExporter> exporters;
75 private MultiMap<Layer, Layer> dependencies;
76 private boolean zip;
77
78 private ZipOutputStream zipOut;
79
80 public SessionWriter(List<Layer> layers, Map<Layer, SessionLayerExporter> exporters,
81 MultiMap<Layer, Layer> dependencies, boolean zip) {
82 this.layers = layers;
83 this.exporters = exporters;
84 this.dependencies = dependencies;
85 this.zip = zip;
86 }
87
88 public class ExportSupport {
89 private Document doc;
90 private int layerIndex;
91
92 public ExportSupport(Document doc, int layerIndex) {
93 this.doc = doc;
94 this.layerIndex = layerIndex;
95 }
96
97 public Element createElement(String name) {
98 return doc.createElement(name);
99 }
100
101 public Text createTextNode(String text) {
102 return doc.createTextNode(text);
103 }
104
105 public int getLayerIndex() {
106 return layerIndex;
107 }
108
109 /**
110 * Create a file in the zip archive.
111 *
112 * @return never close the output stream, but make sure to flush buffers
113 */
114 public OutputStream getOutputStreamZip(String zipPath) throws IOException {
115 if (!isZip()) throw new RuntimeException();
116 ZipEntry entry = new ZipEntry(zipPath);
117 zipOut.putNextEntry(entry);
118 return zipOut;
119 }
120
121 public boolean isZip() {
122 return zip;
123 }
124 }
125
126 public Document createJosDocument() throws IOException {
127 DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
128 builderFactory.setValidating(false);
129 builderFactory.setNamespaceAware(true);
130 DocumentBuilder builder = null;
131 try {
132 builder = builderFactory.newDocumentBuilder();
133 } catch (ParserConfigurationException e) {
134 throw new RuntimeException(e);
135 }
136 Document doc = builder.newDocument();
137
138 Element root = doc.createElement("josm-session");
139 root.setAttribute("version", "0.1");
140 doc.appendChild(root);
141
142 Element layersEl = doc.createElement("layers");
143 root.appendChild(layersEl);
144
145 for (int index=0; index<layers.size(); ++index) {
146 Layer layer = layers.get(index);
147 SessionLayerExporter exporter = exporters.get(layer);
148 ExportSupport support = new ExportSupport(doc, index+1);
149 Element el = exporter.export(support);
150 el.setAttribute("index", Integer.toString(index+1));
151 el.setAttribute("name", layer.getName());
152 Set<Layer> deps = dependencies.get(layer);
153 if (deps.size() > 0) {
154 List<Integer> depsInt = new ArrayList<Integer>();
155 for (Layer depLayer : deps) {
156 int depIndex = layers.indexOf(depLayer);
157 if (depIndex == -1) throw new AssertionError();
158 depsInt.add(depIndex+1);
159 }
160 el.setAttribute("depends", Utils.join(",", depsInt));
161 }
162 layersEl.appendChild(el);
163 }
164 return doc;
165 }
166
167 public void writeJos(Document doc, OutputStream out) throws IOException {
168 try {
169 OutputStreamWriter writer = new OutputStreamWriter(out, "utf-8");
170 writer.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
171 TransformerFactory transfac = TransformerFactory.newInstance();
172 Transformer trans = transfac.newTransformer();
173 trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
174 trans.setOutputProperty(OutputKeys.INDENT, "yes");
175 trans.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
176 StreamResult result = new StreamResult(writer);
177 DOMSource source = new DOMSource(doc);
178 trans.transform(source, result);
179 } catch (TransformerException e) {
180 throw new RuntimeException(e);
181 }
182 }
183
184 public void write(File f) throws IOException {
185 OutputStream out = null;
186 try {
187 out = new FileOutputStream(f);
188 } catch (FileNotFoundException e) {
189 throw new IOException(e);
190 }
191 write(out);
192 }
193
194 public void write (OutputStream out) throws IOException {
195 if (zip) {
196 zipOut = new ZipOutputStream(new BufferedOutputStream(out));
197 }
198 Document doc = createJosDocument(); // as side effect, files may be added to zipOut
199 if (zip) {
200 ZipEntry entry = new ZipEntry("session.jos");
201 zipOut.putNextEntry(entry);
202 writeJos(doc, zipOut);
203 zipOut.close();
204 } else {
205 writeJos(doc, new BufferedOutputStream(out));
206 }
207 Utils.close(out);
208 }
209}
Note: See TracBrowser for help on using the repository browser.