public void CopySpatialContexts()
        {
            List <SpatialContextInfo> contexts   = new List <SpatialContextInfo>();
            FdoConnection             srcConn    = _connMgr.GetConnection(_view.SourceConnectionName);
            FdoConnection             targetConn = _connMgr.GetConnection(_view.SelectedTargetConnectionName);

            using (FdoFeatureService service = srcConn.CreateFeatureService())
            {
                foreach (string ctxName in _view.SpatialContexts)
                {
                    SpatialContextInfo sc = service.GetSpatialContext(ctxName);
                    if (sc != null)
                    {
                        contexts.Add(sc);
                    }
                }
            }

            if (contexts.Count == 0)
            {
                _view.ShowMessage(null, ResourceService.GetString("MSG_NO_SPATIAL_CONTEXTS_COPIED"));
                return;
            }

            ExpressUtility.CopyAllSpatialContexts(contexts, targetConn, _view.Overwrite);
            _view.ShowMessage(null, ResourceService.GetString("MSG_SPATIAL_CONTEXTS_COPIED"));
            _view.Close();
        }
        /// <summary>
        /// Initializes this instance.
        /// </summary>
        protected override void Initialize()
        {
            SendMessage("Creating target data source");
            if (!ExpressUtility.CreateFlatFileDataSource(_outputFile))
            {
                throw new FdoETLException(ResourceUtil.GetStringFormatted("ERR_CANNOT_CREATE_DATA_FILE", _outputFile));
            }

            _outConn = ExpressUtility.CreateFlatFileConnection(_outputFile);
            _outConn.Open();

            ClassDefinition cd = _table.CreateClassDefinition(true);

            using (FdoFeatureService service = _outConn.CreateFeatureService())
            {
                SendMessage("Applying schema to target");
                FeatureSchema schema = new FeatureSchema("Schema1", "Default schema");
                schema.Classes.Add(cd);
                service.ApplySchema(schema);
            }

            SendMessage("Copying any attached spatial contexts");
            ExpressUtility.CopyAllSpatialContexts(_table.SpatialContexts, _outConn, true);

            Register(new FdoFeatureTableInputOperation(_table));
            Register(new FdoOutputOperation(_outConn, cd.Name));
        }
            public override IEnumerable <FdoRow> Execute(IEnumerable <FdoRow> rows)
            {
                if (_counter < 1) //Shouldn't be reentrant, but just play it safe.
                {
                    /*
                     * Check and apply the following rules for all geometry properties to be created
                     *
                     * Target supports multiple spatial contexts:
                     * -------------------------------------------
                     * If there is no spatial contexts of the specified (source) name. Create a copy of the source spatial context.
                     * If there is a spatial context of the same name, using the same WKT. Do nothing
                     * If there is a spatial context of the same name, but using a different WKT. Create a new spatial context using the source WKT, but use a different name.
                     *
                     * Target only supports one spatial context:
                     * If there is no spatial context already. Create a copy of the source spatial context.
                     * If there is a spatial context of the same WKT. Change the association to match the name of this spatial context.
                     * If there is a spatial context not using the source WKT. Change the association to match the name of this spatial context. This may not be ideal, but there is no other option at this point.
                     *
                     * The regular schema compatibility fixes will handle the other properties
                     */
                    bool targetSupportsMultipleSpatialContexts      = _target.Capability.GetBooleanCapability(CapabilityType.FdoCapabilityType_SupportsMultipleSpatialContexts);
                    List <SpatialContextInfo> targetSpatialContexts = null;
                    List <SpatialContextInfo> sourceSpatialContexts = null;

                    if (typeof(CreateTargetClassFromSource).IsAssignableFrom(_opts.PreCopyTargetModifier.GetType()))
                    {
                        using (var tsvc = _target.CreateFeatureService())
                            using (var ssvc = _source.CreateFeatureService())
                            {
                                targetSpatialContexts = new List <SpatialContextInfo>(tsvc.GetSpatialContexts());
                                sourceSpatialContexts = new List <SpatialContextInfo>(ssvc.GetSpatialContexts());
                                var ct = (CreateTargetClassFromSource)_opts.PreCopyTargetModifier;

                                Info("Getting current schema from target");
                                var schema = tsvc.GetSchemaByName(_opts.TargetSchema);
                                if (schema.Classes.IndexOf(ct.Name) >= 0)
                                {
                                    Info("Class " + _opts.TargetSchema + ":" + ct.Name + " already exists. Nothing to do here");
                                }
                                else
                                {
                                    List <SpatialContextInfo> createScs = new List <SpatialContextInfo>();

                                    var cls = ssvc.GetClassByName(ct.Schema, ct.Name);
                                    Info("Creating a cloned copy of source class " + ct.Schema + ":" + ct.Name);

                                    var cloned     = FdoSchemaUtil.CloneClass(cls);
                                    var propList   = new List <string>(_opts.CheckSourceProperties);
                                    var removeList = new List <string>();
                                    foreach (PropertyDefinition prop in cloned.Properties)
                                    {
                                        string propName = prop.Name;
                                        if (!propList.Contains(propName))
                                        {
                                            removeList.Add(propName);
                                        }
                                    }

                                    if (removeList.Count > 0)
                                    {
                                        Info("Removing " + removeList.Count + " unused properties from cloned class");
                                        var props = cloned.Properties;
                                        var ids   = cloned.IdentityProperties;
                                        foreach (var name in removeList)
                                        {
                                            if (ids.Contains(name))
                                            {
                                                ids.RemoveAt(ids.IndexOf(name));
                                            }

                                            if (props.Contains(name))
                                            {
                                                props.RemoveAt(props.IndexOf(name));
                                            }
                                        }
                                        Info(removeList.Count + " unused properties removed");
                                    }

                                    foreach (var prop in ct.PropertiesToCreate)
                                    {
                                        Info("Adding property to cloned class: " + prop.Name);
                                        PropertyDefinition clonedProp = FdoSchemaUtil.CloneProperty(prop);
                                        cloned.Properties.Add(clonedProp);
                                    }

                                    //Add an auto-generated identity property if none exist
                                    if (cloned.IdentityProperties.Count == 0)
                                    {
                                        var id = new DataPropertyDefinition("FID", "Auto-Generated Feature Id");
                                        id.IsAutoGenerated = true;
                                        id.Nullable        = false;
                                        //This may not be valid for target connection, but FdoFeatureService
                                        //will fix this for us.
                                        id.DataType = DataType.DataType_Int32;

                                        cloned.Properties.Add(id);
                                        cloned.IdentityProperties.Add(id);

                                        Info("Adding an auto-generated id (FID) to this cloned class");
                                    }

                                    Info("Checking this class for incompatibilities");
                                    IncompatibleClass ic;
                                    if (!tsvc.CanApplyClass(cloned, out ic))
                                    {
                                        Info("Altering this class to become compatible with target connection");
                                        cloned = tsvc.AlterClassDefinition(cloned, ic);
                                        Info("Class successfully altered");
                                    }

                                    Info("Checking if any spatial contexts need to be created and/or references modified");
                                    foreach (PropertyDefinition pd in cloned.Properties)
                                    {
                                        if (pd.PropertyType == PropertyType.PropertyType_GeometricProperty)
                                        {
                                            AddSpatialContextsToCreate(targetSupportsMultipleSpatialContexts, targetSpatialContexts, sourceSpatialContexts, createScs, (GeometricPropertyDefinition)pd);
                                        }
                                    }

                                    //We have to create spatial contexts first before applying the schema
                                    if (createScs.Count > 0)
                                    {
                                        //The ones we create should be unique so no overwriting needed
                                        ExpressUtility.CopyAllSpatialContexts(createScs, _target, false);

                                        foreach (var sc in createScs)
                                        {
                                            Info("Created spatial context: " + sc.Name);
                                        }
                                    }

                                    Info("Adding cloned class to target schema");
                                    schema.Classes.Add(cloned);
                                    Info("Applying schema back to target connection");
                                    tsvc.ApplySchema(schema);
                                    Info("Updated schema applied to target connection");
                                }
                            }
                    }
                    else if (typeof(UpdateTargetClass).IsAssignableFrom(_opts.PreCopyTargetModifier.GetType()))
                    {
                        var ut = (UpdateTargetClass)_opts.PreCopyTargetModifier;
                        using (var tsvc = _target.CreateFeatureService())
                            using (var ssvc = _source.CreateFeatureService())
                            {
                                targetSpatialContexts = new List <SpatialContextInfo>(tsvc.GetSpatialContexts());
                                sourceSpatialContexts = new List <SpatialContextInfo>(ssvc.GetSpatialContexts());
                                var schema = tsvc.GetSchemaByName(_opts.TargetSchema);
                                var cidx   = schema.Classes.IndexOf(ut.Name);
                                if (cidx < 0)
                                {
                                    throw new InvalidOperationException("Target class to be updated " + _opts.TargetSchema + ":" + ut.Name + " not found");
                                }
                                else
                                {
                                    List <SpatialContextInfo> createScs = new List <SpatialContextInfo>();

                                    var cls = schema.Classes[cidx];
                                    foreach (var prop in ut.PropertiesToCreate)
                                    {
                                        if (cls.Properties.IndexOf(prop.Name) < 0)
                                        {
                                            Info("Adding property to class: " + prop.Name);
                                            var clonedProp = FdoSchemaUtil.CloneProperty(prop);
                                            if (clonedProp.PropertyType == PropertyType.PropertyType_GeometricProperty)
                                            {
                                                AddSpatialContextsToCreate(targetSupportsMultipleSpatialContexts, targetSpatialContexts, sourceSpatialContexts, createScs, (GeometricPropertyDefinition)clonedProp);
                                            }
                                            cls.Properties.Add(clonedProp);
                                        }
                                        else
                                        {
                                            Info("Skipping property " + prop.Name + " because it already exists");
                                        }
                                    }

                                    //We have to create spatial contexts first before applying the schema
                                    if (createScs.Count > 0)
                                    {
                                        //The ones we create should be unique so no overwriting needed
                                        ExpressUtility.CopyAllSpatialContexts(createScs, _target, false);

                                        foreach (var sc in createScs)
                                        {
                                            Info("Created spatial context: " + sc.Name);
                                        }
                                    }

                                    Info("Applying modified schema " + schema.Name + " to target connection");
                                    tsvc.ApplySchema(schema);
                                    Info("Modified schema " + schema.Name + " applied to target connection");
                                }
                            }
                    }

                    _counter++;
                }
                return(rows);
            }
        public override int Execute()
        {
            CommandStatus retCode;

            FdoConnection srcConn  = new FdoConnection(_srcProvider, _srcConnStr);
            FdoConnection destConn = null;

            //Directory given, assume SHP
            if (Directory.Exists(_destPath))
            {
                destConn = new FdoConnection("OSGeo.SHP", "DefaultFileLocation=" + _destPath);
            }
            else
            {
                if (ExpressUtility.CreateFlatFileDataSource(_destPath))
                {
                    destConn = ExpressUtility.CreateFlatFileConnection(_destPath);
                }
                else
                {
                    throw new FdoException("Could not create data source: " + _destPath);
                }
            }

            try
            {
                srcConn.Open();
                destConn.Open();

                string srcName = "SOURCE";
                string dstName = "TARGET";

                FdoBulkCopyOptions options = new FdoBulkCopyOptions();
                options.RegisterConnection(srcName, srcConn);
                options.RegisterConnection(dstName, destConn);
                using (FdoFeatureService srcService = srcConn.CreateFeatureService())
                    using (FdoFeatureService destService = destConn.CreateFeatureService())
                    {
                        //See if spatial context needs to be copied to target
                        if (!string.IsNullOrEmpty(_srcSpatialContext))
                        {
                            SpatialContextInfo srcCtx = srcService.GetSpatialContext(_srcSpatialContext);
                            if (srcCtx != null)
                            {
                                Console.WriteLine("Copying spatial context: " + srcCtx.Name);
                                ExpressUtility.CopyAllSpatialContexts(new SpatialContextInfo[] { srcCtx }, destConn, true);
                            }
                        }
                        else
                        {
                            //Copy all
                            ExpressUtility.CopyAllSpatialContexts(srcConn, destConn, true);
                        }

                        FeatureSchema srcSchema = null;
                        //See if partial class list is needed
                        if (_srcClasses.Count > 0)
                        {
                            WriteLine("Checking if partial schema discovery is supported: " + srcService.SupportsPartialSchemaDiscovery());

                            srcSchema = srcService.PartialDescribeSchema(_srcSchema, _srcClasses);
                        }
                        else //Full copy
                        {
                            WriteLine("No classes specified, reading full source schema");
                            srcSchema = srcService.GetSchemaByName(_srcSchema);
                        }

                        if (srcSchema == null)
                        {
                            WriteError("Could not find source schema: " + _srcSchema);
                            retCode = CommandStatus.E_FAIL_SCHEMA_NOT_FOUND;
                        }
                        else
                        {
                            WriteLine("Checking source schema for incompatibilities");
                            FeatureSchema      targetSchema = null;
                            IncompatibleSchema incSchema;
                            if (destService.CanApplySchema(srcSchema, out incSchema))
                            {
                                int clsCount = srcSchema.Classes.Count;
                                WriteLine("Applying source schema (containing " + clsCount + " classes) to target");
                                destService.ApplySchema(srcSchema, null, true);
                                targetSchema = srcSchema;
                            }
                            else
                            {
                                WriteWarning("Incompatibilities were detected in source schema. Applying a modified version to target");
                                FeatureSchema fixedSchema = destService.AlterSchema(srcSchema, incSchema);
                                int           clsCount    = fixedSchema.Classes.Count;
                                WriteLine("Applying modified source schema (containing " + clsCount + " classes) to target");
                                destService.ApplySchema(fixedSchema, null, true);
                                targetSchema = fixedSchema;
                            }

                            //Now set class copy options
                            foreach (ClassDefinition cd in srcSchema.Classes)
                            {
                                FdoClassCopyOptions copt = new FdoClassCopyOptions(srcName, dstName, srcSchema.Name, cd.Name, targetSchema.Name, cd.Name);
                                copt.FlattenGeometries = _flatten;
                                options.AddClassCopyOption(copt);
                            }

                            if (_flatten)
                            {
                                WriteWarning("The switch -flatten has been defined. Geometries that are copied will have any Z or M coordinates removed");
                            }

                            FdoBulkCopy copy = new FdoBulkCopy(options);
                            copy.ProcessMessage   += new MessageEventHandler(OnMessage);
                            copy.ProcessCompleted += new EventHandler(OnCompleted);
                            Console.WriteLine("Executing bulk copy");
                            copy.Execute();
                            List <Exception> errors = new List <Exception>(copy.GetAllErrors());
                            if (errors.Count > 0)
                            {
                                string file = GenerateLogFileName("bcp-error-");
                                LogErrors(errors, file);
                                base.WriteError("Errors were encountered during bulk copy.");
                                retCode = CommandStatus.E_FAIL_BULK_COPY_WITH_ERRORS;
                            }
                            else
                            {
                                retCode = CommandStatus.E_OK;
                            }
                            retCode = CommandStatus.E_OK;
                        }
                    }
            }
            catch (Exception ex)
            {
                WriteException(ex);
                retCode = CommandStatus.E_FAIL_UNKNOWN;
            }
            finally
            {
                srcConn.Dispose();
                destConn.Dispose();
            }
            return((int)retCode);
        }