/*
* The Unified Mapping Platform (JUMP) is an extensible, interactive GUI
* for visualizing and manipulating spatial features with geometry and attributes.
*
* JUMP is Copyright (C) 2003 Vivid Solutions
*
* This program implements extensions to JUMP and is
* Copyright (C) 2004 Integrated Systems Analysts, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* For more information, contact:
*
* Integrated Systems Analysts, Inc.
* 630C Anchors St., Suite 101
* Fort Walton Beach, Florida
* USA
*
* (850)862-7321
* www.ashs.isa.com
*/
package org.openjump.core.ui.plugin.mousemenu;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.filechooser.FileFilter;
import org.openjump.core.geomutils.GeoUtils;
import org.openjump.core.ui.images.IconLoader;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryCollection;
import com.vividsolutions.jts.geom.MultiLineString;
import com.vividsolutions.jts.geom.MultiPoint;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jump.I18N;
import com.vividsolutions.jump.feature.Feature;
import com.vividsolutions.jump.feature.FeatureCollectionWrapper;
import com.vividsolutions.jump.feature.FeatureDataset;
import com.vividsolutions.jump.feature.FeatureSchema;
import com.vividsolutions.jump.io.DriverProperties;
import com.vividsolutions.jump.io.FMEGMLWriter;
import com.vividsolutions.jump.io.GMLWriter;
import com.vividsolutions.jump.io.JMLWriter;
import com.vividsolutions.jump.io.ShapefileWriter;
import com.vividsolutions.jump.io.WKTWriter;
import com.vividsolutions.jump.io.datasource.DataSource;
import com.vividsolutions.jump.io.datasource.DataSourceQuery;
import com.vividsolutions.jump.io.datasource.StandardReaderWriterFileDataSource;
import com.vividsolutions.jump.util.FileUtil;
import com.vividsolutions.jump.workbench.WorkbenchContext;
import com.vividsolutions.jump.workbench.model.Layer;
import com.vividsolutions.jump.workbench.model.LayerManager;
import com.vividsolutions.jump.workbench.model.StandardCategoryNames;
import com.vividsolutions.jump.workbench.plugin.AbstractPlugIn;
import com.vividsolutions.jump.workbench.plugin.EnableCheckFactory;
import com.vividsolutions.jump.workbench.plugin.MultiEnableCheck;
import com.vividsolutions.jump.workbench.plugin.PlugInContext;
import com.vividsolutions.jump.workbench.ui.GUIUtil;
import com.vividsolutions.jump.workbench.ui.WorkbenchFrame;
import com.vividsolutions.jump.workbench.ui.WorkbenchToolBar;
import com.vividsolutions.jump.workbench.plugin.EnableCheck;
import com.vividsolutions.jump.workbench.ui.plugin.FeatureInstaller;
import com.vividsolutions.jump.workbench.ui.plugin.SaveProjectAsPlugIn;
import com.vividsolutions.jump.workbench.ui.plugin.SaveProjectPlugIn;
public class SaveDatasetsPlugIn extends AbstractPlugIn
{
private static final String sSaveSelectedDatasets = I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Save-Selected-Datasets");
private static final String sUseSaveDatasetAsToSaveLayer= I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Use***Save-Dataset-As***to-Save-Layer");
private static final String sSavedLayer= I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Saved-Layer");
private static final String sErrorSeeOutputWindow=I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Error-See-Output-Window");
private static final String sWarningSeeOutputWindow=I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Warning-See-Output-Window");
private static final String sCouldNotSaveLayer=I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Could-not-save-layer");
private static final String sCouldNotSave=I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Could-not-save");
private static final String sLayer=I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.layer");
private static final String sWithEmptyGeometry=I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.with-empty-geometry");
private static final String sWithMixedGeometryTypes=I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.with-mixed-geometry-types");
private static final String sCanNotSaveReadOnly=I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Cannot-save-to-read-only-source-for-layer");
private static final String sDidNotSaveSameFile=I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Did-not-save-these-layers-since-they-would-have-to-be-saved-to-the-same-file");
private static final String sSavedTask=I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Saved-task");
private static final String sFileName=I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.File-Name");
private static final String sLayerName=I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Layer-Name");
private static final String sUnrecognizedFileType=I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Unrecognized-file-type");
private static final String sNewLayerCreated=I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.New-layer-created");
private static final String sCouldNotWrite=I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Could-not-write");
private static final String sEmptyLayerNotSaved = I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Empty-layer-not-saved");
private static final String sSaveFilesFromReadOnlySources = I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Save-files-from-read-only-sources");
private static final String sFiles = I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Files");
private static final String sWantToSaveReadonly = I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Do-you-want-to-save-the-read-only-layers");
private static final String sNoteLayerNameWillBeFileName = I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Note-layer-name-will-be-filename");
private static final String sReadOnlyLayer = I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.read-only-layer");
private static final String sReplacesFile = I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.replaces-file");
private static final String sReadOnlyWillReplace = I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.read-only-source-will-replace-an-existing-file");
private static final String sNoteOutputWindow = I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.Note-Output-window-will-display-the-results-of-this-command");
private static final String sWouldHaveReplaced = I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.The-read-only-layer-would-have-replaced-the-following-file(s)");
private static final String sHasReplaced = I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.The-read-only-layer-has-replaced-the-following-file(s)");
private static final String sNoOutputDir = I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.No-output-directory-designated-for-read-only-source-could-not-save-layer");
private static final String sNoOutputFileExt = I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.No-output-file-extension-designated-for-read-only-source-could-not-save-layer");
// With the new "modified-writable-layer-selected" enableCheck, we shouldn't need
// sCanNotSaveReadOnly
private static final String sNoModifiedWritableLayerSelected = I18N.get("org.openjump.core.ui.plugin.mousemenu.SaveDatasetsPlugIn.No-modified-writable-layer-selected");
private boolean saveAll = false;
private int saveReadOnlySources = -1; //-1 - ask; 0 - don't save; 1 - save;
private String pathToSaveReadOnlySources = "";
private String extToSaveReadOnlySources = "";
private JFileChooser fileChooser;
public void initialize(PlugInContext context) throws Exception
{
WorkbenchContext workbenchContext = context.getWorkbenchContext();
WorkbenchFrame frame = workbenchContext.getWorkbench().getFrame();
FeatureInstaller featureInstaller = new FeatureInstaller(workbenchContext);
EnableCheck enableCheck = SaveDatasetsPlugIn.createEnableCheck(workbenchContext);
JPopupMenu layerNamePopupMenu = frame.getLayerNamePopupMenu();
// Add tool-bar Icon
WorkbenchToolBar toolBar = frame.getToolBar();
toolBar.addPlugIn(2, this, ICON, enableCheck, workbenchContext);
featureInstaller.addPopupMenuItem(layerNamePopupMenu,
this, sSaveSelectedDatasets +"{pos:12}",
false, ICON,
enableCheck);
}
public static final ImageIcon ICON = IconLoader.icon("disk_multiple.png");
public boolean execute(PlugInContext context) throws Exception
{
try
{
WorkbenchContext workbenchContext = context.getWorkbenchContext();
fileChooser = new JFileChooser();
//fileChooser = GUIUtil.createJFileChooserWithOverwritePrompting();
fileChooser.setDialogTitle(sSaveFilesFromReadOnlySources);
fileChooser.setDialogType(JFileChooser.SAVE_DIALOG);
fileChooser.setMultiSelectionEnabled(false);
GUIUtil.removeChoosableFileFilters(fileChooser);
FileFilter fileFilter1 = GUIUtil.createFileFilter("SHP " + sFiles, new String[]{"shp"});
fileChooser.addChoosableFileFilter(fileFilter1);
FileFilter fileFilter2 = GUIUtil.createFileFilter("GML " + sFiles, new String[]{"gml"});
fileChooser.addChoosableFileFilter(fileFilter2);
FileFilter fileFilter3 = GUIUtil.createFileFilter("JML " + sFiles, new String[]{"jml"});
fileChooser.addChoosableFileFilter(fileFilter3);
FileFilter fileFilter4 = GUIUtil.createFileFilter("FME " + sFiles, new String[]{"fme"});
fileChooser.addChoosableFileFilter(fileFilter4);
FileFilter fileFilter5 = GUIUtil.createFileFilter("WKT " + sFiles, new String[]{"wkt"});
fileChooser.addChoosableFileFilter(fileFilter5);
fileChooser.setFileFilter(fileFilter1);
boolean writeWarning = false;
String newLine = "";
context.getWorkbenchFrame().getOutputFrame().createNewDocument();
LayerManager layerManager = context.getLayerManager();
Collection layerCollection = layerManager.getLayers();
//ensure all appropriate layers get projection files
for (Iterator i = layerCollection.iterator(); i.hasNext();)
{
writeProjectionFile(context, (Layer) i.next());
}
List layerList = new ArrayList();
if (saveAll)
{
layerCollection = layerManager.getLayersWithModifiedFeatureCollections();
for (Iterator i = layerCollection.iterator(); i.hasNext();)
layerList.add((Layer) i.next());
}
else
{
layerCollection = (Collection) context.getWorkbenchContext().getLayerNamePanel().selectedNodes(Layer.class);
for (Iterator i = layerCollection.iterator(); i.hasNext();)
{
Layer layer = (Layer) i.next();
boolean addIt = false;
DataSourceQuery dsq = layer.getDataSourceQuery();
if (dsq != null)
if (!dsq.getDataSource().isWritable())
addIt = true;
if (layer.isFeatureCollectionModified() || addIt) //just add modified or read-only layers
layerList.add(layer);
}
}
//remove empty layers
for (int i = layerList.size() - 1; i >= 0; i--)
{
Layer layer = (Layer) layerList.get(i);
if (layer.getFeatureCollectionWrapper().getFeatures().size() == 0) //layer is empty
{
context.getWorkbenchFrame().getOutputFrame().addText( sEmptyLayerNotSaved + ": " + layer.getName());
writeWarning = true;
layerList.remove(i);
newLine = "\n";
}
}
//remove any layers which have no data sources, ie,
//those that have not been previously saved
for (int i = layerList.size() - 1; i >= 0; i--)
{
Layer layer = (Layer) layerList.get(i);
DataSourceQuery dsq = layer.getDataSourceQuery();
boolean writeSaveMsg = false;
if (dsq == null) //layer does not have a data source
{
writeSaveMsg = true;
}
else
{
DataSource ds = dsq.getDataSource();
if (ds == null)
{
writeSaveMsg = true;
}
else
{
if (ds.getProperties().get("File") == null)
{
writeSaveMsg = true;
}
}
}
if (writeSaveMsg)
{
context.getWorkbenchFrame().getOutputFrame().addText(sUseSaveDatasetAsToSaveLayer + layer.getName());
writeWarning = true;
layerList.remove(i);
newLine = "\n";
}
}
//remove any layers which have read-only sources, ie, SdeDataSources
saveReadOnlySources = -1; //initialize so that we ask user if these are to be saved
pathToSaveReadOnlySources = ""; //initialize to that WriteLayer will ask the first time
String chosenSaveFile = "";
for (int i = layerList.size() - 1; i >= 0; i--)
{
Layer layer = (Layer) layerList.get(i);
DataSourceQuery dsq = layer.getDataSourceQuery();
if (!dsq.getDataSource().isWritable()) //data source is read-only
{
if (saveReadOnlySources == -1)
{
int response = JOptionPane.showConfirmDialog(workbenchContext.getLayerViewPanel(),
sWantToSaveReadonly + "\n" + "(" + sNoteLayerNameWillBeFileName + ")",
"JUMP", JOptionPane.YES_NO_OPTION);
saveReadOnlySources = 0;
if (response == JOptionPane.YES_OPTION)
{
if (JFileChooser.APPROVE_OPTION == fileChooser.showSaveDialog(workbenchContext.getLayerViewPanel()))
{
File file = fileChooser.getSelectedFile();
pathToSaveReadOnlySources = file.getParent() + "\\";
extToSaveReadOnlySources = "." + FileUtil.getExtension(file);
saveReadOnlySources = 1;
chosenSaveFile = file.getPath();
}
}
}
if (saveReadOnlySources == 0)
{
context.getWorkbenchFrame().getOutputFrame().addText(newLine + sCanNotSaveReadOnly + ": " + layer.getName());
writeWarning = true;
layerList.remove(i);
}
}
}
//remove any layers which have the same data source
//since we don't want to overwrite earlier layers with later layers
int currRec = 0;
int lastRec = layerList.size() - 1;
boolean writeHeader = true;
while (currRec < lastRec)
{
Layer currLayer = (Layer) layerList.get(currRec);
String currDestination = currLayer.getDataSourceQuery().getDataSource().getProperties().get("File").toString();
if (!currLayer.getDataSourceQuery().getDataSource().isWritable()) //read-only source
currDestination = pathToSaveReadOnlySources + currLayer.getName() + extToSaveReadOnlySources;
String dupLayers = "\n" + sFileName + ": " + currDestination + "\n" + sLayerName + ": " + currLayer.getName();
int numDups = 0;
int checkRec = currRec + 1;
while (checkRec <= lastRec)
{
Layer checkLayer = (Layer) layerList.get(checkRec);
String checkDestination = checkLayer.getDataSourceQuery().getDataSource().getProperties().get("File").toString();
if (!checkLayer.getDataSourceQuery().getDataSource().isWritable())
checkDestination = pathToSaveReadOnlySources + checkLayer.getName() + extToSaveReadOnlySources;
if (currDestination.equals(checkDestination)) //found duplicate source
{
dupLayers = dupLayers + "\n" + sLayerName + ": " + checkLayer.getName();
layerList.remove(checkRec);
lastRec--;
numDups++;
}
else
{
checkRec++;
}
}
if (numDups > 0)
{
if (writeHeader)
{
writeHeader = false;
writeWarning = true;
context.getWorkbenchFrame().getOutputFrame().addText(
"\n" + sDidNotSaveSameFile + ":");
newLine = "\n";
}
context.getWorkbenchFrame().getOutputFrame().addText(dupLayers);
layerList.remove(currRec);
lastRec--;
}
else
{
currRec++;
}
}
//check to see if we need to warn user that files are about to be replaced
String replacedFiles = "";
int numReplaced = 0;
boolean fileMatches = false;
for (int i = 0; i < layerList.size(); i++)
{
String destinationFile = "";
Layer layer = (Layer) layerList.get(i);
DataSourceQuery dsq = layer.getDataSourceQuery();
if (!dsq.getDataSource().isWritable())
{
destinationFile = pathToSaveReadOnlySources + layer.getName() + extToSaveReadOnlySources;
if (new File(destinationFile).exists())
{
numReplaced++;
replacedFiles = replacedFiles + sReadOnlyLayer + ": " + layer.getName() + " " + sReplacesFile + ": " + destinationFile + "\n";
if (destinationFile.equalsIgnoreCase(chosenSaveFile))
fileMatches = true;
}
}
}
if ((numReplaced > 1) || ((numReplaced == 1) && (!fileMatches))) //need to ask user if it is OK to replace files
{
String prompt = numReplaced + " " + sReadOnlyWillReplace + "\n (" + sNoteOutputWindow + ")";
if (numReplaced > 1)
prompt = numReplaced + " " + sReadOnlyWillReplace + "\n (" + sNoteOutputWindow + ")";
int response = JOptionPane.showConfirmDialog(workbenchContext.getLayerViewPanel(),
prompt, "JUMP", JOptionPane.OK_CANCEL_OPTION);
if (response == JOptionPane.CANCEL_OPTION)
{
if (numReplaced == 1)
context.getWorkbenchFrame().getOutputFrame().addText(sWouldHaveReplaced + ":");
else
context.getWorkbenchFrame().getOutputFrame().addText(sWouldHaveReplaced + ":");
context.getWorkbenchFrame().getOutputFrame().addText(replacedFiles);
writeWarning = true;
return true;
}
if (numReplaced == 1)
context.getWorkbenchFrame().getOutputFrame().addText(sHasReplaced + ":");
else
context.getWorkbenchFrame().getOutputFrame().addText(sHasReplaced + ":");
context.getWorkbenchFrame().getOutputFrame().addText(replacedFiles);
}
//save the files
//won't get here if user did not want files replaced
for (int i = 0; i < layerList.size(); i++)
{
Layer layer = (Layer) layerList.get(i);
if (WriteLayer(context, layer))
{
layer.setFeatureCollectionModified(false);
context.getWorkbenchFrame().getOutputFrame().addText(sSavedLayer + ": " + layer.getName());
}
else
{
context.getWorkbenchFrame().getOutputFrame().addText(sCouldNotSaveLayer + ": " + layer.getName());
}
}
if (saveAll)
{
if (context.getTask().getProjectFile() != null)
{
new SaveProjectPlugIn(new SaveProjectAsPlugIn()).execute(context);
context.getWorkbenchFrame().getOutputFrame().addText("\n " + sSavedTask +": " + context.getTask().getProjectFile().getName());
}
}
if (writeWarning)
context.getWorkbenchFrame().warnUser(sCouldNotSaveLayer + " --- " + sErrorSeeOutputWindow);
return true;
}
catch (Exception e)
{
context.getWorkbenchFrame().warnUser(sErrorSeeOutputWindow);
context.getWorkbenchFrame().getOutputFrame().addText("SaveDatasetsPlugIn Exception:" + e.toString());
return false;
}
}
public static MultiEnableCheck createEnableCheck(final WorkbenchContext workbenchContext)
{
EnableCheckFactory checkFactory = new EnableCheckFactory(workbenchContext);
return new MultiEnableCheck()
.add(checkFactory.createWindowWithSelectionManagerMustBeActiveCheck())
.add(checkFactory.createAtLeastNLayersMustBeSelectedCheck(1))
.add(new EnableCheck() {
public String check(JComponent component) {
Layer[] lyrs = workbenchContext.getLayerNamePanel().getSelectedLayers();
boolean changesToSave = false;
for (Layer lyr : lyrs) {
if (!lyr.isReadonly() &&
lyr.hasReadableDataSource() &&
lyr.isFeatureCollectionModified()) return null;
}
return sNoModifiedWritableLayerSelected;
}
});
}
public void setSaveAll()
{
saveAll = true;
}
private boolean WriteLayer(PlugInContext context, Layer layer)
{
String filename = "";
DataSourceQuery dsq = layer.getDataSourceQuery();
if (dsq.getDataSource().isWritable())
{
filename = dsq.getDataSource().getProperties().get("File").toString();
}
else //read-only source
{
filename = pathToSaveReadOnlySources + layer.getName() + extToSaveReadOnlySources;
//the following shouldn't happen
if (pathToSaveReadOnlySources.equals(""))
{
context.getWorkbenchFrame().getOutputFrame().addText(sNoOutputDir + ": " + layer.getName());
context.getWorkbenchFrame().warnUser(sWarningSeeOutputWindow);
return false;
}
if (extToSaveReadOnlySources.equals(""))
{
context.getWorkbenchFrame().getOutputFrame().addText(sNoOutputFileExt + ": " + layer.getName());
context.getWorkbenchFrame().warnUser(sWarningSeeOutputWindow);
return false;
}
}
DriverProperties dp = new DriverProperties();
dp.set("File", filename);
try
{
if ((filename.toLowerCase()).endsWith(".shp"))
{
String path = new File(filename).getParent() + "\\";
List newLayers = new ArrayList();
if (!CompatibleFeatures(layer))
newLayers = splitLayer(context, layer);
// charset fix [Matthias Scholz 12. Feb 2011]
Object charsetName = dsq.getDataSource().getProperties().get("charset");
if (charsetName != null) dp.set("charset", charsetName.toString());
(new ShapefileWriter()).write(layer.getFeatureCollectionWrapper(), dp);
for (int i = 0; i < newLayers.size(); i++)
{
Layer newLayer = (Layer) newLayers.get(i);
String newFileName = path + newLayer.getName() + ".shp";
HashMap properties = new HashMap();
properties.put(DataSource.COORDINATE_SYSTEM_KEY, "Unspecified");
properties.put(DataSource.FILE_KEY, newFileName);
DataSource dataSource = (DataSource) StandardReaderWriterFileDataSource.Shapefile.class.newInstance();
dataSource.setProperties(properties);
DataSourceQuery dataSourceQuery = new DataSourceQuery(dataSource, newLayer.getName(), null);
newLayer.setDataSourceQuery(dataSourceQuery).setFeatureCollectionModified(false);
dp.set("File", newFileName);
(new ShapefileWriter()).write(newLayer.getFeatureCollectionWrapper(), dp);
context.getWorkbenchFrame().getOutputFrame().addText(sSavedLayer + ": " + newLayer.getName());
}
return true;
}
if ((filename.toLowerCase()).endsWith(".jml"))
{
(new JMLWriter()).write(layer.getFeatureCollectionWrapper(), dp);
return true;
}
if ((filename.toLowerCase()).endsWith(".gml"))
{
(new GMLWriter()).write(layer.getFeatureCollectionWrapper(), dp);
return true;
}
if ((filename.toLowerCase()).endsWith(".fme"))
{
(new FMEGMLWriter()).write(layer.getFeatureCollectionWrapper(), dp);
return true;
}
if ((filename.toLowerCase()).endsWith(".wkt"))
{
(new WKTWriter()).write(layer.getFeatureCollectionWrapper(), dp);
return true;
}
context.getWorkbenchFrame().getOutputFrame().addText( sUnrecognizedFileType + " --- " + sCouldNotSaveLayer + ": " + layer.getName());
context.getWorkbenchFrame().warnUser(sErrorSeeOutputWindow);
return false;
}
catch (Exception e)
{
context.getWorkbenchFrame().warnUser(sErrorSeeOutputWindow);
context.getWorkbenchFrame().getOutputFrame().createNewDocument();
context.getWorkbenchFrame().getOutputFrame().addText("SaveDatasetsPlugIn:WriteLayer Exception:" + e.toString());
return false;
}
}
private boolean CompatibleFeatures(Layer layer)
{
BitSet bitSet = new BitSet();
FeatureCollectionWrapper featureCollection = layer.getFeatureCollectionWrapper();
List featureList = featureCollection.getFeatures();
for (Iterator i = featureList.iterator(); i.hasNext();)
bitSet = GeoUtils.setBit(bitSet, ((Feature) i.next()).getGeometry());
return (bitSet.cardinality() < 2);
}
private List splitLayer(PlugInContext context, Layer layer)
{
ArrayList newLayers = new ArrayList();
if (!CompatibleFeatures(layer))
{
ArrayList emptyFeatures = new ArrayList();
ArrayList pointFeatures = new ArrayList();
ArrayList lineFeatures = new ArrayList();
ArrayList polyFeatures = new ArrayList();
ArrayList groupFeatures = new ArrayList();
FeatureCollectionWrapper featureCollection = layer.getFeatureCollectionWrapper();
List featureList = featureCollection.getFeatures();
FeatureSchema featureSchema = layer.getFeatureCollectionWrapper().getFeatureSchema();
//first find and handle all empty geometries and GeometryCollections
for (Iterator i = featureList.iterator(); i.hasNext();)
{
Feature feature = (Feature) i.next();
Geometry geometry = feature.getGeometry();
if (geometry.isEmpty()) //going to delete it
emptyFeatures.add(feature);
else if ((geometry instanceof GeometryCollection) &&
(!(geometry instanceof MultiPoint)) &&
(!(geometry instanceof MultiLineString)) &&
(!(geometry instanceof MultiPolygon))) //mixed geometry; going to explode it
groupFeatures.add(feature);
}
for (int i = 0; i < emptyFeatures.size(); i++) //delete empty geometries
{
featureCollection.remove((Feature) emptyFeatures.get(i));
}
for (int i = 0; i < groupFeatures.size(); i++) //delete GeometryCollections
{
Feature feature = (Feature) groupFeatures.get(i);
GeometryCollection geometry = (GeometryCollection) feature.getGeometry();
explodeGeometryCollection(featureSchema, pointFeatures, lineFeatures, polyFeatures, geometry, feature);
featureCollection.remove(feature);
}
//now get new list of remaining features
featureCollection = layer.getFeatureCollectionWrapper();
featureList = layer.getFeatureCollectionWrapper().getFeatures();
BitSet layerBit = new BitSet();
if (featureList.size() > 0)
{
Geometry firstGeo = ((Feature) featureList.iterator().next()).getGeometry();
layerBit = GeoUtils.setBit(layerBit, firstGeo); //this is the layer type
}
//now add just the exploded features that belong on the the original layer
if (layerBit.get(GeoUtils.polyBit))
{
if (polyFeatures.size() > 0)
{
for (int i = 0; i < polyFeatures.size(); i++)
{
Feature feature = (Feature) polyFeatures.get(i);
featureCollection.add(feature);
}
polyFeatures.clear();
}
}
else if (layerBit.get(GeoUtils.lineBit))
{
if (lineFeatures.size() > 0)
{
for (int i = 0; i < lineFeatures.size(); i++)
{
Feature feature = (Feature) lineFeatures.get(i);
featureCollection.add(feature);
}
lineFeatures.clear();
}
}
else if (layerBit.get(GeoUtils.pointBit))
{
if (pointFeatures.size() > 0)
{
for (int i = 0; i < pointFeatures.size(); i++)
{
Feature feature = (Feature) pointFeatures.get(i);
featureCollection.add(feature);
}
pointFeatures.clear();
}
}
else //nothing left on layer; just pick a type for the layer
{
if (polyFeatures.size() > 0)
{
for (int i = 0; i < polyFeatures.size(); i++)
{
Feature feature = (Feature) polyFeatures.get(i);
featureCollection.add(feature);
}
polyFeatures.clear();
}
else if (lineFeatures.size() > 0)
{
for (int i = 0; i < lineFeatures.size(); i++)
{
Feature feature = (Feature) lineFeatures.get(i);
featureCollection.add(feature);
}
lineFeatures.clear();
}
else if (pointFeatures.size() > 0)
{
for (int i = 0; i < pointFeatures.size(); i++)
{
Feature feature = (Feature) pointFeatures.get(i);
featureCollection.add(feature);
}
pointFeatures.clear();
}
}
//at this point we have taken care of the GeometryCollections
//some part of them have been added to the original layer
//the rest of the features are in the array lists waiting
//to be added to the appropriate layers
featureCollection = layer.getFeatureCollectionWrapper();
featureList = layer.getFeatureCollectionWrapper().getFeatures();
layerBit = new BitSet();
if (featureList.size() > 0)
{
Geometry firstGeo = ((Feature) featureList.iterator().next()).getGeometry();
layerBit = GeoUtils.setBit(layerBit, firstGeo); //this is the layer type
}
Collection selectedCategories = context.getLayerNamePanel().getSelectedCategories();
for (Iterator i = featureList.iterator(); i.hasNext();)
{
Feature feature = (Feature) i.next();
Geometry geo = feature.getGeometry();
BitSet currFeatureBit = new BitSet();
currFeatureBit = GeoUtils.setBit(currFeatureBit, geo);
if (!layerBit.get(GeoUtils.pointBit) && currFeatureBit.get(GeoUtils.pointBit))
pointFeatures.add(feature);
if (!layerBit.get(GeoUtils.lineBit) && currFeatureBit.get(GeoUtils.lineBit))
lineFeatures.add(feature);
if (!layerBit.get(GeoUtils.polyBit) && currFeatureBit.get(GeoUtils.polyBit))
polyFeatures.add(feature);
}
if (pointFeatures.size() > 0)
{
Layer pointLayer = context.addLayer(selectedCategories.isEmpty()
? StandardCategoryNames.WORKING
: selectedCategories.iterator().next().toString(), layer.getName() + "_point",
new FeatureDataset(featureSchema));
FeatureCollectionWrapper pointFeatureCollection = pointLayer.getFeatureCollectionWrapper();
newLayers.add(pointLayer);
context.getWorkbenchFrame().getOutputFrame().addText(sNewLayerCreated + ": " + pointLayer.getName());
context.getWorkbenchFrame().warnUser(sNewLayerCreated + " - " + sWarningSeeOutputWindow);
for (int i = 0; i < pointFeatures.size(); i++)
{
Feature feature = (Feature) pointFeatures.get(i);
featureCollection.remove(feature);
pointFeatureCollection.add(feature);
}
}
if (lineFeatures.size() > 0)
{
Layer lineLayer = context.addLayer(selectedCategories.isEmpty()
? StandardCategoryNames.WORKING
: selectedCategories.iterator().next().toString(), layer.getName() + "_line",
new FeatureDataset(featureSchema));
FeatureCollectionWrapper lineFeatureCollection = lineLayer.getFeatureCollectionWrapper();
newLayers.add(lineLayer);
context.getWorkbenchFrame().getOutputFrame().addText(sNewLayerCreated + ": " + lineLayer.getName());
context.getWorkbenchFrame().warnUser(sNewLayerCreated + " - " + sErrorSeeOutputWindow);
for (int i = 0; i < lineFeatures.size(); i++)
{
Feature feature = (Feature) lineFeatures.get(i);
featureCollection.remove(feature);
lineFeatureCollection.add(feature);
}
}
if (polyFeatures.size() > 0)
{
Layer polyLayer = context.addLayer(selectedCategories.isEmpty()
? StandardCategoryNames.WORKING
: selectedCategories.iterator().next().toString(), layer.getName() + "_area",
new FeatureDataset(featureSchema));
FeatureCollectionWrapper polyFeatureCollection = polyLayer.getFeatureCollectionWrapper();
newLayers.add(polyLayer);
context.getWorkbenchFrame().getOutputFrame().addText(sNewLayerCreated + ": " + polyLayer.getName());
context.getWorkbenchFrame().warnUser(sNewLayerCreated + " - " + sErrorSeeOutputWindow);
for (int i = 0; i < polyFeatures.size(); i++)
{
Feature feature = (Feature) polyFeatures.get(i);
featureCollection.remove(feature);
polyFeatureCollection.add(feature);
}
}
}
return newLayers;
}
private void explodeGeometryCollection(FeatureSchema fs, ArrayList pointFeatures, ArrayList lineFeatures, ArrayList polyFeatures, GeometryCollection geometryCollection, Feature feature)
{
for (int i = 0; i < geometryCollection.getNumGeometries(); i++)
{
Geometry geometry = geometryCollection.getGeometryN(i);
if (geometry instanceof GeometryCollection)
{
explodeGeometryCollection(fs, pointFeatures, lineFeatures, polyFeatures, (GeometryCollection) geometry, feature);
}
else
{
//Feature newFeature = new BasicFeature(fs);
Feature newFeature = feature.clone(true);
newFeature.setGeometry(geometry);
BitSet featureBit = new BitSet();
featureBit = GeoUtils.setBit(featureBit, geometry);
if (featureBit.get(GeoUtils.pointBit)) pointFeatures.add(newFeature);
if (featureBit.get(GeoUtils.lineBit)) lineFeatures.add(newFeature);
if (featureBit.get(GeoUtils.polyBit)) polyFeatures.add(newFeature);
}
}
}
private void writeProjectionFile(PlugInContext context, Layer outputLayer)throws IOException, FileNotFoundException
{ //per LDB projection files only associated with .shp files; confirmed 8/16/05
DataSourceQuery dsqOut = outputLayer.getDataSourceQuery();
if (dsqOut != null) //file exists; not a new layer
{
String outputFileName = dsqOut.getDataSource().getProperties().get("File").toString();
if ((outputFileName.toLowerCase()).endsWith(".shp"))
{
String outputPrjFileName = "";
int pos = outputFileName.lastIndexOf('.');
outputPrjFileName = outputFileName.substring(0, pos) + ".prj";
if (!(new File(outputPrjFileName).exists()))
{ //loop through all layers to find a project file; then copy contents
List layerList = context.getLayerManager().getLayers();
for (Iterator i = layerList.iterator(); i.hasNext();)
{
Layer layer = (Layer) i.next();
DataSourceQuery dsq = layer.getDataSourceQuery();
if (dsq != null)
{
String inputFileName = dsq.getDataSource().getProperties().get("File").toString();
if ((inputFileName.toLowerCase()).endsWith(".shp"))
{
String inputPrjFileName = "";
pos = inputFileName.lastIndexOf('.');
inputPrjFileName = inputFileName.substring(0, pos) + ".prj";
if (new File(inputPrjFileName).exists())
{
List prjStr = FileUtil.getContents(inputPrjFileName);
try
{
FileUtil.setContents(outputPrjFileName, prjStr);
}
catch (IOException ex)
{
context.getWorkbenchFrame().getOutputFrame().addText(sCouldNotWrite + ": " + outputPrjFileName + " --- " + ex.getMessage());
}
break;
}
}
}
}
}
}
}
}
}