private static void LoadDataSources(CanvasDocument app, DirectoryReader directory, ErrorContainer errors) { var tableDefs = new Dictionary <string, DataSourceDefinition>(); app._dataSourceReferences = new Dictionary <string, LocalDatabaseReferenceJson>(); foreach (var file in directory.EnumerateFiles(DataSourcePackageDir, "*.json")) { var tableDef = file.ToObject <DataSourceDefinition>(); tableDefs.Add(tableDef.EntityName, tableDef); if (tableDef.DatasetName == null) { continue; } if (!app._dataSourceReferences.TryGetValue(tableDef.DatasetName, out var localDatabaseReferenceJson)) { localDatabaseReferenceJson = new LocalDatabaseReferenceJson() { dataSources = new Dictionary <string, LocalDatabaseReferenceDataSource>(), ExtensionData = tableDef.ExtensionData, instanceUrl = tableDef.InstanceUrl }; app._dataSourceReferences.Add(tableDef.DatasetName, localDatabaseReferenceJson); } if (localDatabaseReferenceJson.instanceUrl != tableDef.InstanceUrl) { // Generate an error, dataset defs have diverged in a way that shouldn't be possible // Each dataset has one instanceurl errors.ValidationError($"For file {file._relativeName}, the dataset {tableDef.DatasetName} has multiple instanceurls"); throw new DocumentException(); } localDatabaseReferenceJson.dataSources.Add(tableDef.EntityName, tableDef.LocalReferenceDSJson); } // key is filename, value is stringified xml var xmlDefs = new Dictionary <string, string>(); foreach (var file in directory.EnumerateFiles(WadlPackageDir, "*.xml")) { xmlDefs.Add(Path.GetFileNameWithoutExtension(file._relativeName), file.GetContents()); } // key is filename, value is stringified json var swaggerDefs = new Dictionary <string, string>(); foreach (var file in directory.EnumerateFiles(SwaggerPackageDir, "*.json")) { swaggerDefs.Add(Path.GetFileNameWithoutExtension(file._relativeName), file.GetContents()); } foreach (var file in directory.EnumerateFiles(DataSourcesDir, "*")) { var dataSources = file.ToObject <List <DataSourceEntry> >(); foreach (var ds in dataSources) { if (tableDefs.TryGetValue(ds.RelatedEntityName ?? ds.Name, out var definition)) { switch (ds.Type) { case "NativeCDSDataSourceInfo": ds.DatasetName = definition.DatasetName; ds.TableDefinition = JsonSerializer.Serialize(definition.TableDefinition, Utility._jsonOpts); break; case "ConnectedDataSourceInfo": ds.DataEntityMetadataJson = definition.DataEntityMetadataJson; ds.TableName = definition.TableName; break; case "OptionSetInfo": ds.DatasetName = ds.DatasetName != string.Empty? definition.DatasetName : null; break; case "ServiceInfo": case "ViewInfo": default: break; } } else if (ds.Type == "ServiceInfo") { var foundXML = xmlDefs.TryGetValue(Path.GetFileNameWithoutExtension(file._relativeName), out string xmlDef); var foundJson = swaggerDefs.TryGetValue(Path.GetFileNameWithoutExtension(file._relativeName), out string swaggerDef); if (!foundXML && !foundJson) { errors.ValidationError($"No matching wadl or swagger def for {file._relativeName}"); throw new DocumentException(); } ds.WadlMetadata = new WadlDefinition() { WadlXml = xmlDef, SwaggerJson = swaggerDef }; } app.AddDataSourceForLoad(ds); } } }
// Full fidelity read-write public static CanvasDocument LoadFromSource(string directory2, ErrorContainer errors) { if (File.Exists(directory2)) { if (directory2.EndsWith(".msapp", StringComparison.OrdinalIgnoreCase)) { throw new ArgumentException($"Must point to a source directory, not an msapp file ({directory2}"); } } if (!Directory.Exists(directory2)) { throw new InvalidOperationException($"No directory {directory2}"); } var dir = new DirectoryReader(directory2); var app = new CanvasDocument(); // Do the manifest check (and version check) first. // MAnifest lives in top-level directory. foreach (var file in dir.EnumerateFiles("", "*.json")) { switch (file.Kind) { case FileKind.CanvasManifest: var manifest = file.ToObject <CanvasManifestJson>(); if (manifest.FormatVersion != CurrentSourceVersion) { errors.FormatNotSupported($"This tool only supports {CurrentSourceVersion}, the manifest version is {manifest.FormatVersion}"); throw new DocumentException(); } app._properties = manifest.Properties; app._header = manifest.Header; app._publishInfo = manifest.PublishInfo; app._screenOrder = manifest.ScreenOrder; break; case FileKind.Templates: foreach (var kvp in file.ToObject <List <KeyValuePair <string, CombinedTemplateState> > >()) { app._templateStore.AddTemplate(kvp.Key, kvp.Value); } break; case FileKind.ComponentReferences: var refs = file.ToObject <ComponentDependencyInfo[]>(); app._libraryReferences = refs; break; } } if (app._header == null) { // Manifest not found. errors.FormatNotSupported($"Can't find CanvasManifest.json file - is sources an old version?"); throw new DocumentException(); } // Load template files, recreate References/templates.json LoadTemplateFiles(errors, app, Path.Combine(directory2, PackagesDir), out var templateDefaults); foreach (var file in dir.EnumerateFiles(AssetsDir)) { if (file._relativeName == "Resources.json") { app._resourcesJson = file.ToObject <ResourcesJson>(); continue; } app.AddAssetFile(file.ToFileEntry()); } // var root = Path.Combine(directory, OtherDir); foreach (var file in dir.EnumerateFiles(OtherDir)) { // Special files like Header / Properties switch (file.Kind) { default: // Track any unrecognized files so we can save back. app.AddFile(file.ToFileEntry()); break; case FileKind.Entropy: app._entropy = file.ToObject <Entropy>(); break; case FileKind.Checksum: app._checksum = file.ToObject <ChecksumJson>(); break; case FileKind.Themes: app._themes = file.ToObject <ThemesJson>(); break; case FileKind.Header: case FileKind.Properties: throw new NotSupportedException($"Old format"); case FileKind.ComponentSrc: case FileKind.ControlSrc: // Shouldn't find any here - were explicit in source throw new InvalidOperationException($"Unexpected source file: " + file._relativeName); } } // each loose file in '\other' app.GetLogoFile(); LoadDataSources(app, dir, errors); LoadSourceFiles(app, dir, templateDefaults, errors); foreach (var file in dir.EnumerateFiles(ConnectionDir)) { // Special files like Header / Properties switch (file.Kind) { case FileKind.Connections: app._connections = file.ToObject <IDictionary <string, ConnectionJson> >(); break; } } // Defaults. // - DynamicTypes.Json, Resources.Json , Templates.Json - could all be empty // - Themes.json- default to app.OnLoadComplete(errors); return(app); }
private static IEnumerable <DirectoryReader.Entry> EnumerateComponentDirs( DirectoryReader directory, string pattern) { return(directory.EnumerateFiles(ComponentCodeDir, pattern).Concat( directory.EnumerateFiles(ComponentPackageDir, pattern))); }