/// <summary> /// Creates a Metadata reference appropriate for the data source. /// </summary> /// <remarks> /// This method will guess the metadata Path, Type and Format based on Esri conventions /// and file existence. It is Async, because Iit will check the file system for a file /// and/or directory existance which will block, and could take significant time in unusual /// circumstances: missing drive, network connection problems, drive asleep, etc. This may /// need to check several different paths to ensure we do not miss existing metadata for a datasource. /// This method is only called by ThemeBuilder.cs when the user adds a new data source. /// </remarks> /// <param name="data">The theme's data source</param> /// <returns>a new Metadata object for a theme</returns> internal static async Task <Metadata> FromDataSourceAsync(ThemeData data) { Metadata newMetadata = new Metadata(); if (data == null) { return(newMetadata); } //Caution: Setting Path will clear the Type and Format, so set Path first. // General file based metadata // Includes layer files. if *.lyr.xml exists, it trumps the datasource metadata (for single datasource layers) if (data.Path != null && await MyFile.ExistsAsync(data.Path + ".xml")) { newMetadata.Path = data.Path + ".xml"; newMetadata.Type = MetadataType.FilePath; newMetadata.Format = MetadataFormat.Xml; return(newMetadata); } // General file based metadata // Includes file based raster data, LAS datasets, and others. if (data.DataSource != null && await MyFile.ExistsAsync(data.DataSource + ".xml")) { newMetadata.Path = data.DataSource + ".xml"; newMetadata.Type = MetadataType.FilePath; newMetadata.Format = MetadataFormat.Xml; return(newMetadata); } // Grids, TINs, and other directory based feature classes if (data.IsRasterBand && data.DataSource != null && await MyDirectory.ExistsAsync(data.DataSource)) { string metadataPath = System.IO.Path.Combine(data.DataSource, "metadata.xml"); if (await MyFile.ExistsAsync(metadataPath)) { newMetadata.Path = metadataPath; newMetadata.Type = MetadataType.FilePath; newMetadata.Format = MetadataFormat.Xml; } return(newMetadata); } // Shapefile if (data.IsShapefile) { string metadataPath = data.DataSource + ".shp.xml"; if (await MyFile.ExistsAsync(metadataPath)) { newMetadata.Path = metadataPath; newMetadata.Type = MetadataType.FilePath; newMetadata.Format = MetadataFormat.Xml; } return(newMetadata); } // ArcInfo Coverages if (data.IsCoverage && data.WorkspacePath != null && data.Container != null) { string coverageDir = System.IO.Path.Combine(data.WorkspacePath, data.Container); if (await MyDirectory.ExistsAsync(coverageDir)) { string metadataPath = System.IO.Path.Combine(coverageDir, "metadata.xml"); if (await MyFile.ExistsAsync(metadataPath)) { newMetadata.Path = metadataPath; newMetadata.Type = MetadataType.FilePath; newMetadata.Format = MetadataFormat.Xml; } return(newMetadata); } } // CAD if (data.IsCad && data.WorkspacePath != null && data.Container != null) { string cadFile = System.IO.Path.Combine(data.WorkspacePath, data.Container); if (await MyFile.ExistsAsync(cadFile)) { string metadataPath = cadFile + ".xml"; if (await MyFile.ExistsAsync(metadataPath)) { newMetadata.Path = metadataPath; newMetadata.Type = MetadataType.FilePath; newMetadata.Format = MetadataFormat.Xml; } return(newMetadata); } } // SDC - Smart Data Compression for ESRI Street Map and Sample datasets. if (data.IsSdc && data.WorkspacePath != null && data.Container != null) { string sdcFile = System.IO.Path.Combine(data.WorkspacePath, data.Container); if (await MyFile.ExistsAsync(sdcFile)) { string metadataPath = sdcFile + ".xml"; if (await MyFile.ExistsAsync(metadataPath)) { newMetadata.Path = metadataPath; newMetadata.Type = MetadataType.FilePath; newMetadata.Format = MetadataFormat.Xml; } return(newMetadata); } } // GeoDatabases - Metadata is not a separate XML file, it is internal to the database // For SDE datasets to work, the original connection file (*.sde) must be available // to all theme manager users, i.e. not in a local profile (the typical default location) if (data.IsInGeodatabase) { newMetadata.Path = data.DataSource; if (data.IsRasterBand) { newMetadata.Path = data.DataSource?.Replace("\\" + data.DataSourceName, ""); } newMetadata.Type = MetadataType.EsriDataPath; newMetadata.Format = MetadataFormat.Xml; return(newMetadata); } // File based Raster band metadata // DataSource will contain the Band Name, while metadata will not // Needs to be done after geodatabase, else we miss rasterbands in geodatabases if (data.IsRasterBand && data.WorkspacePath != null && data.Container != null) { string rasterName = System.IO.Path.Combine(data.WorkspacePath, data.Container); string metadataPath = rasterName + ".xml"; if (await MyFile.ExistsAsync(metadataPath)) { newMetadata.Path = metadataPath; newMetadata.Type = MetadataType.FilePath; newMetadata.Format = MetadataFormat.Xml; } return(newMetadata); } // Esri Web services if ((data.IsEsriMapService || data.IsEsriImageService) && data.DataSource != null) { newMetadata.Path = Regex.Replace(data.DataSource, "/arcgis/services/", "/arcgis/rest/services/", RegexOptions.IgnoreCase); newMetadata.Path += "/info/metadata"; newMetadata.Type = MetadataType.Url; newMetadata.Format = MetadataFormat.Xml; return(newMetadata); } if (data.IsEsriFeatureService && data.WorkspacePath != null) { newMetadata.Path = Regex.Replace(data.WorkspacePath, "/arcgis/services/", "/arcgis/rest/services/", RegexOptions.IgnoreCase); newMetadata.Path += "/info/metadata"; newMetadata.Type = MetadataType.Url; newMetadata.Format = MetadataFormat.Xml; return(newMetadata); } // Other web services may have metadata, but we are not ready to support them // LiDAR data tiles (.las) are not data sources that ArcGIS manages directly (*.lasD files are handled above) // Raster functions have no permanent disk representation except a layer file // Do not provide a default, it was usually wrong, and it will be better to return nothing Debug.Print($"Metadata not found for Data.Path:{data.Path}, Data.DataSource:{data.DataSource}, Data.DataSetType:{data.DataSetType}"); return(newMetadata); }