示例#1
0
        private void RepairWithDataset(IDataLayer2 dataLayer, Moves.GisDataset oldDataset, Moves.GisDataset newDataset, AlertForm alert)
        {
            // This routine, can only repair workspace path, and dataset name.
            // The workspace type and data type must be the same.
            // This can be checked with the CSV verifier. Violations will be ignored in the CSV loader
            if (oldDataset.DatasourceType != newDataset.DatasourceType ||
                oldDataset.WorkspaceProgId != newDataset.WorkspaceProgId)
            {
                return;
            }
            var helper = (IDataSourceHelperLayer) new DataSourceHelper();

            if (oldDataset.DatasourceName == newDataset.DatasourceName)
            {
                helper.FindAndReplaceWorkspaceNamePath((ILayer)dataLayer, oldDataset.Workspace.Folder, newDataset.Workspace.Folder, false);
            }
            else
            {
                // I can't find a way to simply change the name of the dataset in a layer.
                // To set the data source of a layer I need to first open the data source (using the newDataset properties)
                // I can then use the Name (as IName) of the data source to fix the layer.
                IDataset dataset = TryOpenDataset(newDataset);
                if (dataset == null)
                {
                    alert.Text        = @"Error";
                    alert.msgBox.Text = $"Map Fixer is unable to repair the layer {((ILayer2)dataLayer).Name}. " +
                                        "Use the 'Set Data Source button' on the Source tab of the layer properties dialog to " +
                                        $"set the data source to {newDataset.Workspace.Folder}\\{newDataset.DatasourceName}";
                    alert.ShowDialog(new WindowWrapper(new IntPtr(ArcMap.Application.hWnd)));
                    return;
                }
                helper.ReplaceName((ILayer)dataLayer, dataset.FullName, false);
            }
        }
示例#2
0
        private IDataset TryOpenDataset(Moves.GisDataset dataset, IWorkspace workspace, IDatasetName datasetName)
        {
            if (dataset.DatasourceType.AsDatasetType() == null)
            {
                return(null);
            }
            var datasetType = dataset.DatasourceType.AsDatasetType().Value;

            if (datasetType == esriDatasetType.esriDTFeatureClass)
            {
                try
                {
                    IFeatureWorkspace featureWorkspace = (IFeatureWorkspace)workspace;
                    IFeatureClass     featureClass     = featureWorkspace.OpenFeatureClass(datasetName.Name);
                    return((IDataset)featureClass);
                }
                catch (Exception)
                {
                    return(null);
                }
            }
            // For opening raster data see https://desktop.arcgis.com/en/arcobjects/10.5/net/webframe.htm#62937a09-b1c5-47d7-a1ac-f7a5daab3c89.htm
            if (datasetType == esriDatasetType.esriDTRasterDataset)
            {
                try
                {
                    // ReSharper disable once SuspiciousTypeConversion.Global
                    // Raster Workspace Class is in ESRI.ArcGIS.DataSourcesRaster
                    IRasterWorkspace2 rasterWorkspace = (IRasterWorkspace2)workspace;
                    IRasterDataset    rasterDataset   = rasterWorkspace.OpenRasterDataset(datasetName.Name);
                    // ReSharper disable once SuspiciousTypeConversion.Global
                    // Three possible co-classes FunctionRasterDataset, RasterBand, RasterDataset are in ESRI.ArcGIS.DataSourcesRaster
                    return((IDataset)rasterDataset);
                }
                catch (Exception)
                {
                    return(null);
                }
            }
            if (datasetType == esriDatasetType.esriDTRasterCatalog || datasetType == esriDatasetType.esriDTMosaicDataset)
            {
                try
                {
                    IRasterWorkspaceEx rasterWorkspace = (IRasterWorkspaceEx)workspace;
                    IRasterDataset     rasterDataset   = rasterWorkspace.OpenRasterDataset(datasetName.Name);
                    // ReSharper disable once SuspiciousTypeConversion.Global
                    // Three possible co-classes FunctionRasterDataset, RasterBand, RasterDataset are in ESRI.ArcGIS.DataSourcesRaster
                    return((IDataset)rasterDataset);
                }
                catch (Exception)
                {
                    return(null);
                }
            }
            //TODO: Open additional types of data sources, support at least all in theme Manager

            return(null);
        }
示例#3
0
        private IDataset TryOpenDataset(Moves.GisDataset dataset)
        {
            IWorkspaceName workspaceName = new WorkspaceNameClass()
            {
                WorkspaceFactoryProgID = dataset.WorkspaceProgId, // i.e. "esriDataSourcesGDB.AccessWorkspaceFactory";
                PathName = dataset.Workspace.Folder
            };
            IWorkspace workspace;

            try
            {
                workspace = workspaceName.WorkspaceFactory.Open(null, 0);
            }
            catch (Exception)
            {
                // This may fail for any number of reasons, bad input (progID or path), network or filesystem error permissions, ...
                return(null);
            }
            if (workspace == null)
            {
                return(null);
            }
            if (dataset.DatasourceType.AsDatasetType() == null)
            {
                return(null);
            }
            var          datasetNames = workspace.DatasetNames[dataset.DatasourceType.AsDatasetType().Value];
            IDatasetName datasetName;

            while ((datasetName = datasetNames.Next()) != null)
            {
                if (datasetName.ToString() == dataset.DatasourceType && string.Compare(datasetName.Name, dataset.DatasourceName, StringComparison.OrdinalIgnoreCase) == 0)
                {
                    return(TryOpenDataset(dataset, workspace, datasetName));
                }
            }
            return(null);
        }
示例#4
0
        private static void RepairWithDataset(Layer layer, Moves.GisDataset oldDataset, Moves.GisDataset newDataset)
        {
            // This routine, can only repair workspace path, and dataset name.
            // The workspace type and data type must be the same.
            // This is checked with a warning in the CSV verifier.
            // Violations are silently ignored in the CSV loader so this code should never see it
            // however if it escapes, it will also be ignored here as well.
            if (oldDataset.DatasourceType != newDataset.DatasourceType ||
                oldDataset.WorkspaceProgId != newDataset.WorkspaceProgId)
            {
                return;
            }
            if (oldDataset.DatasourceName == newDataset.DatasourceName)
            {
                try
                {
                    // This threw an underlying COM exception with a test case with valid input, so wrap in the try for safely
                    layer.FindAndReplaceWorkspacePath(oldDataset.Workspace.Folder, newDataset.Workspace.Folder, false);
                }
                catch
                {
                    var title = @"Map Fixer Error";
                    var msg   = $"Map Fixer failed to repair the layer {layer.Name}. " +
                                "Use the 'Set Data Source button' on the Source tab of the layer properties dialog to " +
                                $"set the data source to {newDataset.Workspace.Folder}\\{newDataset.DatasourceName}";
                    MessageBox.Show(msg, title, System.Windows.MessageBoxButton.OK,
                                    System.Windows.MessageBoxImage.Error);
                }
            }
            else
            {
                if (Enum.TryParse(newDataset.DatasourceType, out esriDatasetType dataType) &&
                    Enum.TryParse(newDataset.WorkspaceProgId, out WorkspaceFactory workspaceFactory))
                {
                    //TODO: Replace the existing data connection with the same sub class of CIMDataConnection,
                    //      Need support from the moves database and GetDataset() below to support this.
                    //      Currently GetDataset() will ignore all but CIMStandardDataConnection, so we can
                    //      safely assume that is what we need to create
                    string workspaceConnection = "DATABASE=" + newDataset.Workspace.Folder;
                    CIMStandardDataConnection updatedDataConnection = new CIMStandardDataConnection()
                    {
                        WorkspaceConnectionString = workspaceConnection,
                        WorkspaceFactory          = workspaceFactory,
                        Dataset     = newDataset.DatasourceName,
                        DatasetType = dataType
                    };
                    layer.SetDataConnection(updatedDataConnection);
                }
                else
                {
                    var title = @"Map Fixer Error";
                    var msg   = $"Map Fixer is unable to repair the layer {layer.Name}. " +
                                "Use the 'Set Data Source button' on the Source tab of the layer properties dialog to " +
                                $"set the data source to {newDataset.Workspace.Folder}\\{newDataset.DatasourceName}";
                    MessageBox.Show(msg, title, System.Windows.MessageBoxButton.OK,
                                    System.Windows.MessageBoxImage.Error);
                }
            }

            // Alternative implementation
            // switch on newDataset.WorkspaceProgId, newDataset.DatasourceType
            // uri = Uri(Path.Join(newDataset.Workspace.Folder, newDataset.DatasourceName)
            // connection = <Type>ConnectionPath(uri, newDataset.DatasourceType)
            // var dataset = OpenDataset<Type>(new <Type>DataSource(connection))
            // i.e. file geodatabase DatasourceType = .fgdb //ArcGIS.Core.CIM.esriDatasetType, ArcGIS.Core.CIM.WorkspaceFactory
            // var connection = new Geodatabase(new FileGeodatabaseConnectionPath(new Uri(@"newDataset.Workspace.Folder")))
            // var dataset = connection.OpenDataset<FeatureDataset>(newDataset.DatasourceName)
            // for .raster and .shape
            // var connection = new FileSystemDataStore(new FileSystemConnectionPath(new Uri(@"newDataset.Workspace.Folder")))
            // var dataset = connection.OpenDataset<BasicRasterDataset>(newDataset.DatasourceName)
        }
示例#5
0
        public void FixMap(Moves moves)
        {
            var brokenDataSources = GetBrokenDataSources();

            // We do not need to do anything if there was nothing to fix
            if (brokenDataSources.Count == 0)
            {
                return;
            }
            var alert               = new AlertForm();
            var selector            = new SelectionForm();
            var autoFixesApplied    = 0;
            var unFixableLayers     = 0;
            var intentionallyBroken = 0;

            foreach (var item in brokenDataSources)
            {
                var mapIndex = item.Key;
                foreach (IDataLayer2 dataLayer in item.Value)
                {
                    var layerName = dataLayer is IDataset dataset ? dataset.Name : ((ILayer2)dataLayer).Name;
                    Moves.GisDataset oldDataset    = GetDataset(dataLayer);
                    Moves.Solution?  maybeSolution = moves.GetSolution(oldDataset);
                    if (maybeSolution == null)
                    {
                        unFixableLayers += 1;
                        continue;
                    }
                    Moves.Solution solution = maybeSolution.Value;
                    if (solution.NewDataset != null && solution.ReplacementDataset == null &&
                        solution.ReplacementLayerFilePath == null && solution.Remarks == null)
                    {
                        // This is the optimal action.
                        // The user is not prompted, since there is no good reason for a user not to click OK.
                        // The user will be warned that layers have been fixed, and they can choose to not save the changes.
                        autoFixesApplied += 1;
                        RepairWithDataset(dataLayer, oldDataset, solution.NewDataset.Value, alert);
                    }
                    else
                    {
                        selector.LayerName = layerName;
                        //selector.GisDataset = oldDataset;
                        selector.Solution = solution;
                        selector.ShowDialog(new WindowWrapper(new IntPtr(ArcMap.Application.hWnd)));
                        if (selector.UseLayerFile)
                        {
                            RepairWithLayerFile(mapIndex, dataLayer, selector.LayerFile, selector.KeepBrokenLayer, alert);
                            if (selector.KeepBrokenLayer)
                            {
                                intentionallyBroken += 1;
                            }
                        }
                        else if (selector.UseDataset && selector.Dataset.HasValue)
                        {
                            RepairWithDataset(dataLayer, oldDataset, selector.Dataset.Value, alert);
                        }
                        else
                        {
                            intentionallyBroken += 1;
                        }
                    }
                }
            }

            // Refresh TOC
            ArcMap.Document.UpdateContents();        //update the TOC
            ArcMap.Document.ActivatedView.Refresh(); // refresh the view

            // Print a Summary
            brokenDataSources = GetBrokenDataSources();
            // Some unfixable layers may actually have been corrected by fixing the Mosaic Dataset Layer
            // Limit unfixable to no more than the actual number of broken layers
            unFixableLayers = Math.Min(unFixableLayers, brokenDataSources.Count);
            if (autoFixesApplied > 0 || unFixableLayers > 0 || brokenDataSources.Count > intentionallyBroken)
            {
                string msg = "";
                if (autoFixesApplied > 0)
                {
                    msg +=
                        $"{autoFixesApplied} broken layers were automatically fixed based on the new locations of known data sources. " +
                        "Close the document without saving if this is not what you want.";
                }
                if (autoFixesApplied > 0 && (unFixableLayers > 0 || brokenDataSources.Count > 0))
                {
                    msg += "\n\n";
                }
                if (unFixableLayers > 0)
                {
                    msg +=
                        $"{unFixableLayers} broken layers could not be fixed; breakage is not due to changes on the PDS (X drive).";
                }
                if (unFixableLayers < brokenDataSources.Count - intentionallyBroken)
                {
                    // We know that brokenDataSources.Count must be >= unFixableLayers, therefore some of the fixes need fixing
                    if (unFixableLayers > 0)
                    {
                        msg += "\n\n";
                    }
                    msg += "Additional fixes are possible and needed.  Please save, close and reopen your map.";
                }
                alert.Text        = @"Map Fixer Summary";
                alert.msgBox.Text = msg;
                alert.ShowDialog(new WindowWrapper(new IntPtr(ArcMap.Application.hWnd)));
            }
        }