public TmNode(TmNodeType nodeType, string name, TmNode parent, ThemeData data, Metadata metadata, string desc, DateTime? pubDate) { _type = nodeType; _name = name; Parent = parent; _pubDate = pubDate.HasValue ? pubDate.Value : DefaultPubDate; //_readonly = (Parent == null) ? false : Parent._readonly; _description = desc; // Always create a data and Metadata object, else data binding in properties form won't work. _data = data ?? new ThemeData(); _data.PropertyChanged += Data_PropertyChanged; Metadata = metadata ?? new Metadata(); Metadata.PropertyChanged += Metadata_PropertyChanged; if (_type == TmNodeType.ThemeList) { Author = new ThemeListAuthor(); _status = ThemeListStatus.Created; _dataStore = TryToGetDataStore(); // TryToGetDataStore() will set _readonly for theme ThemeList = this; } }
//Load From MDB, SubTheme, overloads public ThemeNode(string name, TmNode parent, ThemeData data, Metadata metadata, string desc, DateTime? pubDate) : base(name, parent, metadata, desc) { IsInitialized = false; Data = data; PubDate = pubDate.HasValue ? pubDate.Value : DefaultPubDate; //Age is not a saved property, so calling the setter will not flag the node as edited Age = CalculateAge(); IsInitialized = true; }
private static void BuildThemeDataForLayer(ThemeData data, IGisLayer layer) { data.DataSource = layer.DataSource; data.WorkspacePath = layer.WorkspacePath; data.WorkspaceProgId = layer.WorkspaceProgId; data.WorkspaceType = layer.WorkspaceType; data.Container = layer.Container; data.ContainerType = layer.ContainerType; data.DataSourceName = layer.DataSourceName; data.DataSetName = layer.DataSetName; data.DataSetType = layer.DataSetType; }
/// <summary> /// Updates the Path, Type and Format based on a new data source /// </summary> /// <remarks> /// This is called when the user changes the data source of a theme either by editing the path /// directly, or by reloading the theme. It does not load the content or validate the properties. /// This method will not throw any exceptions. /// This should be a fast non-blocking method, but it isn't quite, see the docs on FromDataSource() /// for details on why. /// This method is required because WinForm binding is difficult to manage if an object is replaced /// by a new one. It is much easier to update the existing bound object. /// </remarks> /// <param name="data">The theme's data source</param> internal async Task UpdateWithDataSourceAsync(ThemeData data) { Metadata newMetadata = await FromDataSourceAsync(data); if (Path != null && newMetadata.Path == null) { // This item has a non-standard metadata path (set manually), do not delete it. return; } Path = newMetadata.Path; Type = newMetadata.Type; Format = newMetadata.Format; }
private static async Task BuildSubThemeForLayerAsync(TmNode node, IGisLayer subLayer) { ThemeData data = new ThemeData(null, subLayer.DataType); if (subLayer.IsGroup) { TmNode newNode = new TmNode(TmNodeType.Theme, subLayer.Name, node, data, null, null, null); node.Add(newNode); await BuildSubThemesForGroupLayerAsync(newNode, subLayer); } else { BuildThemeDataForLayer(data, subLayer); Metadata md = await Metadata.FromDataSourceAsync(data); TmNode newNode = new TmNode(TmNodeType.Theme, subLayer.Name, node, data, md, null, null); node.Add(newNode); } }
private static void BuildSubThemeForLayer(ThemeNode node, ILayer subLayer) { if (subLayer is GroupLayer) { SubThemeNode newNode = new SubThemeNode(subLayer.Name, node, new ThemeData(null, "Group Layer", null), null, null, null); node.Add(newNode); BuildSubThemesForGroupLayer(newNode, subLayer); } else { string dataType = LayerUtilities.GetLayerDescriptionFromLayer(subLayer); ThemeData data = new ThemeData(null, dataType, null); BuildThemeDataForLayer(data, subLayer); Metadata md = Metadata.Find(data); TmNode newNode = new SubThemeNode(subLayer.Name, node, data, md, null, null); node.Add(newNode); } }
internal static Meta ExpectedMetadataProperties(ThemeData data) { var newMeta = new Meta { Path=null, Type = MetadataType.Undefined, Format= MetadataFormat.Undefined }; if (data == null) return newMeta; newMeta.Type = MetadataType.FilePath; newMeta.Format = MetadataFormat.Xml; //general file based metadata if (data.Path != null && File.Exists(data.Path + ".xml")) { newMeta.Path = data.Path + ".xml"; return newMeta; } if (data.DataSource != null && File.Exists(data.DataSource + ".xml")) { newMeta.Path = data.DataSource + ".xml"; return newMeta; } //grids & tins if (data.DataSource != null //&& data.WorkspacePath != null && Directory.Exists(data.DataSource)) { string metapath = System.IO.Path.Combine(data.DataSource, "metadata.xml"); if (File.Exists(metapath)) { newMeta.Path = metapath; return newMeta; } } //shapefile if (data.IsShapefile) { string metapath = data.DataSource + ".shp.xml"; if (File.Exists(metapath)) { newMeta.Path = metapath; return newMeta; } } //coverages if (data.IsCoverage && data.WorkspacePath != null && data.Container != null) { string coverageDir = System.IO.Path.Combine(data.WorkspacePath, data.Container); if (Directory.Exists(coverageDir)) { string metapath = System.IO.Path.Combine(coverageDir, "metadata.xml"); if (File.Exists(metapath)) { newMeta.Path = metapath; return newMeta; } } } //CAD if (data.IsCad && data.WorkspacePath != null && data.Container != null) { string cadFile = System.IO.Path.Combine(data.WorkspacePath, data.Container); if (File.Exists(cadFile)) { string metapath = cadFile + ".xml"; if (File.Exists(metapath)) { newMeta.Path = metapath; return newMeta; } } } newMeta.Type = MetadataType.EsriDataPath; if (data.IsInGeodatabase && !data.IsLayerFile) { newMeta.Path = data.DataSource; return newMeta; } if (data.IsLayerFile && !data.IsGroupLayerFile) { newMeta.Path = data.DataSource; return newMeta; } //FIXME - does not work for web services ??? newMeta.Type = MetadataType.Undefined; newMeta.Format = MetadataFormat.Undefined; return newMeta; }
internal void Repair(ThemeData data) { //FIXME - this is a redundant load/validate/scan going on. Meta myNewProps = ExpectedMetadataProperties(data); if (myNewProps.Path == null) return; //exception or error ??? Type = myNewProps.Type; Format = myNewProps.Format; Path = myNewProps.Path; //will revalidation only if path changes Validate(); }
internal static Metadata Find(ThemeData data) { if (data == null) return null; Meta myProps = ExpectedMetadataProperties(data); var metadata = new Metadata(myProps.Path, myProps.Type, myProps.Format); if (metadata.Validate()) return metadata; return null; }
// FIXME - the following would be nice to have, but I don't have // workable code, so they are not used // //internal bool IsThemeListFile //{ // get // { // return false; // } //} #region XML Serialize public static ThemeData Load(XElement xele) { if (xele == null) throw new ArgumentNullException("xele"); if (xele.Name != "data") throw new ArgumentException("Invalid Xelement"); ThemeData data = new ThemeData( xele.Value, (string)xele.Attribute("type"), (string)xele.Attribute("format"), (string)xele.Attribute("version"), (string)xele.Attribute("datasource"), (string)xele.Attribute("workspace"), (string)xele.Attribute("workspacetype"), (string)xele.Attribute("workspaceprogid"), (string)xele.Attribute("container"), (string)xele.Attribute("containertype"), (string)xele.Attribute("datasourcename"), (string)xele.Attribute("datasetname"), (string)xele.Attribute("datasettype") ); return data; }
//Load from MDB, ThemeBuilder, overloads public SubThemeNode(string name, TmNode parent, ThemeData data, Metadata metadata, string desc, DateTime? pubDate) : base(name, parent, data, metadata, desc, pubDate) { }
internal static Metadata Find(ThemeData data) { if (data == null) return null; meta myProps = ExpectedMetadataProperties(data); Metadata metadata = new Metadata(myProps.path, myProps.type, myProps.format); if (metadata != null && metadata.Validate()) return metadata; return null; }
private static void BuildThemeDataForLayer(ThemeData data, ILayer layer) { // Can be called on any layer type, but it will not get sub layer information // and a lot of info will be lacking if this is not a data layer //LayerUtilities.GetLayerDescriptionFromLayer(layer); if (LayerUtilities.HasDataSetName(layer)) { data.DataSource = GetDataSourceFullNameFromLayer(layer); data.WorkspacePath = LayerUtilities.GetWorkspacePathFromLayer(layer); data.WorkspaceProgId = LayerUtilities.GetWorkspaceProgIDFromLayer(layer); data.WorkspaceType = LayerUtilities.GetWorkspaceTypeFromLayer(layer); data.Container = LayerUtilities.GetDataSourceContainerFromLayer(layer); data.ContainerType = LayerUtilities.GetDataSourceContainerTypeFromLayer(layer); data.DataSourceName = LayerUtilities.GetDataSourceNameFromLayer(layer); data.DataSetName = LayerUtilities.GetDataSetNameFromLayer(layer); data.DataSetType = LayerUtilities.GetDataSetTypeFromLayer(layer); } else if (LayerUtilities.HasAGSServerObjectName(layer)) { data.DataSource = LayerUtilities.GetURLFromAGSLayer(layer); data.DataSourceName = LayerUtilities.GetNameFromAGSLayer(layer); data.DataSetName = data.DataSourceName; data.DataSetType = LayerUtilities.GetTypeFromAGSLayer(layer); data.WorkspacePath = null; data.WorkspaceProgId = null; data.WorkspaceType = null; data.Container = null; data.ContainerType = null; } else if (LayerUtilities.HasIMSServiceDescription(layer)) { data.DataSource = LayerUtilities.GetURLFromIMSLayer(layer); data.DataSourceName = LayerUtilities.GetNameFromIMSLayer(layer); data.DataSetName = data.DataSourceName; data.DataSetType = LayerUtilities.GetTypeFromIMSLayer(layer); data.WorkspacePath = null; data.WorkspaceProgId = null; data.WorkspaceType = null; data.Container = null; data.ContainerType = null; } else if (LayerUtilities.HasWMSConnectionName(layer)) { data.DataSource = LayerUtilities.GetURLFromWMSLayer(layer); data.DataSourceName = data.DataSource; data.DataSetName = data.DataSource; data.DataSetType = LayerUtilities.GetAllPropertiesFromWMSLayer(layer); data.WorkspacePath = null; data.WorkspaceProgId = null; data.WorkspaceType = null; data.Container = null; data.ContainerType = null; } else if (LayerUtilities.HasDataSourceName(layer)) { data.DataSource = LayerUtilities.GetDataSourceName(layer); data.DataSourceName = data.DataSource; data.DataSetName = data.DataSource; data.DataSetType = data.DataSource; data.WorkspacePath = null; data.WorkspaceProgId = null; data.WorkspaceType = null; data.Container = null; data.ContainerType = null; } else { data.DataSource = "!Error, Unable to determine data source type"; data.WorkspacePath = null; data.WorkspaceProgId = null; data.WorkspaceType = null; data.Container = null; data.ContainerType = null; data.DataSourceName = null; data.DataSetName = null; data.DataSetType = null; } if (string.IsNullOrEmpty(data.DataSource)) data.DataSource = "!Error - Data source not found"; }
/// <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); }