From 959130d5b081b88ceb86010db2b8236785517847 Mon Sep 17 00:00:00 2001 From: Sylvester Knudsen Date: Fri, 19 Mar 2021 14:43:00 +0000 Subject: [PATCH] Extension data to home workspace (#11553) * workspacemodel thumbnail api + test * add graphDocumentationURL + serialise and deserialise Author * Update WorkspaceModel.cs * handle empty URIs * Update 2080_JSONTESTCRASH undo_redo.dyn * move thumbnail and help link to HomeWorkspaceMode * move extension data to HomeWorkspaceModel --- .../Graph/Workspaces/HomeWorkspaceModel.cs | 46 ++++++++++++++++++- .../Workspaces/SerializationConverters.cs | 16 ++++--- .../Graph/Workspaces/WorkspaceModel.cs | 43 ----------------- src/DynamoCore/Models/DynamoModel.cs | 14 +++--- .../Views/Core/DynamoView.xaml.cs | 10 +++- test/DynamoCoreTests/StorageExtensionTests.cs | 22 +++++---- 6 files changed, 84 insertions(+), 67 deletions(-) diff --git a/src/DynamoCore/Graph/Workspaces/HomeWorkspaceModel.cs b/src/DynamoCore/Graph/Workspaces/HomeWorkspaceModel.cs index 8858121b6c7..c1d9c48f5b7 100644 --- a/src/DynamoCore/Graph/Workspaces/HomeWorkspaceModel.cs +++ b/src/DynamoCore/Graph/Workspaces/HomeWorkspaceModel.cs @@ -7,6 +7,7 @@ using System.Xml; using Dynamo.Core; using Dynamo.Engine; +using Dynamo.Extensions; using Dynamo.Graph.Annotations; using Dynamo.Graph.Nodes; using Dynamo.Graph.Nodes.NodeLoaders; @@ -131,6 +132,14 @@ public string Thumbnail } } + /// + /// List of user defined data from extensions and view extensions stored in the graph + /// + internal ICollection ExtensionData + { + get; set; + } + /// /// In near future, the file loading mechanism will be completely moved /// into WorkspaceModel, that's the time we removed this property setter below. @@ -320,6 +329,7 @@ public HomeWorkspaceModel(EngineController engine, this.verboseLogging = verboseLogging; IsTestMode = isTestMode; EngineController = engine; + this.ExtensionData = new List(); // The first time the preloaded trace data is set, we cache // the data as historical. This will be used after the initial @@ -811,6 +821,40 @@ internal IList GetOrphanedSerializablesAndClearHistoricalTraceDat historicalTraceData = null; return orphans; - } + } + + internal bool TryGetMatchingWorkspaceData(string uniqueId, out Dictionary data) + { + data = new Dictionary(); + if (!ExtensionData.Any()) + return false; + + var extensionData = ExtensionData.Where(x => x.ExtensionGuid == uniqueId) + .FirstOrDefault(); + + if (extensionData is null) + return false; + + data = extensionData.Data; + return true; + } + + internal void UpdateExtensionData(string uniqueId, Dictionary data) + { + var extensionData = ExtensionData.Where(x => x.ExtensionGuid == uniqueId) + .FirstOrDefault(); + + if (extensionData is null) + return; + + extensionData.Data = data; + } + + internal void CreateNewExtensionData(string uniqueId, string name, string version, Dictionary data) + { + // TODO: Figure out how to add extension version when creating new ExtensionData + var extensionData = new ExtensionData(uniqueId, name, version, data); + ExtensionData.Add(extensionData); + } } } diff --git a/src/DynamoCore/Graph/Workspaces/SerializationConverters.cs b/src/DynamoCore/Graph/Workspaces/SerializationConverters.cs index 3416cc9e2bf..23bf68bf743 100644 --- a/src/DynamoCore/Graph/Workspaces/SerializationConverters.cs +++ b/src/DynamoCore/Graph/Workspaces/SerializationConverters.cs @@ -646,25 +646,28 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist Enumerable.Empty(), elementResolver, info, verboseLogging, isTestMode); + // Thumbnail if (obj.TryGetValue(nameof(HomeWorkspaceModel.Thumbnail), StringComparison.OrdinalIgnoreCase, out JToken thumbnail)) homeWorkspace.Thumbnail = thumbnail.ToString(); + // GraphDocumentaionLink if (obj.TryGetValue(nameof(HomeWorkspaceModel.GraphDocumentationURL), StringComparison.OrdinalIgnoreCase, out JToken helpLink)) { if (Uri.TryCreate(helpLink.ToString(), UriKind.Absolute, out Uri uri)) homeWorkspace.GraphDocumentationURL = uri; } + // ExtensionData + homeWorkspace.ExtensionData = GetExtensionData(serializer, obj); + ws = homeWorkspace; } ws.NodeLibraryDependencies = nodeLibraryDependencies.ToList(); - ws.ExtensionData = GetExtensionData(serializer, obj); if (obj.TryGetValue(nameof(WorkspaceModel.Author), StringComparison.OrdinalIgnoreCase, out JToken author)) ws.Author = author.ToString(); - return ws; } @@ -781,11 +784,6 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s // NodeLibraryDependencies writer.WritePropertyName(WorkspaceReadConverter.NodeLibraryDependenciesPropString); serializer.Serialize(writer, ws.NodeLibraryDependencies); - - // ExtensionData - writer.WritePropertyName(WorkspaceReadConverter.EXTENSION_WORKSPACE_DATA); - serializer.Serialize(writer, ws.ExtensionData); - if (!isCustomNode && ws is HomeWorkspaceModel hws) { @@ -796,6 +794,10 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s // GraphDocumentaionLink writer.WritePropertyName(nameof(HomeWorkspaceModel.GraphDocumentationURL)); writer.WriteValue(hws.GraphDocumentationURL); + + // ExtensionData + writer.WritePropertyName(WorkspaceReadConverter.EXTENSION_WORKSPACE_DATA); + serializer.Serialize(writer, hws.ExtensionData); } // Graph Author diff --git a/src/DynamoCore/Graph/Workspaces/WorkspaceModel.cs b/src/DynamoCore/Graph/Workspaces/WorkspaceModel.cs index 040b982c9da..9ff2b3f4dc1 100644 --- a/src/DynamoCore/Graph/Workspaces/WorkspaceModel.cs +++ b/src/DynamoCore/Graph/Workspaces/WorkspaceModel.cs @@ -724,14 +724,6 @@ public string Description } } - /// - /// List of user defined data from extensions and view extensions stored in the graph - /// - internal ICollection ExtensionData - { - get; set; - } - /// /// Are there unsaved changes in the workspace? /// @@ -1045,7 +1037,6 @@ protected WorkspaceModel( this.annotations = new List(annotations); this.NodeLibraryDependencies = new List(); - this.ExtensionData = new List(); // Set workspace info from WorkspaceInfo object Name = info.Name; @@ -2158,40 +2149,6 @@ private Guid IdToGuidConverter(string id) return deterministicGuid; } - - internal bool TryGetMatchingWorkspaceData(string uniqueId, out Dictionary data) - { - data = new Dictionary(); - if (!ExtensionData.Any()) - return false; - - var extensionData = ExtensionData.Where(x => x.ExtensionGuid == uniqueId) - .FirstOrDefault(); - - if (extensionData is null) - return false; - - data = extensionData.Data; - return true; - } - - internal void UpdateExtensionData(string uniqueId, Dictionary data) - { - var extensionData = ExtensionData.Where(x => x.ExtensionGuid == uniqueId) - .FirstOrDefault(); - - if (extensionData is null) - return; - - extensionData.Data = data; - } - - internal void CreateNewExtensionData(string uniqueId, string name, string version, Dictionary data) - { - // TODO: Figure out how to add extension version when creating new ExtensionData - var extensionData = new ExtensionData(uniqueId, name, version, data); - ExtensionData.Add(extensionData); - } /// /// Returns a DelayedGraphExecution object. diff --git a/src/DynamoCore/Models/DynamoModel.cs b/src/DynamoCore/Models/DynamoModel.cs index c2ff86edba5..b4b2f7cc98a 100644 --- a/src/DynamoCore/Models/DynamoModel.cs +++ b/src/DynamoCore/Models/DynamoModel.cs @@ -156,7 +156,8 @@ internal void OnWorkspaceSaving(WorkspaceModel workspace, SaveContext saveContex if (WorkspaceSaving != null) { WorkspaceSaving(workspace, saveContext); - HandleStorageExtensionsOnWorkspaceSaving(workspace, saveContext); + if (workspace is HomeWorkspaceModel hws) + HandleStorageExtensionsOnWorkspaceSaving(hws, saveContext); } } @@ -194,7 +195,8 @@ internal void OnWorkspaceOpened(WorkspaceModel workspace) if(WorkspaceOpened != null) { WorkspaceOpened.Invoke(workspace); - HandleStorageExtensionsOnWorkspaceOpened(workspace); + if (workspace is HomeWorkspaceModel hws) + HandleStorageExtensionsOnWorkspaceOpened(hws); } } @@ -972,7 +974,7 @@ private void RemoveExtension(IExtension ext) } - private void HandleStorageExtensionsOnWorkspaceOpened(WorkspaceModel workspace) + private void HandleStorageExtensionsOnWorkspaceOpened(HomeWorkspaceModel workspace) { foreach (var extension in extensionManager.StorageAccessExtensions) { @@ -980,7 +982,7 @@ private void HandleStorageExtensionsOnWorkspaceOpened(WorkspaceModel workspace) } } - private void HandleStorageExtensionsOnWorkspaceSaving(WorkspaceModel workspace, SaveContext saveContext) + private void HandleStorageExtensionsOnWorkspaceSaving(HomeWorkspaceModel workspace, SaveContext saveContext) { foreach (var extension in extensionManager.StorageAccessExtensions) { @@ -988,7 +990,7 @@ private void HandleStorageExtensionsOnWorkspaceSaving(WorkspaceModel workspace, } } - internal static void RaiseIExtensionStorageAccessWorkspaceOpened(WorkspaceModel workspace, IExtensionStorageAccess extension, ILogger logger) + internal static void RaiseIExtensionStorageAccessWorkspaceOpened(HomeWorkspaceModel workspace, IExtensionStorageAccess extension, ILogger logger) { workspace.TryGetMatchingWorkspaceData(extension.UniqueId, out Dictionary data); var extensionDataCopy = new Dictionary(data); @@ -1004,7 +1006,7 @@ internal static void RaiseIExtensionStorageAccessWorkspaceOpened(WorkspaceModel } } - internal static void RaiseIExtensionStorageAccessWorkspaceSaving(WorkspaceModel workspace, IExtensionStorageAccess extension, SaveContext saveContext, ILogger logger) + internal static void RaiseIExtensionStorageAccessWorkspaceSaving(HomeWorkspaceModel workspace, IExtensionStorageAccess extension, SaveContext saveContext, ILogger logger) { var assemblyName = Assembly.GetAssembly(extension.GetType()).GetName(); var version = $"{assemblyName.Version.Major}.{assemblyName.Version.Minor}"; diff --git a/src/DynamoCoreWpf/Views/Core/DynamoView.xaml.cs b/src/DynamoCoreWpf/Views/Core/DynamoView.xaml.cs index 793ae4ce709..f56dff21ae0 100644 --- a/src/DynamoCoreWpf/Views/Core/DynamoView.xaml.cs +++ b/src/DynamoCoreWpf/Views/Core/DynamoView.xaml.cs @@ -227,17 +227,23 @@ public DynamoView(DynamoViewModel dynamoViewModel) private void OnWorkspaceOpened(WorkspaceModel workspace) { + if (!(workspace is HomeWorkspaceModel hws)) + return; + foreach (var extension in viewExtensionManager.StorageAccessViewExtensions) { - DynamoModel.RaiseIExtensionStorageAccessWorkspaceOpened(workspace, extension, dynamoViewModel.Model.Logger); + DynamoModel.RaiseIExtensionStorageAccessWorkspaceOpened(hws, extension, dynamoViewModel.Model.Logger); } } private void OnWorkspaceSaving(WorkspaceModel workspace, Graph.SaveContext saveContext) { + if (!(workspace is HomeWorkspaceModel hws)) + return; + foreach (var extension in viewExtensionManager.StorageAccessViewExtensions) { - DynamoModel.RaiseIExtensionStorageAccessWorkspaceSaving(workspace, extension, saveContext, dynamoViewModel.Model.Logger); + DynamoModel.RaiseIExtensionStorageAccessWorkspaceSaving(hws, extension, saveContext, dynamoViewModel.Model.Logger); } } diff --git a/test/DynamoCoreTests/StorageExtensionTests.cs b/test/DynamoCoreTests/StorageExtensionTests.cs index f8645f54641..5c8bb027cd8 100644 --- a/test/DynamoCoreTests/StorageExtensionTests.cs +++ b/test/DynamoCoreTests/StorageExtensionTests.cs @@ -4,6 +4,7 @@ using System.Text; using System.Threading.Tasks; using Dynamo.Extensions; +using Dynamo.Graph.Workspaces; using Dynamo.Models; using Dynamo.Scheduler; using Moq; @@ -11,6 +12,7 @@ namespace Dynamo.Tests { + [TestFixture] public class StorageExtensionTests { private const string MOCK_EXTENSION_GUID = "7de691ac-b1ea-4353-9b9b-1f57b2967895"; @@ -124,7 +126,8 @@ public void OnWorkspaceOpenIsCalledWhenWorkspaceIsOpened() public void OnWorkspaceOpenDoesNotAddToWorkspaceExtensionData() { // Arrange - var extensionDataBeforeWorkspaceOpen = model.CurrentWorkspace.ExtensionData.Count; + var homeworkspace = model.CurrentWorkspace as HomeWorkspaceModel; + var extensionDataBeforeWorkspaceOpen = homeworkspace.ExtensionData.Count; var dataDictionary = new Dictionary { @@ -135,7 +138,7 @@ public void OnWorkspaceOpenDoesNotAddToWorkspaceExtensionData() // Act model.OnWorkspaceOpened(model.CurrentWorkspace); - var extensionDataAfterWorkspaceOpen = model.CurrentWorkspace.ExtensionData.Count; + var extensionDataAfterWorkspaceOpen = homeworkspace.ExtensionData.Count; // Assert Assert.AreEqual(extensionDataBeforeWorkspaceOpen, extensionDataAfterWorkspaceOpen); @@ -145,6 +148,7 @@ public void OnWorkspaceOpenDoesNotAddToWorkspaceExtensionData() public void OnWorkspaceOpenDoesNotModifyExistingExtensionDataDictionary() { // Arrange + var homeworkspace = model.CurrentWorkspace as HomeWorkspaceModel; var initialDict = new Dictionary { {"A","a"}, @@ -161,11 +165,11 @@ public void OnWorkspaceOpenDoesNotModifyExistingExtensionDataDictionary() // Act model.OnWorkspaceSaving(model.CurrentWorkspace, Graph.SaveContext.Save); - var extensionDataDictionaryBeforeOpen = model.CurrentWorkspace.ExtensionData + var extensionDataDictionaryBeforeOpen = homeworkspace.ExtensionData .Where(x=>x.ExtensionGuid == MOCK_EXTENSION_GUID).FirstOrDefault(); model.OnWorkspaceOpened(model.CurrentWorkspace); - var extensionDataDictionaryAfterOpen = model.CurrentWorkspace.ExtensionData + var extensionDataDictionaryAfterOpen = homeworkspace.ExtensionData .Where(x => x.ExtensionGuid == MOCK_EXTENSION_GUID).FirstOrDefault(); // Assert @@ -178,7 +182,8 @@ public void OnWorkspaceOpenDoesNotModifyExistingExtensionDataDictionary() public void OnWorkspaceSavingAddsToStoredExtensionData() { // Arrange - var initialDataDictionary = model.CurrentWorkspace.ExtensionData + var homeworkspace = model.CurrentWorkspace as HomeWorkspaceModel; + var initialDataDictionary = homeworkspace.ExtensionData .Where(x => x.ExtensionGuid == MOCK_EXTENSION_GUID) .FirstOrDefault(); @@ -193,7 +198,7 @@ public void OnWorkspaceSavingAddsToStoredExtensionData() // Act model.OnWorkspaceSaving(model.CurrentWorkspace, Graph.SaveContext.Save); - var extensionDataDictionaryAfterSave = model.CurrentWorkspace.ExtensionData + var extensionDataDictionaryAfterSave = homeworkspace.ExtensionData .Where(x => x.ExtensionGuid == MOCK_EXTENSION_GUID).FirstOrDefault(); // Assert @@ -207,13 +212,14 @@ public void OnWorkspaceSavingAddsToStoredExtensionData() public void OnWorkspaceSavingModifiesExistingExtensionDataDictionary() { // Arrange + var homeworkspace = model.CurrentWorkspace as HomeWorkspaceModel; var initialDataDictionary = new Dictionary { {"A","a" }, {"B","b" } }; var extensionData = new ExtensionData(MOCK_EXTENSION_GUID, MOCK_EXTENSION_NAME, "0.0", initialDataDictionary); - model.CurrentWorkspace.ExtensionData.Add(extensionData); + homeworkspace.ExtensionData.Add(extensionData); var dictionaryToAddOnSaving = new Dictionary { @@ -230,7 +236,7 @@ public void OnWorkspaceSavingModifiesExistingExtensionDataDictionary() // Act model.OnWorkspaceSaving(model.CurrentWorkspace, Graph.SaveContext.Save); - var extensionDataAfterSave = model.CurrentWorkspace.ExtensionData + var extensionDataAfterSave = homeworkspace.ExtensionData .Where(x => x.ExtensionGuid == MOCK_EXTENSION_GUID).FirstOrDefault(); // Assert