/// <summary> /// Initializes a new instance of the <see cref="CustomNodeSearchElement"/> class. /// </summary> /// <param name="customNodeManager">Custom node manager</param> /// <param name="info">Custom node info</param> public CustomNodeSearchElement(ICustomNodeSource customNodeManager, CustomNodeInfo info) { this.customNodeManager = customNodeManager; inputParameters = new List<Tuple<string, string>>(); outputParameters = new List<string>(); SyncWithCustomNodeInfo(info); }
/// <summary> /// Updates the properties of this search element. /// </summary> /// <param name="info">Actual data of custom node</param> public void SyncWithCustomNodeInfo(CustomNodeInfo info) { ID = info.FunctionId; Name = info.Name; FullCategoryName = info.Category; Description = info.Description; Path = info.Path; iconName = ID.ToString(); ElementType = ElementTypes.CustomNode; if (info.IsPackageMember) ElementType |= ElementTypes.Packaged; // Add one more flag. }
public void CanRefactorCustomNodeDescription() { const string nodeName = "TheNoodle"; const string catName = "TheCat"; const string descr = "TheCat"; const string path = @"C:\turtle\graphics.dyn"; var guid1 = Guid.NewGuid(); var dummyInfo1 = new CustomNodeInfo(guid1, nodeName, catName, descr, path); var dummySearch1 = new CustomNodeSearchElement(null, dummyInfo1); search.Add(dummySearch1); Assert.AreEqual(1, search.NumElements); // search for name var results = search.Search(nodeName).ToList(); // results are correct Assert.AreEqual(1, results.Count()); var res1 = results[0]; Assert.IsInstanceOf<CustomNodeSearchElement>(res1); Assert.AreEqual(guid1, ((CustomNodeSearchElement)res1).ID); // refactor description const string newDescription = "Tickle me elmo"; var newInfo = new CustomNodeInfo(guid1, nodeName, catName, newDescription, path); dummySearch1.SyncWithCustomNodeInfo(newInfo); search.Update(dummySearch1); // num elements is unchanged Assert.AreEqual(1, search.NumElements); // search for name var results1 = search.Search(nodeName).ToList(); // description is updated Assert.AreEqual(1, results1.Count()); var res2 = results1[0]; Assert.IsInstanceOf<CustomNodeSearchElement>(res2); Assert.AreEqual(guid1, ((CustomNodeSearchElement)res2).ID); Assert.AreEqual(newDescription, res2.Description); }
public void CanRefactorCustomNodeName() { const string nodeName = "TheNoodle"; const string catName = "TheCat"; const string descr = "TheCat"; const string path = @"C:\turtle\graphics.dyn"; var guid1 = Guid.NewGuid(); var dummyInfo1 = new CustomNodeInfo(guid1, nodeName, catName, descr, path); var dummySearch1 = new CustomNodeSearchElement(null, dummyInfo1); search.Add(dummySearch1); Assert.AreEqual(1, search.NumElements); const string newNodeName = "TheTurtle"; var newInfo = new CustomNodeInfo(guid1, newNodeName, catName, descr, path); dummySearch1.SyncWithCustomNodeInfo(newInfo); search.Update(dummySearch1); Assert.AreEqual(1, search.NumElements); // search for new name var results = search.Search(newNodeName).ToList(); // results are correct Assert.AreEqual(1, results.Count()); var res1 = results[0]; Assert.IsInstanceOf<CustomNodeSearchElement>(res1); Assert.AreEqual(guid1, ((CustomNodeSearchElement)res1).ID); // search for old name var results1 = search.Search(nodeName); // results are correct Assert.AreEqual(0, results1.Count()); }
/// <summary> /// Attempts to retrieve information for the given custom node name. If there are multiple /// custom nodes matching the given name, this method will return any one of them. /// </summary> /// <param name="name">Name of a custom node.</param> /// <param name="info"></param> /// <returns></returns> public bool TryGetNodeInfo(string name, out CustomNodeInfo info) { info = NodeInfos.Values.FirstOrDefault(x => x.Name == name); return(info != null); }
public void CanRemoveSingleCustomNodeByIdWhereThereAreDuplicatesWithDifferentIds() { const string nodeName = "TheNoodle"; const string catName = "TheCat"; const string descr = "TheCat"; const string path = @"C:\turtle\graphics.dyn"; var guid1 = Guid.NewGuid(); var guid2 = Guid.NewGuid(); var dummyInfo1 = new CustomNodeInfo(guid1, nodeName, catName, descr, path); var dummySearch1 = new CustomNodeSearchElement(null, dummyInfo1); var dummyInfo2 = new CustomNodeInfo(guid2, nodeName, catName, descr, path); var dummySearch2 = new CustomNodeSearchElement(null, dummyInfo2); search.Add(dummySearch1); search.Add(dummySearch2); Assert.AreEqual(2, search.NumElements); search.Remove(dummySearch2); Assert.AreEqual(1, search.NumElements); var results = search.Search(nodeName).ToList(); Assert.AreEqual(1, results.Count()); var res1 = results[0]; Assert.IsInstanceOf<CustomNodeSearchElement>(res1); var node1 = (CustomNodeSearchElement)res1; Assert.AreEqual(node1.ID, guid1); }
public void CanAddDuplicateCustomNodeWithDifferentGuidsAndGetBothInResults() { const string nodeName = "TheNoodle"; const string catName = "TheCat"; const string descr = "TheCat"; const string path = @"C:\turtle\graphics.dyn"; var guid1 = Guid.NewGuid(); var guid2 = Guid.NewGuid(); var dummyInfo1 = new CustomNodeInfo(guid1, nodeName, catName, descr, path); var dummySearch1 = new CustomNodeSearchElement(null, dummyInfo1); var dummyInfo2 = new CustomNodeInfo(guid2, nodeName, catName, descr, path); var dummySearch2 = new CustomNodeSearchElement(null, dummyInfo2); search.Add(dummySearch1); search.Add(dummySearch2); Assert.AreEqual(2, search.NumElements); var results = search.Search(nodeName).ToList(); Assert.AreEqual(2, results.Count()); var resultIds = results.Cast<CustomNodeSearchElement>().Select(x => x.ID).ToList(); Assert.IsTrue(resultIds.Contains(guid1)); Assert.IsTrue(resultIds.Contains(guid2)); }
public void CanRemoveNodeAndCategoryByFunctionId() { const string nodeName = "TheNoodle"; const string catName = "TheCat"; const string descr = "TheCat"; const string path = @"C:\turtle\graphics.dyn"; var guid1 = Guid.NewGuid(); var dummyInfo1 = new CustomNodeInfo(guid1, nodeName, catName, descr, path); var dummySearch1 = new CustomNodeSearchElement(null, dummyInfo1); // add custom node search.Add(dummySearch1); // confirm it's in the dictionary Assert.AreEqual(1, search.NumElements); // remove custom node search.Remove(dummySearch1); // it's gone Assert.AreEqual(0, search.NumElements); var results = search.Search(nodeName); Assert.AreEqual(0, results.Count()); }
/// <summary> /// Helper method for custom node adding and removing /// </summary> public static void AssertAddAndRemoveCustomNode( NodeSearchModel searchModel, string nodeName, string catName, string descr = "Bla", string path = "Bla") { var dummyInfo = new CustomNodeInfo(Guid.NewGuid(), nodeName, catName, descr, path); var dummySearch = new CustomNodeSearchElement(null, dummyInfo); searchModel.Add(dummySearch); var res = searchModel.Search(nodeName).ToList(); Assert.AreNotEqual(0, res.Count()); Assert.AreEqual(res[0].Name, nodeName); searchModel.Remove(dummySearch); res = searchModel.Search(nodeName).ToList(); Assert.AreEqual(0, res.Count()); }
public void CanRefactorCustomNodeWhilePreservingDuplicates() { const string nodeName = "TheNoodle"; const string catName = "TheCat"; const string descr = "TheCat"; const string path = @"C:\turtle\graphics.dyn"; var guid1 = Guid.NewGuid(); var dummyInfo1 = new CustomNodeInfo(guid1, nodeName, catName, descr, path); var dummySearch1 = new CustomNodeSearchElement(null, dummyInfo1); var dummySearch2 = new CustomNodeSearchElement(null, dummyInfo1); search.Add(dummySearch1); search.Add(dummySearch2); Assert.AreEqual(2, search.NumElements); // refactor one of the nodes with newNodeName const string newNodeName = "TheTurtle"; var newInfo = new CustomNodeInfo(guid1, newNodeName, catName, descr, path); dummySearch1.SyncWithCustomNodeInfo(newInfo); search.Update(dummySearch1); // num elements is unchanged Assert.AreEqual(2, search.NumElements); // search for new name var results = search.Search(newNodeName).ToList(); // results are correct - only one result Assert.AreEqual(1, results.Count()); var res1 = results[0]; Assert.IsInstanceOf<CustomNodeSearchElement>(res1); Assert.AreSame(dummySearch1, res1); // search for old name results = search.Search(nodeName).ToList(); // results are correct - the first nodes are returned Assert.AreEqual(1, results.Count()); var res2 = results[0]; Assert.IsInstanceOf<CustomNodeSearchElement>(res2); Assert.AreSame(dummySearch2, res2); }
internal bool Refactor(CustomNodeInfo nodeInfo) { this.RemoveNodeAndEmptyParentCategory(nodeInfo.Guid); return(this.Add(nodeInfo)); }
public void Add(CustomNodeInfo nodeInfo) { this.Add(nodeInfo.Name, nodeInfo.Category, nodeInfo.Description, nodeInfo.Guid); }
/// <summary> /// Attempts to retrieve information for the given custom node identifier. /// </summary> /// <param name="id">Custom node identifier.</param> /// <param name="info"></param> /// <returns>Success or failure.</returns> public bool TryGetNodeInfo(Guid id, out CustomNodeInfo info) { return(NodeInfos.TryGetValue(id, out info)); }
public bool SyncWithWorkspace(DynamoModel dynamoModel, bool addToSearch, bool compileFunction) { // Get the internal nodes for the function var functionWorkspace = WorkspaceModel; try { // Add function defininition dynamoModel.CustomNodeManager.AddFunctionDefinition(FunctionId, this); // search if (addToSearch) { AddToSearch(dynamoModel.SearchModel); } var info = new CustomNodeInfo(FunctionId, functionWorkspace.Name, functionWorkspace.Category, functionWorkspace.Description, WorkspaceModel.FileName); dynamoModel.CustomNodeManager.SetNodeInfo(info); Compile(dynamoModel, dynamoModel.EngineController); } catch (Exception e) { dynamoModel.Logger.Log("Error saving:" + e.GetType()); dynamoModel.Logger.Log(e); return false; } return true; }
/// <summary> /// Stores the path and function definition without initializing a node. Overwrites /// the existing NodeInfo if necessary /// </summary> private void SetNodeInfo(CustomNodeInfo newInfo) { NodeInfos[newInfo.FunctionId] = newInfo; OnInfoUpdated(newInfo); }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { NodeModel node = null; String typeName = String.Empty; String functionName = String.Empty; String assemblyName = String.Empty; var obj = JObject.Load(reader); Type type = null; try { type = Type.GetType(obj["$type"].Value <string>()); typeName = obj["$type"].Value <string>().Split(',').FirstOrDefault(); if (typeName.Equals("Dynamo.Graph.Nodes.ZeroTouch.DSFunction")) { // If it is a zero touch node, then get the whole function name including the namespace. functionName = obj["FunctionSignature"].Value <string>().Split('@').FirstOrDefault().Trim(); } // we get the assembly name from the type string for the node model nodes. else { assemblyName = obj["$type"].Value <string>().Split(',').Skip(1).FirstOrDefault().Trim(); } } catch (Exception e) { nodeFactory?.AsLogger().Log(e); } // If we can't find this type - try to look in our load from assemblies, // but only during testing - this is required during testing because some dlls are loaded // using Assembly.LoadFrom using the assemblyHelper - which loads dlls into loadFrom context - // dlls loaded with LoadFrom context cannot be found using Type.GetType() - this should // not be an issue during normal dynamo use but if it is we can enable this code. if (type == null && this.isTestMode == true) { List <Assembly> resultList; // This assemblyName does not usually contain version information... assemblyName = obj["$type"].Value <string>().Split(',').Skip(1).FirstOrDefault().Trim(); if (assemblyName != null) { if (this.loadedAssemblies.TryGetValue(assemblyName, out resultList)) { var matchingTypes = resultList.Select(x => x.GetType(typeName)).ToList(); type = matchingTypes.FirstOrDefault(); } } } // Check for and attempt to resolve an unknown type before proceeding if (type == null) { // Attempt to resolve the type using `AlsoKnownAs` var unresolvedName = obj["$type"].Value <string>().Split(',').FirstOrDefault(); Type newType; nodeFactory.ResolveType(unresolvedName, out newType); // If resolved update the type if (newType != null) { type = newType; } } // If the id is not a guid, makes a guid based on the id of the node var guid = GuidUtility.tryParseOrCreateGuid(obj["Id"].Value <string>()); var replication = obj["Replication"].Value <string>(); var inPorts = obj["Inputs"].ToArray().Select(t => t.ToObject <PortModel>()).ToArray(); var outPorts = obj["Outputs"].ToArray().Select(t => t.ToObject <PortModel>()).ToArray(); var resolver = (IdReferenceResolver)serializer.ReferenceResolver; string assemblyLocation = objectType.Assembly.Location; bool remapPorts = true; // If type is still null at this point return a dummy node if (type == null) { node = CreateDummyNode(obj, typeName, assemblyName, functionName, inPorts, outPorts); } // Attempt to create a valid node using the type else if (type == typeof(Function)) { var functionId = Guid.Parse(obj["FunctionSignature"].Value <string>()); CustomNodeDefinition def = null; CustomNodeInfo info = null; // Skip deserializing the Description Json property as the original one in dyf may // already be updated without syncing with the dyn bool isUnresolved = !manager.TryGetCustomNodeData(functionId, null, false, out def, out info); Function function = manager.CreateCustomNodeInstance(functionId, null, false, def, info); node = function; if (isUnresolved) { function.UpdatePortsForUnresolved(inPorts, outPorts); } } else if (type == typeof(CodeBlockNodeModel)) { var code = obj["Code"].Value <string>(); CodeBlockNodeModel codeBlockNode = new CodeBlockNodeModel(code, guid, 0.0, 0.0, libraryServices, ElementResolver); node = codeBlockNode; // If the code block node is in an error state read the extra port data // and initialize the input and output ports if (node.IsInErrorState) { List <string> inPortNames = new List <string>(); var inputs = obj["Inputs"]; foreach (var input in inputs) { inPortNames.Add(input["Name"].ToString()); } // NOTE: This could be done in a simpler way, but is being implemented // in this manner to allow for possible future port line number // information being available in the file List <int> outPortLineIndexes = new List <int>(); var outputs = obj["Outputs"]; int outputLineIndex = 0; foreach (var output in outputs) { outPortLineIndexes.Add(outputLineIndex++); } codeBlockNode.SetErrorStatePortData(inPortNames, outPortLineIndexes); } } else if (typeof(DSFunctionBase).IsAssignableFrom(type)) { var mangledName = obj["FunctionSignature"].Value <string>(); var lookupSignature = libraryServices.GetFunctionSignatureFromFunctionSignatureHint(mangledName) ?? mangledName; var functionDescriptor = libraryServices.GetFunctionDescriptor(lookupSignature); // Use the functionDescriptor to try and restore the proper node if possible if (functionDescriptor == null) { node = CreateDummyNode(obj, assemblyName, functionName, inPorts, outPorts); } else { if (type == typeof(DSVarArgFunction)) { node = new DSVarArgFunction(functionDescriptor); // The node syncs with the function definition. // Then we need to make the inport count correct var varg = (DSVarArgFunction)node; varg.VarInputController.SetNumInputs(inPorts.Count()); } else if (type == typeof(DSFunction)) { node = new DSFunction(functionDescriptor); } } } else if (type == typeof(DSVarArgFunction)) { var functionId = Guid.Parse(obj["FunctionSignature"].Value <string>()); node = manager.CreateCustomNodeInstance(functionId); } else if (type.ToString() == "CoreNodeModels.Formula") { node = (NodeModel)obj.ToObject(type); } else { node = (NodeModel)obj.ToObject(type); // if node is an customNode input symbol - assign the element resolver. if (node is Nodes.CustomNodes.Symbol) { (node as Nodes.CustomNodes.Symbol).ElementResolver = ElementResolver; } // We don't need to remap ports for any nodes with json constructors which pass ports remapPorts = false; } if (remapPorts) { RemapPorts(node, inPorts, outPorts, resolver, manager.AsLogger()); } // Cannot set Lacing directly as property is protected node.UpdateValue(new UpdateValueParams("ArgumentLacing", replication)); node.GUID = guid; // Add references to the node and the ports to the reference resolver, // so that they are available for entities which are deserialized later. serializer.ReferenceResolver.AddReference(serializer.Context, node.GUID.ToString(), node); foreach (var p in node.InPorts) { serializer.ReferenceResolver.AddReference(serializer.Context, p.GUID.ToString(), p); } foreach (var p in node.OutPorts) { serializer.ReferenceResolver.AddReference(serializer.Context, p.GUID.ToString(), p); } return(node); }
public Package GetOwnerPackage(CustomNodeInfo def) { return(GetOwnerPackage(def.Path)); }
public bool IsUnderPackageControl(CustomNodeInfo def) { return(IsUnderPackageControl(def.Path)); }
internal void Refactor(CustomNodeInfo nodeInfo) { this.Remove(nodeInfo.Name); this.Add(nodeInfo); }
public bool SyncWithWorkspace(bool addToSearch, bool compileFunction) { // Get the internal nodes for the function var functionWorkspace = this.WorkspaceModel; try { // Add function defininition dynSettings.Controller.CustomNodeManager.AddFunctionDefinition(this.FunctionId, this); // search if (addToSearch) { AddToSearch(); } var info = new CustomNodeInfo(this.FunctionId, functionWorkspace.Name, functionWorkspace.Category, functionWorkspace.Description, this.WorkspaceModel.FileName); dynSettings.Controller.CustomNodeManager.SetNodeInfo(info); this.CompileAndAddToEnvironment(dynSettings.Controller.FSchemeEnvironment); } catch (Exception e) { DynamoLogger.Instance.Log("Error saving:" + e.GetType()); DynamoLogger.Instance.Log(e); return false; } return true; }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { NodeModel node = null; var obj = JObject.Load(reader); var type = Type.GetType(obj["$type"].Value <string>()); // If the id is not a guid, makes a guid based on the id of the node var guid = GuidUtility.tryParseOrCreateGuid(obj["Id"].Value <string>()); var replication = obj["Replication"].Value <string>(); var inPorts = obj["Inputs"].ToArray().Select(t => t.ToObject <PortModel>()).ToArray(); var outPorts = obj["Outputs"].ToArray().Select(t => t.ToObject <PortModel>()).ToArray(); var resolver = (IdReferenceResolver)serializer.ReferenceResolver; string assemblyLocation = objectType.Assembly.Location; bool remapPorts = true; if (type == null) { node = CreateDummyNode(obj, assemblyLocation, inPorts, outPorts); } else if (type == typeof(Function)) { var functionId = Guid.Parse(obj["FunctionSignature"].Value <string>()); CustomNodeDefinition def = null; CustomNodeInfo info = null; bool isUnresolved = !manager.TryGetCustomNodeData(functionId, null, false, out def, out info); Function function = manager.CreateCustomNodeInstance(functionId, null, false, def, info); node = function; if (isUnresolved) { function.UpdatePortsForUnresolved(inPorts, outPorts); } } else if (type == typeof(CodeBlockNodeModel)) { var code = obj["Code"].Value <string>(); node = new CodeBlockNodeModel(code, guid, 0.0, 0.0, libraryServices, ElementResolver); } else if (typeof(DSFunctionBase).IsAssignableFrom(type)) { var mangledName = obj["FunctionSignature"].Value <string>(); var functionDescriptor = libraryServices.GetFunctionDescriptor(mangledName); if (functionDescriptor == null) { node = CreateDummyNode(obj, assemblyLocation, inPorts, outPorts); } else { if (type == typeof(DSVarArgFunction)) { node = new DSVarArgFunction(functionDescriptor); // The node syncs with the function definition. // Then we need to make the inport count correct var varg = (DSVarArgFunction)node; varg.VarInputController.SetNumInputs(inPorts.Count()); } else if (type == typeof(DSFunction)) { node = new DSFunction(functionDescriptor); } } } else if (type == typeof(DSVarArgFunction)) { var functionId = Guid.Parse(obj["FunctionSignature"].Value <string>()); node = manager.CreateCustomNodeInstance(functionId); } else if (type.ToString() == "CoreNodeModels.Formula") { node = (NodeModel)obj.ToObject(type); } else { node = (NodeModel)obj.ToObject(type); // We don't need to remap ports for any nodes with json constructors which pass ports remapPorts = false; } if (remapPorts) { RemapPorts(node, inPorts, outPorts, resolver); } // Cannot set Lacing directly as property is protected node.UpdateValue(new UpdateValueParams("ArgumentLacing", replication)); node.GUID = guid; // Add references to the node and the ports to the reference resolver, // so that they are available for entities which are deserialized later. serializer.ReferenceResolver.AddReference(serializer.Context, node.GUID.ToString(), node); foreach (var p in node.InPorts) { serializer.ReferenceResolver.AddReference(serializer.Context, p.GUID.ToString(), p); } foreach (var p in node.OutPorts) { serializer.ReferenceResolver.AddReference(serializer.Context, p.GUID.ToString(), p); } return(node); }