private void createFeature_Click(object sender, EventArgs e)
        {
            if (elements.Items.Count == 0)
            {
                MessageBox.Show("Must create elements.");
            }
            else
            {
                DynamicForm f = new DynamicForm("Configure feature...", DynamicForm.CloseButtons.OkCancel);
                f.AddTextBox("Feature name:", null, 50, "name");
                if (f.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    string name = f.GetValue <string>("name").Trim();
                    if (name == "")
                    {
                        MessageBox.Show("Invalid name:  must not be blank.");
                    }
                    else
                    {
                        Shapefile shapefile = null;
                        try
                        {
                            shapefile = Shapefile.Create(name, (elements.Items[0] as Geometry).SRID, Shapefile.ShapefileType.Feature);
                            ShapefileGeometry.Create(shapefile, elements.Items.Cast <Geometry>().Select(g => new Tuple <Geometry, DateTime>(g, DateTime.MinValue)).ToList());
                            MessageBox.Show("Shapefile \"" + name + "\" created.");
                            elements.Items.Clear();
                            points.Items.Clear();
                        }
                        catch (Exception ex)
                        {
                            Console.Out.WriteLine("Failed to create shapefile:  " + ex.Message);

                            try { shapefile.Delete(); }
                            catch (Exception ex2) { Console.Out.WriteLine("Failed to delete failed shapefile:  " + ex2.Message); }
                        }
                    }
                }
            }
        }
        public override void Import()
        {
            base.Import();

            Console.Out.WriteLine("Importing shapefile from \"" + Path + "\"...");

            try
            {
                Dictionary<string, string> importOptionValue = new Dictionary<string, string>();
                string importOptionsPath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(Path), System.IO.Path.GetFileNameWithoutExtension(Path) + ".att");
                if (File.Exists(importOptionsPath))
                    foreach (string line in File.ReadLines(importOptionsPath))
                    {
                        string[] parts = line.Split('=');
                        importOptionValue.Add(parts[0].Trim(), parts[1].Trim());
                    }

                if (_sourceSRID > 0 && _targetSRID > 0)
                    importOptionValue["reprojection"] = _sourceSRID + ":" + _targetSRID;

                if (!string.IsNullOrWhiteSpace(Name))
                    importOptionValue["name"] = Name;

                List<string> neededValues = new List<string>();
                if (!importOptionValue.ContainsKey("reprojection") || string.IsNullOrWhiteSpace(importOptionValue["reprojection"])) neededValues.Add("reprojection");
                if (!importOptionValue.ContainsKey("name") || string.IsNullOrWhiteSpace(importOptionValue["name"])) neededValues.Add("name");
                if (neededValues.Count > 0)
                {
                    if (_shapefileInfoRetriever == null)
                        throw new Exception("Missing the following shapefile options, and no information retriever was present:  " + neededValues.Concatenate(","));
                    else
                        _shapefileInfoRetriever.GetShapefileInfo(Path, neededValues, importOptionValue);
                }

                string missingValues = neededValues.Where(v => !importOptionValue.ContainsKey(v) || string.IsNullOrWhiteSpace(importOptionValue[v])).Concatenate(", ");
                if (missingValues != "")
                    throw new Exception("Failed to provide needed values for shapefile import:  " + missingValues);

                string reprojection = importOptionValue["reprojection"];
                Match reprojectionMatch = new Regex("(?<from>[0-9]+):(?<to>[0-9]+)").Match(reprojection);
                if (!reprojectionMatch.Success)
                    throw new Exception("Invalid shapefile reprojection \"" + reprojection + "\". Must be in 1234:1234 format.");

                int fromSRID = int.Parse(reprojectionMatch.Groups["from"].Value);
                int toSRID = int.Parse(reprojectionMatch.Groups["to"].Value);
                if (fromSRID == toSRID)
                    reprojection = fromSRID.ToString();

                string name = importOptionValue["name"];
                if (string.IsNullOrWhiteSpace(name))
                    throw new Exception("Empty name given for shapefile \"" + Path + "\".");

                Name = name; // to make sure names retrieved from *.att files get back to the object and ultimately back to the DB

                File.WriteAllText(importOptionsPath, "reprojection=" + fromSRID + ":" + toSRID + Environment.NewLine +
                                                     "name=" + name);

                Shapefile.ShapefileType type;
                if (this is FeatureShapefileImporter)
                    type = Shapefile.ShapefileType.Feature;
                else if (this is AreaShapefileImporter)
                    type = Shapefile.ShapefileType.Area;
                else if (this is IncidentShapefileImporter)
                    type = Shapefile.ShapefileType.Incident;
                else
                    throw new NotImplementedException("Unrecognized shapefile importer type:  " + GetType());

                _importedShapefile = Shapefile.Create(name, toSRID, type);

                string sql;
                string error;
                using (Process process = new Process())
                {
                    process.StartInfo.FileName = Configuration.Shp2PgsqlPath;
                    process.StartInfo.Arguments = "-I -g " + ShapefileGeometry.Columns.Geometry + " -s " + reprojection + " \"" + Path + "\" " + _importedShapefile.GeometryTable;
                    process.StartInfo.CreateNoWindow = true;
                    process.StartInfo.UseShellExecute = false;
                    process.StartInfo.RedirectStandardError = true;
                    process.StartInfo.RedirectStandardOutput = true;
                    process.Start();

                    Console.Out.WriteLine("Converting shapefile \"" + name + "\".");

                    sql = process.StandardOutput.ReadToEnd().Replace("BEGIN;", "").Replace("COMMIT;", "");
                    error = process.StandardError.ReadToEnd().Trim().Replace(Environment.NewLine, "; ").Replace("\n", "; ");

                    process.WaitForExit();
                }

                Console.Out.WriteLine(error);

                DB.Connection.ExecuteNonQuery(sql);

                // if there's an id column already, rename it native_id
                if (DB.Connection.GetColumnNames(_importedShapefile.GeometryTable).Select(c => c.ToLower()).Contains("id"))
                {
                    DB.Connection.ExecuteNonQuery("ALTER TABLE " + _importedShapefile.GeometryTable + " DROP COLUMN IF EXISTS native_id;" +
                                                  "ALTER TABLE " + _importedShapefile.GeometryTable + " RENAME COLUMN id TO native_id");
                }

                // rename primary key column to ShapefileGeometry.Columns.Id
                List<string> primaryKeyColumns = DB.Connection.GetPrimaryKeyColumns(_importedShapefile.GeometryTable).ToList();
                if (primaryKeyColumns.Count == 1)
                {
                    if (primaryKeyColumns[0] != ShapefileGeometry.Columns.Id)
                    {
                        DB.Connection.ExecuteNonQuery("ALTER TABLE " + _importedShapefile.GeometryTable + " DROP COLUMN IF EXISTS " + ShapefileGeometry.Columns.Id + ";" +
                                                      "ALTER TABLE " + _importedShapefile.GeometryTable + " RENAME COLUMN " + primaryKeyColumns[0] + " TO " + ShapefileGeometry.Columns.Id);
                    }
                }
                else
                    throw new Exception("Imported shapefile database does not contain a single primary key column.");

                Console.Out.WriteLine("Shapefile import succeeded.");
            }
            catch (Exception ex)
            {
                if (_importedShapefile != null)
                {
                    try { _importedShapefile.Delete(); }
                    catch (Exception ex2) { Console.Out.WriteLine("Failed to delete shapefile:  " + ex2.Message); }
                }

                _importedShapefile = null;

                throw new Exception("Shapefile import failed:  " + ex.Message);
            }
        }
        public override void Import()
        {
            base.Import();

            Console.Out.WriteLine("Importing shapefile from \"" + Path + "\"...");

            try
            {
                Dictionary <string, string> importOptionValue = new Dictionary <string, string>();
                string importOptionsPath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(Path), System.IO.Path.GetFileNameWithoutExtension(Path) + ".att");
                if (File.Exists(importOptionsPath))
                {
                    foreach (string line in File.ReadLines(importOptionsPath))
                    {
                        string[] parts = line.Split('=');
                        importOptionValue.Add(parts[0].Trim(), parts[1].Trim());
                    }
                }

                if (_sourceSRID > 0 && _targetSRID > 0)
                {
                    importOptionValue["reprojection"] = _sourceSRID + ":" + _targetSRID;
                }

                if (!string.IsNullOrWhiteSpace(Name))
                {
                    importOptionValue["name"] = Name;
                }

                List <string> neededValues = new List <string>();
                if (!importOptionValue.ContainsKey("reprojection") || string.IsNullOrWhiteSpace(importOptionValue["reprojection"]))
                {
                    neededValues.Add("reprojection");
                }
                if (!importOptionValue.ContainsKey("name") || string.IsNullOrWhiteSpace(importOptionValue["name"]))
                {
                    neededValues.Add("name");
                }
                if (neededValues.Count > 0)
                {
                    if (_shapefileInfoRetriever == null)
                    {
                        throw new Exception("Missing the following shapefile options, and no information retriever was present:  " + neededValues.Concatenate(","));
                    }
                    else
                    {
                        _shapefileInfoRetriever.GetShapefileInfo(Path, neededValues, importOptionValue);
                    }
                }

                string missingValues = neededValues.Where(v => !importOptionValue.ContainsKey(v) || string.IsNullOrWhiteSpace(importOptionValue[v])).Concatenate(", ");
                if (missingValues != "")
                {
                    throw new Exception("Failed to provide needed values for shapefile import:  " + missingValues);
                }

                string reprojection      = importOptionValue["reprojection"];
                Match  reprojectionMatch = new Regex("(?<from>[0-9]+):(?<to>[0-9]+)").Match(reprojection);
                if (!reprojectionMatch.Success)
                {
                    throw new Exception("Invalid shapefile reprojection \"" + reprojection + "\". Must be in 1234:1234 format.");
                }

                int fromSRID = int.Parse(reprojectionMatch.Groups["from"].Value);
                int toSRID   = int.Parse(reprojectionMatch.Groups["to"].Value);
                if (fromSRID == toSRID)
                {
                    reprojection = fromSRID.ToString();
                }

                string name = importOptionValue["name"];
                if (string.IsNullOrWhiteSpace(name))
                {
                    throw new Exception("Empty name given for shapefile \"" + Path + "\".");
                }

                Name = name; // to make sure names retrieved from *.att files get back to the object and ultimately back to the DB

                File.WriteAllText(importOptionsPath, "reprojection=" + fromSRID + ":" + toSRID + Environment.NewLine +
                                  "name=" + name);

                Shapefile.ShapefileType type;
                if (this is FeatureShapefileImporter)
                {
                    type = Shapefile.ShapefileType.Feature;
                }
                else if (this is AreaShapefileImporter)
                {
                    type = Shapefile.ShapefileType.Area;
                }
                else if (this is IncidentShapefileImporter)
                {
                    type = Shapefile.ShapefileType.Incident;
                }
                else
                {
                    throw new NotImplementedException("Unrecognized shapefile importer type:  " + GetType());
                }

                _importedShapefile = Shapefile.Create(name, toSRID, type);

                string sql;
                string error;
                using (Process process = new Process())
                {
                    process.StartInfo.FileName               = Configuration.Shp2PgsqlPath;
                    process.StartInfo.Arguments              = "-I -g " + ShapefileGeometry.Columns.Geometry + " -s " + reprojection + " \"" + Path + "\" " + _importedShapefile.GeometryTable;
                    process.StartInfo.CreateNoWindow         = true;
                    process.StartInfo.UseShellExecute        = false;
                    process.StartInfo.RedirectStandardError  = true;
                    process.StartInfo.RedirectStandardOutput = true;
                    process.Start();

                    Console.Out.WriteLine("Converting shapefile \"" + name + "\".");

                    sql   = process.StandardOutput.ReadToEnd().Replace("BEGIN;", "").Replace("COMMIT;", "");
                    error = process.StandardError.ReadToEnd().Trim().Replace(Environment.NewLine, "; ").Replace("\n", "; ");

                    process.WaitForExit();
                }

                Console.Out.WriteLine(error);

                DB.Connection.ExecuteNonQuery(sql);

                // if there's an id column already, rename it native_id
                if (DB.Connection.GetColumnNames(_importedShapefile.GeometryTable).Select(c => c.ToLower()).Contains("id"))
                {
                    DB.Connection.ExecuteNonQuery("ALTER TABLE " + _importedShapefile.GeometryTable + " DROP COLUMN IF EXISTS native_id;" +
                                                  "ALTER TABLE " + _importedShapefile.GeometryTable + " RENAME COLUMN id TO native_id");
                }

                // rename primary key column to ShapefileGeometry.Columns.Id
                List <string> primaryKeyColumns = DB.Connection.GetPrimaryKeyColumns(_importedShapefile.GeometryTable).ToList();
                if (primaryKeyColumns.Count == 1)
                {
                    if (primaryKeyColumns[0] != ShapefileGeometry.Columns.Id)
                    {
                        DB.Connection.ExecuteNonQuery("ALTER TABLE " + _importedShapefile.GeometryTable + " DROP COLUMN IF EXISTS " + ShapefileGeometry.Columns.Id + ";" +
                                                      "ALTER TABLE " + _importedShapefile.GeometryTable + " RENAME COLUMN " + primaryKeyColumns[0] + " TO " + ShapefileGeometry.Columns.Id);
                    }
                }
                else
                {
                    throw new Exception("Imported shapefile database does not contain a single primary key column.");
                }

                Console.Out.WriteLine("Shapefile import succeeded.");
            }
            catch (Exception ex)
            {
                if (_importedShapefile != null)
                {
                    try { _importedShapefile.Delete(); }
                    catch (Exception ex2) { Console.Out.WriteLine("Failed to delete shapefile:  " + ex2.Message); }
                }

                _importedShapefile = null;

                throw new Exception("Shapefile import failed:  " + ex.Message);
            }
        }