source: josm/trunk/src/org/openstreetmap/josm/actions/SaveActionBase.java@ 1724

Last change on this file since 1724 was 1677, checked in by stoecker, 15 years ago

remove all these ugly tab stops introduced in the last half year

  • Property svn:eol-style set to native
File size: 10.1 KB
Line 
1//License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.actions;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.event.ActionEvent;
7import java.io.File;
8import java.io.FileInputStream;
9import java.io.FileNotFoundException;
10import java.io.FileOutputStream;
11import java.io.IOException;
12import java.io.OutputStream;
13import java.io.OutputStreamWriter;
14import java.io.PrintWriter;
15import java.io.Writer;
16import java.util.zip.GZIPOutputStream;
17
18import javax.swing.JOptionPane;
19
20import org.apache.tools.bzip2.CBZip2OutputStream;
21import org.openstreetmap.josm.Main;
22import org.openstreetmap.josm.data.osm.OsmPrimitive;
23import org.openstreetmap.josm.gui.ExtendedDialog;
24import org.openstreetmap.josm.gui.layer.GpxLayer;
25import org.openstreetmap.josm.gui.layer.Layer;
26import org.openstreetmap.josm.gui.layer.OsmDataLayer;
27import org.openstreetmap.josm.io.GpxImporter;
28import org.openstreetmap.josm.io.GpxWriter;
29import org.openstreetmap.josm.io.OsmBzip2Importer;
30import org.openstreetmap.josm.io.OsmGzipImporter;
31import org.openstreetmap.josm.io.OsmImporter;
32import org.openstreetmap.josm.io.OsmWriter;
33import org.openstreetmap.josm.tools.Shortcut;
34
35public abstract class SaveActionBase extends DiskAccessAction {
36
37 private Layer layer;
38
39 public SaveActionBase(String name, String iconName, String tooltip, Shortcut shortcut, Layer layer) {
40 super(name, iconName, tooltip, shortcut);
41 this.layer = layer;
42 }
43
44 public void actionPerformed(ActionEvent e) {
45 doSave();
46 }
47
48 public Boolean doSave() {
49 Layer layer = this.layer;
50 if (layer == null && Main.map != null && (Main.map.mapView.getActiveLayer() instanceof OsmDataLayer
51 || Main.map.mapView.getActiveLayer() instanceof GpxLayer))
52 layer = Main.map.mapView.getActiveLayer();
53 if (layer == null)
54 layer = Main.main.editLayer();
55
56 if (!checkSaveConditions(layer))
57 return false;
58
59
60 File file = getFile(layer);
61 if (file == null)
62 return false;
63
64 save(file, layer);
65
66 layer.name = file.getName();
67 layer.setAssociatedFile(file);
68 Main.parent.repaint();
69 return true;
70 }
71
72 protected abstract File getFile(Layer layer);
73
74 /**
75 * Checks whether it is ok to launch a save (whether we have data,
76 * there is no conflict etc.)
77 * @return <code>true</code>, if it is safe to save.
78 */
79 public boolean checkSaveConditions(Layer layer) {
80 if (layer == null) {
81 JOptionPane.showMessageDialog(Main.parent, tr("Internal Error: cannot check conditions for no layer. Please report this as a bug."));
82 return false;
83 }
84 if (Main.map == null) {
85 JOptionPane.showMessageDialog(Main.parent, tr("No document open so nothing to save."));
86 return false;
87 }
88
89 if (layer instanceof OsmDataLayer && isDataSetEmpty((OsmDataLayer)layer) && 1 != new ExtendedDialog(Main.parent, tr("Empty document"), tr("The document contains no data."), new String[] {tr("Save anyway"), tr("Cancel")}, new String[] {"save.png", "cancel.png"}).getValue()) {
90 return false;
91 }
92 if (layer instanceof GpxLayer && ((GpxLayer)layer).data == null) {
93 return false;
94 }
95 if (!Main.map.conflictDialog.conflicts.isEmpty()) {
96 int answer = new ExtendedDialog(Main.parent,
97 tr("Conflicts"),
98 tr("There are unresolved conflicts. Conflicts will not be saved and handled as if you rejected all. Continue?"),
99 new String[] {tr("Reject Conflicts and Save"), tr("Cancel")},
100 new String[] {"save.png", "cancel.png"}).getValue();
101
102 if (answer != 1) return false;
103 }
104 return true;
105 }
106
107 public static File openFileDialog(Layer layer) {
108 if (layer instanceof OsmDataLayer)
109 return createAndOpenSaveFileChooser(tr("Save OSM file"), ".osm");
110 else if (layer instanceof GpxLayer)
111 return createAndOpenSaveFileChooser(tr("Save GPX file"), ".gpx");
112 return createAndOpenSaveFileChooser(tr("Save Layer"), ".lay");
113 }
114
115 private static void copy(File src, File dst) throws IOException {
116 FileInputStream srcStream;
117 FileOutputStream dstStream;
118 try {
119 srcStream = new FileInputStream(src);
120 dstStream = new FileOutputStream(dst);
121 } catch (FileNotFoundException e) {
122 JOptionPane.showMessageDialog(Main.parent, tr("Could not back up file.")+"\n"+e.getMessage());
123 return;
124 }
125 byte buf[] = new byte[1<<16];
126 int len;
127 while ((len = srcStream.read(buf)) != -1) {
128 dstStream.write(buf, 0, len);
129 }
130 srcStream.close();
131 dstStream.close();
132 }
133
134 public static void save(File file, Layer layer) {
135 if (layer instanceof GpxLayer) {
136 save(file, (GpxLayer)layer);
137 ((GpxLayer)layer).data.storageFile = file;
138 } else if (layer instanceof OsmDataLayer) {
139 save(file, (OsmDataLayer)layer);
140 }
141 }
142
143 public static void save(File file, OsmDataLayer layer) {
144 File tmpFile = null;
145 try {
146 GpxImporter gpxImExporter = new GpxImporter();
147 OsmImporter osmImExporter = new OsmImporter();
148 OsmGzipImporter osmGzipImporter = new OsmGzipImporter();
149 OsmBzip2Importer osmBzip2Importer = new OsmBzip2Importer();
150 if (gpxImExporter.acceptFile(file))
151 GpxExportAction.exportGpx(file, layer);
152 else if (osmImExporter.acceptFile(file)
153 || osmGzipImporter.acceptFile(file)
154 || osmBzip2Importer.acceptFile(file))
155 {
156 // use a tmp file because if something errors out in the
157 // process of writing the file, we might just end up with
158 // a truncated file. That can destroy lots of work.
159 if (file.exists()) {
160 tmpFile = new File(file.getPath() + "~");
161 copy(file, tmpFile);
162 }
163
164 // create outputstream and wrap it with gzip or bzip, if necessary
165 OutputStream out = new FileOutputStream(file);
166 if(osmGzipImporter.acceptFile(file)) {
167 out = new GZIPOutputStream(out);
168 } else if(osmBzip2Importer.acceptFile(file)) {
169 out.write('B');
170 out.write('Z');
171 out = new CBZip2OutputStream(out);
172 }
173 Writer writer = new OutputStreamWriter(out, "UTF-8");
174
175 OsmWriter w = new OsmWriter(new PrintWriter(writer), false, layer.data.version);
176 w.header();
177 w.writeDataSources(layer.data);
178 w.writeContent(layer.data);
179 w.footer();
180 w.close();
181 // FIXME - how to close?
182 if (!Main.pref.getBoolean("save.keepbackup") && (tmpFile != null))
183 tmpFile.delete();
184 } else {
185 JOptionPane.showMessageDialog(Main.parent, tr("Unknown file extension."));
186 return;
187 }
188 layer.cleanData(null, false);
189 } catch (IOException e) {
190 e.printStackTrace();
191 JOptionPane.showMessageDialog(Main.parent, tr("An error occurred while saving.")+"\n"+e.getMessage());
192
193 try {
194 // if the file save failed, then the tempfile will not
195 // be deleted. So, restore the backup if we made one.
196 if (tmpFile != null && tmpFile.exists()) {
197 copy(tmpFile, file);
198 }
199 } catch (IOException e2) {
200 e2.printStackTrace();
201 JOptionPane.showMessageDialog(Main.parent, tr("An error occurred while restoring backup file.")+"\n"+e2.getMessage());
202 }
203 }
204 }
205
206 public static void save(File file, GpxLayer layer) {
207 File tmpFile = null;
208 try {
209 GpxImporter gpxImExporter = new GpxImporter();
210 if (gpxImExporter.acceptFile(file)) {
211
212 // use a tmp file because if something errors out in the
213 // process of writing the file, we might just end up with
214 // a truncated file. That can destroy lots of work.
215 if (file.exists()) {
216 tmpFile = new File(file.getPath() + "~");
217 copy(file, tmpFile);
218 }
219 FileOutputStream fo = new FileOutputStream(file);
220 new GpxWriter(fo).write(layer.data);
221 fo.flush();
222 fo.close();
223
224 if (!Main.pref.getBoolean("save.keepbackup") && (tmpFile != null)) {
225 tmpFile.delete();
226 }
227 } else {
228 JOptionPane.showMessageDialog(Main.parent, tr("Unknown file extension."));
229 return;
230 }
231 } catch (IOException e) {
232 e.printStackTrace();
233 JOptionPane.showMessageDialog(Main.parent, tr("An error occurred while saving.")+"\n"+e.getMessage());
234 }
235 try {
236 // if the file save failed, then the tempfile will not
237 // be deleted. So, restore the backup if we made one.
238 if (tmpFile != null && tmpFile.exists()) {
239 copy(tmpFile, file);
240 }
241 } catch (IOException e) {
242 e.printStackTrace();
243 JOptionPane.showMessageDialog(Main.parent, tr("An error occurred while restoring backup file.")+"\n"+e.getMessage());
244 }
245 }
246
247 /**
248 * Check the data set if it would be empty on save. It is empty, if it contains
249 * no objects (after all objects that are created and deleted without being
250 * transferred to the server have been removed).
251 *
252 * @return <code>true</code>, if a save result in an empty data set.
253 */
254 private boolean isDataSetEmpty(OsmDataLayer layer) {
255 for (OsmPrimitive osm : layer.data.allNonDeletedPrimitives())
256 if (!osm.deleted || osm.id > 0)
257 return false;
258 return true;
259 }
260}
Note: See TracBrowser for help on using the repository browser.