private static void LoadSourceFiles(CanvasDocument app, DirectoryReader directory, Dictionary <string, ControlTemplate> templateDefaults, ErrorContainer errors) { foreach (var file in directory.EnumerateFiles(EditorStateDir, "*.json")) { if (!file._relativeName.EndsWith(".editorstate.json")) { errors.FormatNotSupported($"Unexpected file present in {EditorStateDir}"); throw new DocumentException(); } // Json peer to a .pa file. var controlExtraData = file.ToObject <Dictionary <string, ControlState> >(); var topParentName = file._relativeName.Replace(".editorstate.json", ""); foreach (var control in controlExtraData) { control.Value.TopParentName = topParentName; if (!app._editorStateStore.TryAddControl(control.Value)) { // Can't have duplicate control names. // This might happen due to a bad merge. errors.EditorStateError(file.SourceSpan, $"Control '{control.Value.Name}' is already defined."); } } } // For now, the Themes file lives in CodeDir as a json file // We'd like to make this .pa.yaml as well eventually foreach (var file in directory.EnumerateFiles(CodeDir, "*.json", searchSubdirectories: false)) { if (Path.GetFileName(file._relativeName) == "Themes.json") { app._themes = file.ToObject <ThemesJson>(); } } foreach (var file in directory.EnumerateFiles(CodeDir, "*.pa.yaml", searchSubdirectories: false)) { AddControl(app, file._relativeName, false, file.GetContents(), errors); } foreach (var file in EnumerateComponentDirs(directory, "*.pa.yaml")) { AddControl(app, file._relativeName, true, file.GetContents(), errors); } foreach (var file in directory.EnumerateFiles(TestDir, "*.pa.yaml")) { AddControl(app, file._relativeName, false, file.GetContents(), errors); } foreach (var file in EnumerateComponentDirs(directory, "*.json")) { var componentTemplate = file.ToObject <CombinedTemplateState>(); app._templateStore.AddTemplate(componentTemplate.ComponentManifest.Name, componentTemplate); } }
// 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 <Dictionary <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()); } foreach (var file in dir.EnumerateFiles(EntropyDir)) { switch (file.Kind) { case FileKind.Entropy: app._entropy = file.ToObject <Entropy>(); break; case FileKind.AppCheckerResult: app._appCheckerResultJson = file.ToObject <AppCheckerResultJson>(); break; case FileKind.Checksum: app._checksum = file.ToObject <ChecksumJson>(); app._checksum.ClientBuildDetails = _buildVerJson; break; default: errors.GenericWarning($"Unexpected file in Entropy, discarding"); break; } } foreach (var file in dir.EnumerateFiles(OtherDir)) { // Special files like Header / Properties switch (file.Kind) { case FileKind.Unknown: // Track any unrecognized files so we can save back. app.AddFile(file.ToFileEntry()); break; default: // Shouldn't find anything else not unknown in here, but just ignore them for now errors.GenericWarning($"Unexpected file in Other, discarding"); break; } } // 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 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 "ViewInfo": if (definition != null) { RestoreViewName(ds, definition.DatasetName); } break; case "ServiceInfo": 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) { ds.WadlMetadata = new WadlDefinition() { WadlXml = xmlDef, SwaggerJson = swaggerDef }; } } app.AddDataSourceForLoad(ds); } } }
private static IEnumerable <DirectoryReader.Entry> EnumerateComponentDirs( DirectoryReader directory, string pattern) { return(directory.EnumerateFiles(ComponentCodeDir, pattern).Concat( directory.EnumerateFiles(ComponentPackageDir, pattern))); }
// Full fidelity read-write public static CanvasDocument LoadFromSource(string directory2, ErrorContainer errors) { if (File.Exists(directory2)) { if (directory2.EndsWith(".msapp", StringComparison.OrdinalIgnoreCase)) { errors.BadParameter($"Must point to a source directory, not an msapp file ({directory2}"); } } Utilities.VerifyDirectoryExists(errors, directory2); if (errors.HasErrors) { return(null); } var dir = new DirectoryReader(directory2); var app = new CanvasDocument(); string appInsightsInstumentationKey = null; // 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 <Dictionary <string, CombinedTemplateState> >()) { app._templateStore.AddTemplate(kvp.Key, kvp.Value); } break; case FileKind.ComponentReferences: var refs = file.ToObject <ComponentDependencyInfo[]>(); app._libraryReferences = refs; break; case FileKind.AppInsightsKey: var appInsights = file.ToObject <AppInsightsKeyJson>(); appInsightsInstumentationKey = appInsights.InstrumentationKey; break; } } if (appInsightsInstumentationKey != null) { app._properties.InstrumentationKey = appInsightsInstumentationKey; } 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(EntropyDir)) { switch (file.Kind) { case FileKind.Entropy: app._entropy = file.ToObject <Entropy>(); break; case FileKind.AppCheckerResult: app._appCheckerResultJson = file.ToObject <AppCheckerResultJson>(); break; case FileKind.Checksum: app._checksum = file.ToObject <ChecksumJson>(); app._checksum.ClientBuildDetails = _buildVerJson; break; default: errors.GenericWarning($"Unexpected file in Entropy, discarding"); break; } } // The resource entries for sample data is sharded into individual json files. // Add each of these entries back into Resrouces.json var resources = new List <ResourceJson>(); app._resourcesJson = new ResourcesJson() { Resources = new ResourceJson[0] }; foreach (var file in dir.EnumerateFiles(AssetsDir, "*", false)) { var fileEntry = file.ToFileEntry(); if (fileEntry.Name.GetExtension() == ".json") { // If its a json file then this must be one of the sharded files from Resources.json resources.Add(file.ToObject <ResourceJson>()); } } // Add the resources from sharded files to _resourcesJson.Resources if (resources.Count > 0) { app._resourcesJson.Resources = resources.ToArray(); } // We have processed all the json files in Assets directory, now interate through all tge files to add the asset files. foreach (var file in dir.EnumerateFiles(AssetsDir)) { // Skip adding the json files which were created to contain the information for duplicate asset files. // The name of the such json files is of the format - <assetFileName>.<assetFileExtension>.json (eg. close_1.jpg.json) var fileName = file._relativeName; var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileName); // Check if the original extension was .json and the remaining file name has still got an extension, // Then this is an additional file that was created to contain information for duplicate assets. if (Path.HasExtension(fileNameWithoutExtension) && Path.GetExtension(fileName) == ".json") { var localAssetInfoJson = file.ToObject <LocalAssetInfoJson>(); app._localAssetInfoJson.Add(localAssetInfoJson.NewFileName, localAssetInfoJson); } // Add non json files to _assetFiles else if (Path.GetExtension(fileName) != ".json") { app.AddAssetFile(file.ToFileEntry()); } } app.GetLogoFile(); // Add the entries for local assets back to resrouces.json TranformResourceJson.AddLocalAssetEntriesToResourceJson(app); foreach (var file in dir.EnumerateFiles(OtherDir)) { // Special files like Header / Properties switch (file.Kind) { case FileKind.Unknown: // Track any unrecognized files so we can save back. app.AddFile(file.ToFileEntry()); break; default: // Shouldn't find anything else not unknown in here, but just ignore them for now errors.GenericWarning($"Unexpected file in Other, discarding"); break; } } // each loose file in '\other' 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 void LoadSourceFiles(CanvasDocument app, DirectoryReader directory, Dictionary <string, ControlTemplate> templateDefaults, ErrorContainer errors) { foreach (var file in directory.EnumerateFiles(EditorStateDir, "*.json")) { if (!file._relativeName.EndsWith(".editorstate.json")) { errors.FormatNotSupported($"Unexpected file present in {EditorStateDir}"); throw new DocumentException(); } // Json peer to a .pa file. ControlTreeState editorState = file.ToObject <ControlTreeState>(); if (editorState.ControlStates == null) { ApplyV24BackCompat(editorState, file); } foreach (var control in editorState.ControlStates) { control.Value.TopParentName = editorState.TopParentName; if (!app._editorStateStore.TryAddControl(control.Value)) { // Can't have duplicate control names. // This might happen due to a bad merge. errors.EditorStateError(file.SourceSpan, $"Control '{control.Value.Name}' is already defined."); } } } // For now, the Themes file lives in CodeDir as a json file // We'd like to make this .fx.yaml as well eventually foreach (var file in directory.EnumerateFiles(CodeDir, "*.json", searchSubdirectories: false)) { if (Path.GetFileName(file._relativeName) == "Themes.json") { app._themes = file.ToObject <ThemesJson>(); } } foreach (var file in EnumerateComponentDirs(directory, "*.fx.yaml")) { AddControl(app, file._relativeName, true, file.GetContents(), errors); } foreach (var file in EnumerateComponentDirs(directory, "*.json")) { var componentTemplate = file.ToObject <CombinedTemplateState>(); app._templateStore.AddTemplate(componentTemplate.ComponentManifest.Name, componentTemplate); } foreach (var file in directory.EnumerateFiles(CodeDir, "*.fx.yaml", searchSubdirectories: false)) { AddControl(app, file._relativeName, false, file.GetContents(), errors); } // When loading TestSuites sharded files, add them within the top parent AppTest control (i.e. Test_7F478737223C4B69) // Make sure to load the the Test_7F478737223C4B69.fx.yaml file first to add the top parent control. var shardedTestSuites = new List <DirectoryReader.Entry>(); foreach (var file in directory.EnumerateFiles(TestDir, "*.fx.yaml")) { if (file.Kind == FileKind.AppTestParentControl) { AddControl(app, file._relativeName, false, file.GetContents(), errors); } else { shardedTestSuites.Add(file); } } shardedTestSuites.ForEach(x => AddControl(app, x._relativeName, false, x.GetContents(), errors)); }