001: /*
002: * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI
003: * for visualizing and manipulating spatial features with geometry and attributes.
004: *
005: * JUMP is Copyright (C) 2003 Vivid Solutions
006: *
007: * This program implements extensions to JUMP and is
008: * Copyright (C) 2004 Integrated Systems Analysts, Inc.
009: *
010: * This program is free software; you can redistribute it and/or
011: * modify it under the terms of the GNU General Public License
012: * as published by the Free Software Foundation; either version 2
013: * of the License, or (at your option) any later version.
014: *
015: * This program is distributed in the hope that it will be useful,
016: * but WITHOUT ANY WARRANTY; without even the implied warranty of
017: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
018: * GNU General Public License for more details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with this program; if not, write to the Free Software
022: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
023: *
024: * For more information, contact:
025: *
026: * Integrated Systems Analysts, Inc.
027: * 630C Anchors St., Suite 101
028: * Fort Walton Beach, Florida
029: * USA
030: *
031: * (850)862-7321
032: * www.ashs.isa.com
033: */
034:
035: package org.openjump.core.ui.plugin.mousemenu;
036:
037: import java.io.File;
038: import java.io.FileNotFoundException;
039: import java.io.IOException;
040: import java.util.ArrayList;
041: import java.util.BitSet;
042: import java.util.Collection;
043: import java.util.HashMap;
044: import java.util.Iterator;
045: import java.util.List;
046:
047: import javax.swing.JFileChooser;
048: import javax.swing.JOptionPane;
049: import javax.swing.JPopupMenu;
050: import javax.swing.filechooser.FileFilter;
051:
052: import org.openjump.core.geomutils.GeoUtils;
053:
054: import com.vividsolutions.jts.geom.Geometry;
055: import com.vividsolutions.jts.geom.GeometryCollection;
056: import com.vividsolutions.jts.geom.MultiLineString;
057: import com.vividsolutions.jts.geom.MultiPoint;
058: import com.vividsolutions.jts.geom.MultiPolygon;
059: import com.vividsolutions.jump.I18N;
060: import com.vividsolutions.jump.feature.Feature;
061: import com.vividsolutions.jump.feature.FeatureCollectionWrapper;
062: import com.vividsolutions.jump.feature.FeatureDataset;
063: import com.vividsolutions.jump.feature.FeatureSchema;
064: import com.vividsolutions.jump.io.DriverProperties;
065: import com.vividsolutions.jump.io.FMEGMLWriter;
066: import com.vividsolutions.jump.io.GMLWriter;
067: import com.vividsolutions.jump.io.JMLWriter;
068: import com.vividsolutions.jump.io.ShapefileWriter;
069: import com.vividsolutions.jump.io.WKTWriter;
070: import com.vividsolutions.jump.io.datasource.DataSource;
071: import com.vividsolutions.jump.io.datasource.DataSourceQuery;
072: import com.vividsolutions.jump.io.datasource.StandardReaderWriterFileDataSource;
073: import com.vividsolutions.jump.util.FileUtil;
074: import com.vividsolutions.jump.workbench.WorkbenchContext;
075: import com.vividsolutions.jump.workbench.model.Layer;
076: import com.vividsolutions.jump.workbench.model.LayerManager;
077: import com.vividsolutions.jump.workbench.model.StandardCategoryNames;
078: import com.vividsolutions.jump.workbench.plugin.AbstractPlugIn;
079: import com.vividsolutions.jump.workbench.plugin.EnableCheckFactory;
080: import com.vividsolutions.jump.workbench.plugin.MultiEnableCheck;
081: import com.vividsolutions.jump.workbench.plugin.PlugInContext;
082: import com.vividsolutions.jump.workbench.ui.GUIUtil;
083: import com.vividsolutions.jump.workbench.ui.plugin.FeatureInstaller;
084: import com.vividsolutions.jump.workbench.ui.plugin.SaveProjectAsPlugIn;
085: import com.vividsolutions.jump.workbench.ui.plugin.SaveProjectPlugIn;
086:
087: public class SaveDatasetsPlugIn extends AbstractPlugIn {
088: private static final String sSaveSelectedDatasets = I18N
089: .get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Save-Selected-Datasets");
090: private static final String sUseSaveDatasetAsToSaveLayer = I18N
091: .get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Use***Save-Dataset-As***to-Save-Layer");
092: private static final String sSavedLayer = I18N
093: .get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Saved-Layer");
094: private static final String sErrorSeeOutputWindow = I18N
095: .get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Error-See-Output-Window");
096: private static final String sWarningSeeOutputWindow = I18N
097: .get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Warning-See-Output-Window");
098: private static final String sCouldNotSaveLayer = I18N
099: .get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Could-not-save-layer");
100: private static final String sCouldNotSave = I18N
101: .get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Could-not-save");
102: private static final String sLayer = I18N
103: .get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.layer");
104: private static final String sWithEmptyGeometry = I18N
105: .get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.with-empty-geometry");
106: private static final String sWithMixedGeometryTypes = I18N
107: .get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.with-mixed-geometry-types");
108: private static final String sCanNotSaveReadOnly = I18N
109: .get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Cannot-save-to-read-only-source-for-layer");
110: private static final String sDidNotSaveSameFile = I18N
111: .get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Did-not-save-these-layers-since-they-would-have-to-be-saved-to-the-same-file");
112: private static final String sSavedTask = I18N
113: .get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Saved-task");
114: private static final String sFileName = I18N
115: .get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.File-Name");
116: private static final String sLayerName = I18N
117: .get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Layer-Name");
118: private static final String sUnrecognizedFileType = I18N
119: .get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Unrecognized-file-type");
120: private static final String sNewLayerCreated = I18N
121: .get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.New-layer-created");
122: private static final String sCouldNotWrite = I18N
123: .get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Could-not-write");
124: private static final String sEmptyLayerNotSaved = I18N
125: .get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Empty-layer-not-saved");
126: private static final String sSaveFilesFromReadOnlySources = I18N
127: .get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Save-files-from-read-only-sources");
128: private static final String sFiles = I18N
129: .get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Files");
130: private static final String sWantToSaveReadonly = I18N
131: .get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Do-you-want-to-save-the-read-only-layers");
132: private static final String sNoteLayerNameWillBeFileName = I18N
133: .get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Note-layer-name-will-be-filename");
134: private static final String sReadOnlyLayer = I18N
135: .get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.read-only-layer");
136: private static final String sReplacesFile = I18N
137: .get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.replaces-file");
138: private static final String sReadOnlyWillReplace = I18N
139: .get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.read-only-source-will-replace-an-existing-file");
140: private static final String sNoteOutputWindow = I18N
141: .get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Note-Output-window-will-display-the-results-of-this-command");
142: private static final String sWouldHaveReplaced = I18N
143: .get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.The-read-only-layer-would-have-replaced-the-following-file(s)");
144: private static final String sHasReplaced = I18N
145: .get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.The-read-only-layer-has-replaced-the-following-file(s)");
146: private static final String sNoOutputDir = I18N
147: .get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.No-output-directory-designated-for-read-only-source-could-not-save-layer");
148: private static final String sNoOutputFileExt = I18N
149: .get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.No-output-file-extension-designated-for-read-only-source-could-not-save-layer");
150:
151: private boolean saveAll = false;
152: private int saveReadOnlySources = -1; //-1 - ask; 0 - don't save; 1 - save;
153: private String pathToSaveReadOnlySources = "";
154: private String extToSaveReadOnlySources = "";
155: private JFileChooser fileChooser;
156:
157: public void initialize(PlugInContext context) throws Exception {
158: WorkbenchContext workbenchContext = context
159: .getWorkbenchContext();
160: FeatureInstaller featureInstaller = new FeatureInstaller(
161: workbenchContext);
162:
163: JPopupMenu layerNamePopupMenu = workbenchContext.getWorkbench()
164: .getFrame().getLayerNamePopupMenu();
165: featureInstaller.addPopupMenuItem(layerNamePopupMenu, this ,
166: sSaveSelectedDatasets + "{pos:12}", false, null,
167: SaveDatasetsPlugIn.createEnableCheck(workbenchContext));
168: }
169:
170: public boolean execute(PlugInContext context) throws Exception {
171: try {
172: WorkbenchContext workbenchContext = context
173: .getWorkbenchContext();
174:
175: fileChooser = new JFileChooser();
176: //fileChooser = GUIUtil.createJFileChooserWithOverwritePrompting();
177: fileChooser.setDialogTitle(sSaveFilesFromReadOnlySources);
178: fileChooser.setDialogType(JFileChooser.SAVE_DIALOG);
179: fileChooser.setMultiSelectionEnabled(false);
180: GUIUtil.removeChoosableFileFilters(fileChooser);
181: FileFilter fileFilter1 = GUIUtil.createFileFilter("SHP "
182: + sFiles, new String[] { "shp" });
183: fileChooser.addChoosableFileFilter(fileFilter1);
184: FileFilter fileFilter2 = GUIUtil.createFileFilter("GML "
185: + sFiles, new String[] { "gml" });
186: fileChooser.addChoosableFileFilter(fileFilter2);
187: FileFilter fileFilter3 = GUIUtil.createFileFilter("JML "
188: + sFiles, new String[] { "jml" });
189: fileChooser.addChoosableFileFilter(fileFilter3);
190: FileFilter fileFilter4 = GUIUtil.createFileFilter("FME "
191: + sFiles, new String[] { "fme" });
192: fileChooser.addChoosableFileFilter(fileFilter4);
193: FileFilter fileFilter5 = GUIUtil.createFileFilter("WKT "
194: + sFiles, new String[] { "wkt" });
195: fileChooser.addChoosableFileFilter(fileFilter5);
196: fileChooser.setFileFilter(fileFilter1);
197:
198: boolean writeWarning = false;
199: String newLine = "";
200: context.getWorkbenchFrame().getOutputFrame()
201: .createNewDocument();
202:
203: LayerManager layerManager = context.getLayerManager();
204: Collection layerCollection = layerManager.getLayers();
205:
206: //ensure all appropriate layers get projection files
207: for (Iterator i = layerCollection.iterator(); i.hasNext();) {
208: writeProjectionFile(context, (Layer) i.next());
209: }
210:
211: List layerList = new ArrayList();
212:
213: if (saveAll) {
214: layerCollection = layerManager
215: .getLayersWithModifiedFeatureCollections();
216: for (Iterator i = layerCollection.iterator(); i
217: .hasNext();)
218: layerList.add((Layer) i.next());
219: } else {
220: layerCollection = (Collection) context
221: .getWorkbenchContext().getLayerNamePanel()
222: .selectedNodes(Layer.class);
223: for (Iterator i = layerCollection.iterator(); i
224: .hasNext();) {
225: Layer layer = (Layer) i.next();
226: boolean addIt = false;
227: DataSourceQuery dsq = layer.getDataSourceQuery();
228: if (dsq != null)
229: if (!dsq.getDataSource().isWritable())
230: addIt = true;
231: if (layer.isFeatureCollectionModified() || addIt) //just add modified or read-only layers
232: layerList.add(layer);
233: }
234: }
235:
236: //remove empty layers
237: for (int i = layerList.size() - 1; i >= 0; i--) {
238: Layer layer = (Layer) layerList.get(i);
239:
240: if (layer.getFeatureCollectionWrapper().getFeatures()
241: .size() == 0) //layer is empty
242: {
243: context.getWorkbenchFrame().getOutputFrame()
244: .addText(
245: sEmptyLayerNotSaved + ": "
246: + layer.getName());
247: writeWarning = true;
248: layerList.remove(i);
249: newLine = "\n";
250: }
251: }
252:
253: //remove any layers which have no data sources, ie,
254: //those that have not been previously saved
255: for (int i = layerList.size() - 1; i >= 0; i--) {
256: Layer layer = (Layer) layerList.get(i);
257: DataSourceQuery dsq = layer.getDataSourceQuery();
258:
259: boolean writeSaveMsg = false;
260:
261: if (dsq == null) //layer does not have a data source
262: {
263: writeSaveMsg = true;
264: } else {
265: DataSource ds = dsq.getDataSource();
266: if (ds == null) {
267: writeSaveMsg = true;
268: } else {
269: if (ds.getProperties().get("File") == null) {
270: writeSaveMsg = true;
271: }
272: }
273: }
274:
275: if (writeSaveMsg) {
276: context.getWorkbenchFrame().getOutputFrame()
277: .addText(
278: sUseSaveDatasetAsToSaveLayer
279: + layer.getName());
280: writeWarning = true;
281: layerList.remove(i);
282: newLine = "\n";
283: }
284: }
285:
286: //remove any layers which have read-only sources, ie, SdeDataSources
287: saveReadOnlySources = -1; //initialize so that we ask user if these are to be saved
288: pathToSaveReadOnlySources = ""; //initialize to that WriteLayer will ask the first time
289: String chosenSaveFile = "";
290:
291: for (int i = layerList.size() - 1; i >= 0; i--) {
292: Layer layer = (Layer) layerList.get(i);
293: DataSourceQuery dsq = layer.getDataSourceQuery();
294:
295: if (!dsq.getDataSource().isWritable()) //data source is read-only
296: {
297: if (saveReadOnlySources == -1) {
298: int response = JOptionPane.showConfirmDialog(
299: workbenchContext.getLayerViewPanel(),
300: sWantToSaveReadonly + "\n" + "("
301: + sNoteLayerNameWillBeFileName
302: + ")", "JUMP",
303: JOptionPane.YES_NO_OPTION);
304:
305: saveReadOnlySources = 0;
306: if (response == JOptionPane.YES_OPTION) {
307: if (JFileChooser.APPROVE_OPTION == fileChooser
308: .showSaveDialog(workbenchContext
309: .getLayerViewPanel())) {
310: File file = fileChooser
311: .getSelectedFile();
312: pathToSaveReadOnlySources = file
313: .getParent()
314: + "\\";
315: extToSaveReadOnlySources = "."
316: + FileUtil.getExtension(file);
317: saveReadOnlySources = 1;
318: chosenSaveFile = file.getPath();
319: }
320: }
321: }
322:
323: if (saveReadOnlySources == 0) {
324: context.getWorkbenchFrame().getOutputFrame()
325: .addText(
326: newLine + sCanNotSaveReadOnly
327: + ": "
328: + layer.getName());
329: writeWarning = true;
330: layerList.remove(i);
331: }
332: }
333: }
334:
335: //remove any layers which have the same data source
336: //since we don't want to overwrite earlier layers with later layers
337: int currRec = 0;
338: int lastRec = layerList.size() - 1;
339: boolean writeHeader = true;
340:
341: while (currRec < lastRec) {
342: Layer currLayer = (Layer) layerList.get(currRec);
343: String currDestination = currLayer.getDataSourceQuery()
344: .getDataSource().getProperties().get("File")
345: .toString();
346: if (!currLayer.getDataSourceQuery().getDataSource()
347: .isWritable()) //read-only source
348: currDestination = pathToSaveReadOnlySources
349: + currLayer.getName()
350: + extToSaveReadOnlySources;
351:
352: String dupLayers = "\n" + sFileName + ": "
353: + currDestination + "\n" + sLayerName + ": "
354: + currLayer.getName();
355:
356: int numDups = 0;
357: int checkRec = currRec + 1;
358:
359: while (checkRec <= lastRec) {
360: Layer checkLayer = (Layer) layerList.get(checkRec);
361: String checkDestination = checkLayer
362: .getDataSourceQuery().getDataSource()
363: .getProperties().get("File").toString();
364: if (!checkLayer.getDataSourceQuery()
365: .getDataSource().isWritable())
366: checkDestination = pathToSaveReadOnlySources
367: + checkLayer.getName()
368: + extToSaveReadOnlySources;
369: if (currDestination.equals(checkDestination)) //found duplicate source
370: {
371: dupLayers = dupLayers + "\n" + sLayerName
372: + ": " + checkLayer.getName();
373: layerList.remove(checkRec);
374: lastRec--;
375: numDups++;
376: } else {
377: checkRec++;
378: }
379: }
380:
381: if (numDups > 0) {
382: if (writeHeader) {
383: writeHeader = false;
384: writeWarning = true;
385: context.getWorkbenchFrame().getOutputFrame()
386: .addText(
387: "\n" + sDidNotSaveSameFile
388: + ":");
389: newLine = "\n";
390: }
391: context.getWorkbenchFrame().getOutputFrame()
392: .addText(dupLayers);
393:
394: layerList.remove(currRec);
395: lastRec--;
396: } else {
397: currRec++;
398: }
399: }
400:
401: //check to see if we need to warn user that files are about to be replaced
402: String replacedFiles = "";
403: int numReplaced = 0;
404: boolean fileMatches = false;
405:
406: for (int i = 0; i < layerList.size(); i++) {
407: String destinationFile = "";
408: Layer layer = (Layer) layerList.get(i);
409: DataSourceQuery dsq = layer.getDataSourceQuery();
410:
411: if (!dsq.getDataSource().isWritable()) {
412: destinationFile = pathToSaveReadOnlySources
413: + layer.getName()
414: + extToSaveReadOnlySources;
415:
416: if (new File(destinationFile).exists()) {
417: numReplaced++;
418: replacedFiles = replacedFiles + sReadOnlyLayer
419: + ": " + layer.getName() + " "
420: + sReplacesFile + ": "
421: + destinationFile + "\n";
422: if (destinationFile
423: .equalsIgnoreCase(chosenSaveFile))
424: fileMatches = true;
425: }
426: }
427:
428: }
429:
430: if ((numReplaced > 1)
431: || ((numReplaced == 1) && (!fileMatches))) //need to ask user if it is OK to replace files
432: {
433: String prompt = numReplaced + " "
434: + sReadOnlyWillReplace + "\n ("
435: + sNoteOutputWindow + ")";
436: if (numReplaced > 1)
437: prompt = numReplaced + " " + sReadOnlyWillReplace
438: + "\n (" + sNoteOutputWindow + ")";
439:
440: int response = JOptionPane.showConfirmDialog(
441: workbenchContext.getLayerViewPanel(), prompt,
442: "JUMP", JOptionPane.OK_CANCEL_OPTION);
443:
444: if (response == JOptionPane.CANCEL_OPTION) {
445: if (numReplaced == 1)
446: context.getWorkbenchFrame().getOutputFrame()
447: .addText(sWouldHaveReplaced + ":");
448: else
449: context.getWorkbenchFrame().getOutputFrame()
450: .addText(sWouldHaveReplaced + ":");
451:
452: context.getWorkbenchFrame().getOutputFrame()
453: .addText(replacedFiles);
454: writeWarning = true;
455: return true;
456: }
457:
458: if (numReplaced == 1)
459: context.getWorkbenchFrame().getOutputFrame()
460: .addText(sHasReplaced + ":");
461: else
462: context.getWorkbenchFrame().getOutputFrame()
463: .addText(sHasReplaced + ":");
464: context.getWorkbenchFrame().getOutputFrame().addText(
465: replacedFiles);
466: }
467:
468: //save the files
469: //won't get here if user did not want files replaced
470: for (int i = 0; i < layerList.size(); i++) {
471: Layer layer = (Layer) layerList.get(i);
472:
473: if (WriteLayer(context, layer)) {
474: layer.setFeatureCollectionModified(false);
475: context.getWorkbenchFrame().getOutputFrame()
476: .addText(
477: sSavedLayer + ": "
478: + layer.getName());
479: } else {
480: context.getWorkbenchFrame().getOutputFrame()
481: .addText(
482: sCouldNotSaveLayer + ": "
483: + layer.getName());
484: }
485:
486: }
487:
488: if (saveAll) {
489: if (context.getTask().getProjectFile() != null) {
490: new SaveProjectPlugIn(new SaveProjectAsPlugIn())
491: .execute(context);
492: context.getWorkbenchFrame().getOutputFrame()
493: .addText(
494: "\n "
495: + sSavedTask
496: + ": "
497: + context.getTask()
498: .getProjectFile()
499: .getName());
500: }
501: }
502:
503: if (writeWarning)
504: context.getWorkbenchFrame().warnUser(
505: sCouldNotSaveLayer + " --- "
506: + sErrorSeeOutputWindow);
507:
508: return true;
509: } catch (Exception e) {
510: context.getWorkbenchFrame().warnUser(sErrorSeeOutputWindow);
511: context.getWorkbenchFrame().getOutputFrame().addText(
512: "SaveDatasetsPlugIn Exception:" + e.toString());
513: return false;
514: }
515: }
516:
517: public static MultiEnableCheck createEnableCheck(
518: WorkbenchContext workbenchContext) {
519: EnableCheckFactory checkFactory = new EnableCheckFactory(
520: workbenchContext);
521:
522: return new MultiEnableCheck()
523: .add(
524: checkFactory
525: .createWindowWithSelectionManagerMustBeActiveCheck())
526: .add(
527: checkFactory
528: .createAtLeastNLayersMustBeSelectedCheck(1));
529: }
530:
531: public void setSaveAll() {
532: saveAll = true;
533: }
534:
535: private boolean WriteLayer(PlugInContext context, Layer layer) {
536: String filename = "";
537: DataSourceQuery dsq = layer.getDataSourceQuery();
538: if (dsq.getDataSource().isWritable()) {
539: filename = dsq.getDataSource().getProperties().get("File")
540: .toString();
541: } else //read-only source
542: {
543: filename = pathToSaveReadOnlySources + layer.getName()
544: + extToSaveReadOnlySources;
545:
546: //the following shouldn't happen
547: if (pathToSaveReadOnlySources.equals("")) {
548: context.getWorkbenchFrame().getOutputFrame().addText(
549: sNoOutputDir + ": " + layer.getName());
550: context.getWorkbenchFrame().warnUser(
551: sWarningSeeOutputWindow);
552: return false;
553: }
554: if (extToSaveReadOnlySources.equals("")) {
555: context.getWorkbenchFrame().getOutputFrame().addText(
556: sNoOutputFileExt + ": " + layer.getName());
557: context.getWorkbenchFrame().warnUser(
558: sWarningSeeOutputWindow);
559: return false;
560: }
561: }
562:
563: DriverProperties dp = new DriverProperties();
564: dp.set("File", filename);
565:
566: try {
567: if ((filename.toLowerCase()).endsWith(".shp")) {
568: String path = new File(filename).getParent() + "\\";
569: List newLayers = new ArrayList();
570:
571: if (!CompatibleFeatures(layer))
572: newLayers = splitLayer(context, layer);
573:
574: (new ShapefileWriter()).write(layer
575: .getFeatureCollectionWrapper(), dp);
576:
577: for (int i = 0; i < newLayers.size(); i++) {
578: Layer newLayer = (Layer) newLayers.get(i);
579: String newFileName = path + newLayer.getName()
580: + ".shp";
581: HashMap properties = new HashMap();
582: properties.put(DataSource.COORDINATE_SYSTEM_KEY,
583: "Unspecified");
584: properties.put(DataSource.FILE_KEY, newFileName);
585: DataSource dataSource = (DataSource) StandardReaderWriterFileDataSource.Shapefile.class
586: .newInstance();
587: dataSource.setProperties(properties);
588: DataSourceQuery dataSourceQuery = new DataSourceQuery(
589: dataSource, newLayer.getName(), null);
590: newLayer.setDataSourceQuery(dataSourceQuery)
591: .setFeatureCollectionModified(false);
592: dp.set("File", newFileName);
593: (new ShapefileWriter()).write(newLayer
594: .getFeatureCollectionWrapper(), dp);
595: context.getWorkbenchFrame().getOutputFrame()
596: .addText(
597: sSavedLayer + ": "
598: + newLayer.getName());
599: }
600:
601: return true;
602: }
603:
604: if ((filename.toLowerCase()).endsWith(".jml")) {
605: (new JMLWriter()).write(layer
606: .getFeatureCollectionWrapper(), dp);
607: return true;
608: }
609:
610: if ((filename.toLowerCase()).endsWith(".gml")) {
611: (new GMLWriter()).write(layer
612: .getFeatureCollectionWrapper(), dp);
613: return true;
614: }
615:
616: if ((filename.toLowerCase()).endsWith(".fme")) {
617: (new FMEGMLWriter()).write(layer
618: .getFeatureCollectionWrapper(), dp);
619: return true;
620: }
621:
622: if ((filename.toLowerCase()).endsWith(".wkt")) {
623: (new WKTWriter()).write(layer
624: .getFeatureCollectionWrapper(), dp);
625: return true;
626: }
627:
628: context.getWorkbenchFrame().getOutputFrame().addText(
629: sUnrecognizedFileType + " --- "
630: + sCouldNotSaveLayer + ": "
631: + layer.getName());
632: context.getWorkbenchFrame().warnUser(sErrorSeeOutputWindow);
633: return false;
634: } catch (Exception e) {
635: context.getWorkbenchFrame().warnUser(sErrorSeeOutputWindow);
636: context.getWorkbenchFrame().getOutputFrame()
637: .createNewDocument();
638: context.getWorkbenchFrame().getOutputFrame().addText(
639: "SaveDatasetsPlugIn:WriteLayer Exception:"
640: + e.toString());
641: return false;
642: }
643: }
644:
645: private boolean CompatibleFeatures(Layer layer) {
646: BitSet bitSet = new BitSet();
647: FeatureCollectionWrapper featureCollection = layer
648: .getFeatureCollectionWrapper();
649: List featureList = featureCollection.getFeatures();
650:
651: for (Iterator i = featureList.iterator(); i.hasNext();)
652: bitSet = GeoUtils.setBit(bitSet, ((Feature) i.next())
653: .getGeometry());
654:
655: return (bitSet.cardinality() < 2);
656: }
657:
658: private List splitLayer(PlugInContext context, Layer layer) {
659: ArrayList newLayers = new ArrayList();
660:
661: if (!CompatibleFeatures(layer)) {
662: ArrayList emptyFeatures = new ArrayList();
663: ArrayList pointFeatures = new ArrayList();
664: ArrayList lineFeatures = new ArrayList();
665: ArrayList polyFeatures = new ArrayList();
666: ArrayList groupFeatures = new ArrayList();
667:
668: FeatureCollectionWrapper featureCollection = layer
669: .getFeatureCollectionWrapper();
670: List featureList = featureCollection.getFeatures();
671: FeatureSchema featureSchema = layer
672: .getFeatureCollectionWrapper().getFeatureSchema();
673:
674: //first find and handle all empty geometries and GeometryCollections
675: for (Iterator i = featureList.iterator(); i.hasNext();) {
676: Feature feature = (Feature) i.next();
677: Geometry geometry = feature.getGeometry();
678:
679: if (geometry.isEmpty()) //going to delete it
680: emptyFeatures.add(feature);
681: else if ((geometry instanceof GeometryCollection)
682: && (!(geometry instanceof MultiPoint))
683: && (!(geometry instanceof MultiLineString))
684: && (!(geometry instanceof MultiPolygon))) //mixed geometry; going to explode it
685: groupFeatures.add(feature);
686: }
687:
688: for (int i = 0; i < emptyFeatures.size(); i++) //delete empty geometries
689: {
690: featureCollection
691: .remove((Feature) emptyFeatures.get(i));
692: }
693:
694: for (int i = 0; i < groupFeatures.size(); i++) //delete GeometryCollections
695: {
696: Feature feature = (Feature) groupFeatures.get(i);
697: GeometryCollection geometry = (GeometryCollection) feature
698: .getGeometry();
699: explodeGeometryCollection(featureSchema, pointFeatures,
700: lineFeatures, polyFeatures, geometry, feature);
701: featureCollection.remove(feature);
702: }
703:
704: //now get new list of remaining features
705: featureCollection = layer.getFeatureCollectionWrapper();
706: featureList = layer.getFeatureCollectionWrapper()
707: .getFeatures();
708: BitSet layerBit = new BitSet();
709: if (featureList.size() > 0) {
710: Geometry firstGeo = ((Feature) featureList.iterator()
711: .next()).getGeometry();
712: layerBit = GeoUtils.setBit(layerBit, firstGeo); //this is the layer type
713: }
714:
715: //now add just the exploded features that belong on the the original layer
716: if (layerBit.get(GeoUtils.polyBit)) {
717: if (polyFeatures.size() > 0) {
718: for (int i = 0; i < polyFeatures.size(); i++) {
719: Feature feature = (Feature) polyFeatures.get(i);
720: featureCollection.add(feature);
721: }
722: polyFeatures.clear();
723: }
724: } else if (layerBit.get(GeoUtils.lineBit)) {
725: if (lineFeatures.size() > 0) {
726: for (int i = 0; i < lineFeatures.size(); i++) {
727: Feature feature = (Feature) lineFeatures.get(i);
728: featureCollection.add(feature);
729: }
730: lineFeatures.clear();
731: }
732: } else if (layerBit.get(GeoUtils.pointBit)) {
733: if (pointFeatures.size() > 0) {
734: for (int i = 0; i < pointFeatures.size(); i++) {
735: Feature feature = (Feature) pointFeatures
736: .get(i);
737: featureCollection.add(feature);
738: }
739: pointFeatures.clear();
740: }
741: } else //nothing left on layer; just pick a type for the layer
742: {
743: if (polyFeatures.size() > 0) {
744: for (int i = 0; i < polyFeatures.size(); i++) {
745: Feature feature = (Feature) polyFeatures.get(i);
746: featureCollection.add(feature);
747: }
748: polyFeatures.clear();
749: } else if (lineFeatures.size() > 0) {
750: for (int i = 0; i < lineFeatures.size(); i++) {
751: Feature feature = (Feature) lineFeatures.get(i);
752: featureCollection.add(feature);
753: }
754: lineFeatures.clear();
755: } else if (pointFeatures.size() > 0) {
756: for (int i = 0; i < pointFeatures.size(); i++) {
757: Feature feature = (Feature) pointFeatures
758: .get(i);
759: featureCollection.add(feature);
760: }
761: pointFeatures.clear();
762: }
763: }
764:
765: //at this point we have taken care of the GeometryCollections
766: //some part of them have been added to the original layer
767: //the rest of the features are in the array lists waiting
768: //to be added to the appropriate layers
769:
770: featureCollection = layer.getFeatureCollectionWrapper();
771: featureList = layer.getFeatureCollectionWrapper()
772: .getFeatures();
773: layerBit = new BitSet();
774: if (featureList.size() > 0) {
775: Geometry firstGeo = ((Feature) featureList.iterator()
776: .next()).getGeometry();
777: layerBit = GeoUtils.setBit(layerBit, firstGeo); //this is the layer type
778: }
779:
780: Collection selectedCategories = context.getLayerNamePanel()
781: .getSelectedCategories();
782:
783: for (Iterator i = featureList.iterator(); i.hasNext();) {
784: Feature feature = (Feature) i.next();
785: Geometry geo = feature.getGeometry();
786: BitSet currFeatureBit = new BitSet();
787: currFeatureBit = GeoUtils.setBit(currFeatureBit, geo);
788:
789: if (!layerBit.get(GeoUtils.pointBit)
790: && currFeatureBit.get(GeoUtils.pointBit))
791: pointFeatures.add(feature);
792:
793: if (!layerBit.get(GeoUtils.lineBit)
794: && currFeatureBit.get(GeoUtils.lineBit))
795: lineFeatures.add(feature);
796:
797: if (!layerBit.get(GeoUtils.polyBit)
798: && currFeatureBit.get(GeoUtils.polyBit))
799: polyFeatures.add(feature);
800: }
801:
802: if (pointFeatures.size() > 0) {
803: Layer pointLayer = context.addLayer(selectedCategories
804: .isEmpty() ? StandardCategoryNames.WORKING
805: : selectedCategories.iterator().next()
806: .toString(),
807: layer.getName() + "_point", new FeatureDataset(
808: featureSchema));
809:
810: FeatureCollectionWrapper pointFeatureCollection = pointLayer
811: .getFeatureCollectionWrapper();
812: newLayers.add(pointLayer);
813: context.getWorkbenchFrame().getOutputFrame().addText(
814: sNewLayerCreated + ": " + pointLayer.getName());
815: context.getWorkbenchFrame().warnUser(
816: sNewLayerCreated + " - "
817: + sErrorSeeOutputWindow);
818:
819: for (int i = 0; i < pointFeatures.size(); i++) {
820: Feature feature = (Feature) pointFeatures.get(i);
821: featureCollection.remove(feature);
822: pointFeatureCollection.add(feature);
823: }
824: }
825:
826: if (lineFeatures.size() > 0) {
827: Layer lineLayer = context.addLayer(selectedCategories
828: .isEmpty() ? StandardCategoryNames.WORKING
829: : selectedCategories.iterator().next()
830: .toString(), layer.getName() + "_line",
831: new FeatureDataset(featureSchema));
832:
833: FeatureCollectionWrapper lineFeatureCollection = lineLayer
834: .getFeatureCollectionWrapper();
835: newLayers.add(lineLayer);
836: context.getWorkbenchFrame().getOutputFrame().addText(
837: sNewLayerCreated + ": " + lineLayer.getName());
838: context.getWorkbenchFrame().warnUser(
839: sNewLayerCreated + " - "
840: + sErrorSeeOutputWindow);
841:
842: for (int i = 0; i < lineFeatures.size(); i++) {
843: Feature feature = (Feature) lineFeatures.get(i);
844: featureCollection.remove(feature);
845: lineFeatureCollection.add(feature);
846: }
847: }
848:
849: if (polyFeatures.size() > 0) {
850: Layer polyLayer = context.addLayer(selectedCategories
851: .isEmpty() ? StandardCategoryNames.WORKING
852: : selectedCategories.iterator().next()
853: .toString(), layer.getName() + "_area",
854: new FeatureDataset(featureSchema));
855:
856: FeatureCollectionWrapper polyFeatureCollection = polyLayer
857: .getFeatureCollectionWrapper();
858: newLayers.add(polyLayer);
859: context.getWorkbenchFrame().getOutputFrame().addText(
860: sNewLayerCreated + ": " + polyLayer.getName());
861: context.getWorkbenchFrame().warnUser(
862: sNewLayerCreated + " - "
863: + sErrorSeeOutputWindow);
864:
865: for (int i = 0; i < polyFeatures.size(); i++) {
866: Feature feature = (Feature) polyFeatures.get(i);
867: featureCollection.remove(feature);
868: polyFeatureCollection.add(feature);
869: }
870: }
871: }
872: return newLayers;
873: }
874:
875: private void explodeGeometryCollection(FeatureSchema fs,
876: ArrayList pointFeatures, ArrayList lineFeatures,
877: ArrayList polyFeatures,
878: GeometryCollection geometryCollection, Feature feature) {
879: for (int i = 0; i < geometryCollection.getNumGeometries(); i++) {
880: Geometry geometry = geometryCollection.getGeometryN(i);
881:
882: if (geometry instanceof GeometryCollection) {
883: explodeGeometryCollection(fs, pointFeatures,
884: lineFeatures, polyFeatures,
885: (GeometryCollection) geometry, feature);
886: } else {
887: //Feature newFeature = new BasicFeature(fs);
888: Feature newFeature = feature.clone(true);
889: newFeature.setGeometry(geometry);
890: BitSet featureBit = new BitSet();
891: featureBit = GeoUtils.setBit(featureBit, geometry);
892: if (featureBit.get(GeoUtils.pointBit))
893: pointFeatures.add(newFeature);
894: if (featureBit.get(GeoUtils.lineBit))
895: lineFeatures.add(newFeature);
896: if (featureBit.get(GeoUtils.polyBit))
897: polyFeatures.add(newFeature);
898: }
899: }
900: }
901:
902: private void writeProjectionFile(PlugInContext context,
903: Layer outputLayer) throws IOException,
904: FileNotFoundException { //per LDB projection files only associated with .shp files; confirmed 8/16/05
905: DataSourceQuery dsqOut = outputLayer.getDataSourceQuery();
906:
907: if (dsqOut != null) //file exists; not a new layer
908: {
909: String outputFileName = dsqOut.getDataSource()
910: .getProperties().get("File").toString();
911: if ((outputFileName.toLowerCase()).endsWith(".shp")) {
912: String outputPrjFileName = "";
913: int pos = outputFileName.lastIndexOf('.');
914: outputPrjFileName = outputFileName.substring(0, pos)
915: + ".prj";
916:
917: if (!(new File(outputPrjFileName).exists())) { //loop through all layers to find a project file; then copy contents
918: List layerList = context.getLayerManager()
919: .getLayers();
920:
921: for (Iterator i = layerList.iterator(); i.hasNext();) {
922: Layer layer = (Layer) i.next();
923: DataSourceQuery dsq = layer
924: .getDataSourceQuery();
925: if (dsq != null) {
926: String inputFileName = dsq.getDataSource()
927: .getProperties().get("File")
928: .toString();
929:
930: if ((inputFileName.toLowerCase())
931: .endsWith(".shp")) {
932: String inputPrjFileName = "";
933: pos = inputFileName.lastIndexOf('.');
934: inputPrjFileName = inputFileName
935: .substring(0, pos)
936: + ".prj";
937:
938: if (new File(inputPrjFileName).exists()) {
939: List prjStr = FileUtil
940: .getContents(inputPrjFileName);
941: try {
942: FileUtil.setContents(
943: outputPrjFileName,
944: prjStr);
945: } catch (IOException ex) {
946: context
947: .getWorkbenchFrame()
948: .getOutputFrame()
949: .addText(
950: sCouldNotWrite
951: + ": "
952: + outputPrjFileName
953: + " --- "
954: + ex
955: .getMessage());
956: }
957: break;
958: }
959: }
960: }
961: }
962: }
963: }
964: }
965: }
966:
967: }
|