コード例 #1
0
        /// <summary>
        ///     Deserialize a function definition from a given path.  A side effect of this function is that
        ///     the node is added to the dictionary of loadedNodes.
        /// </summary>
        /// <param name="funcDefGuid">The function guid we're currently loading</param>
        /// <param name="controller">Reference to the calling controller</param>
        /// <param name="def">The resultant function definition</param>
        /// <returns></returns>
        private bool GetDefinitionFromPath(Guid funcDefGuid, out FunctionDefinition def)
        {
            var controller = dynSettings.Controller;

            try
            {
                var xmlPath = GetNodePath(funcDefGuid);

                #region read xml file

                var xmlDoc = new XmlDocument();
                xmlDoc.Load(xmlPath);

                string funName     = null;
                string category    = "";
                double cx          = 0;
                double cy          = 0;
                string description = "";
                string version     = "";

                double zoom = 1.0;
                string id   = "";

                // load the header

                // handle legacy workspace nodes called dynWorkspace
                // and new workspaces without the dyn prefix
                XmlNodeList workspaceNodes = xmlDoc.GetElementsByTagName("Workspace");
                if (workspaceNodes.Count == 0)
                {
                    workspaceNodes = xmlDoc.GetElementsByTagName("dynWorkspace");
                }

                foreach (XmlNode node in workspaceNodes)
                {
                    foreach (XmlAttribute att in node.Attributes)
                    {
                        if (att.Name.Equals("X"))
                        {
                            cx = double.Parse(att.Value, CultureInfo.InvariantCulture);
                        }
                        else if (att.Name.Equals("Y"))
                        {
                            cy = double.Parse(att.Value, CultureInfo.InvariantCulture);
                        }
                        else if (att.Name.Equals("zoom"))
                        {
                            zoom = double.Parse(att.Value, CultureInfo.InvariantCulture);
                        }
                        else if (att.Name.Equals("Name"))
                        {
                            funName = att.Value;
                        }
                        else if (att.Name.Equals("Category"))
                        {
                            category = att.Value;
                        }
                        else if (att.Name.Equals("Description"))
                        {
                            description = att.Value;
                        }
                        else if (att.Name.Equals("ID"))
                        {
                            id = att.Value;
                        }
                        else if (att.Name.Equals("Version"))
                        {
                            version = att.Value;
                        }
                    }
                }

                // we have a dyf and it lacks an ID field, we need to assign it
                // a deterministic guid based on its name.  By doing it deterministically,
                // files remain compatible
                if (string.IsNullOrEmpty(id) && !string.IsNullOrEmpty(funName))
                {
                    id = GuidUtility.Create(GuidUtility.UrlNamespace, funName).ToString();
                }

                #endregion

                //DynamoCommands.WriteToLogCmd.Execute("Loading node definition for \"" + funName + "\" from: " + xmlPath);
                dynSettings.Controller.DynamoModel.WriteToLog("Loading node definition for \"" + funName + "\" from: " + xmlPath);

                var ws = new CustomNodeWorkspaceModel(
                    funName, category.Length > 0
                    ? category
                    : "Custom Nodes", description, cx, cy)
                {
                    WatchChanges = false,
                    FileName     = xmlPath,
                    Zoom         = zoom
                };

                def = new FunctionDefinition(Guid.Parse(id))
                {
                    WorkspaceModel = ws
                };

                // load a dummy version, so any nodes depending on this node
                // will find an (empty) identifier on compilation
                FScheme.Expression dummyExpression = FScheme.Expression.NewNumber_E(0);
                controller.FSchemeEnvironment.DefineSymbol(def.FunctionId.ToString(), dummyExpression);

                // set the node as loaded
                this.LoadedCustomNodes.Add(def.FunctionId, def);

                XmlNodeList elNodes = xmlDoc.GetElementsByTagName("Elements");
                XmlNodeList cNodes  = xmlDoc.GetElementsByTagName("Connectors");
                XmlNodeList nNodes  = xmlDoc.GetElementsByTagName("Notes");

                if (elNodes.Count == 0)
                {
                    elNodes = xmlDoc.GetElementsByTagName("dynElements");
                }
                if (cNodes.Count == 0)
                {
                    cNodes = xmlDoc.GetElementsByTagName("dynConnectors");
                }
                if (nNodes.Count == 0)
                {
                    nNodes = xmlDoc.GetElementsByTagName("dynNotes");
                }

                XmlNode elNodesList = elNodes[0];
                XmlNode cNodesList  = cNodes[0];
                XmlNode nNodesList  = nNodes[0];

                #region instantiate nodes

                var badNodes = new List <Guid>();

                foreach (XmlNode elNode in elNodesList.ChildNodes)
                {
                    XmlAttribute typeAttrib          = elNode.Attributes["type"];
                    XmlAttribute guidAttrib          = elNode.Attributes["guid"];
                    XmlAttribute nicknameAttrib      = elNode.Attributes["nickname"];
                    XmlAttribute xAttrib             = elNode.Attributes["x"];
                    XmlAttribute yAttrib             = elNode.Attributes["y"];
                    XmlAttribute lacingAttrib        = elNode.Attributes["lacing"];
                    XmlAttribute isVisAttrib         = elNode.Attributes["isVisible"];
                    XmlAttribute isUpstreamVisAttrib = elNode.Attributes["isUpstreamVisible"];

                    string typeName = typeAttrib.Value;

                    //test the GUID to confirm that it is non-zero
                    //if it is zero, then we have to fix it
                    //this will break the connectors, but it won't keep
                    //propagating bad GUIDs
                    var guid = new Guid(guidAttrib.Value);
                    if (guid == Guid.Empty)
                    {
                        guid = Guid.NewGuid();
                    }

                    string nickname = nicknameAttrib.Value;

                    double x = double.Parse(xAttrib.Value, CultureInfo.InvariantCulture);
                    double y = double.Parse(yAttrib.Value, CultureInfo.InvariantCulture);

                    bool isVisible = true;
                    if (isVisAttrib != null)
                    {
                        isVisible = isVisAttrib.Value == "true" ? true : false;
                    }

                    bool isUpstreamVisible = true;
                    if (isUpstreamVisAttrib != null)
                    {
                        isUpstreamVisible = isUpstreamVisAttrib.Value == "true" ? true : false;
                    }

                    typeName = Dynamo.Nodes.Utilities.PreprocessTypeName(typeName);
                    System.Type type = Dynamo.Nodes.Utilities.ResolveType(typeName);
                    if (null == type)
                    {
                        badNodes.Add(guid);
                        continue;
                    }

                    NodeModel el = dynSettings.Controller.DynamoModel.CreateNodeInstance(type, nickname, guid);

                    if (lacingAttrib != null)
                    {
                        LacingStrategy lacing = LacingStrategy.First;
                        Enum.TryParse(lacingAttrib.Value, out lacing);
                        el.ArgumentLacing = lacing;
                    }

                    el.IsVisible         = isVisible;
                    el.IsUpstreamVisible = isUpstreamVisible;

                    ws.Nodes.Add(el);
                    el.WorkSpace = ws;
                    var node = el;

                    node.X = x;
                    node.Y = y;

                    if (el == null)
                    {
                        return(false);
                    }

                    el.DisableReporting();

                    el.Load(
                        elNode,
                        string.IsNullOrEmpty(version)
                            ? new Version(0, 0, 0, 0)
                            : new Version(version));
                }

                #endregion

                #region instantiate connectors

                foreach (XmlNode connector in cNodesList.ChildNodes)
                {
                    XmlAttribute guidStartAttrib = connector.Attributes[0];
                    XmlAttribute intStartAttrib  = connector.Attributes[1];
                    XmlAttribute guidEndAttrib   = connector.Attributes[2];
                    XmlAttribute intEndAttrib    = connector.Attributes[3];
                    XmlAttribute portTypeAttrib  = connector.Attributes[4];

                    var      guidStart  = new Guid(guidStartAttrib.Value);
                    var      guidEnd    = new Guid(guidEndAttrib.Value);
                    int      startIndex = Convert.ToInt16(intStartAttrib.Value);
                    int      endIndex   = Convert.ToInt16(intEndAttrib.Value);
                    PortType portType   = ((PortType)Convert.ToInt16(portTypeAttrib.Value));

                    //find the elements to connect
                    NodeModel start = null;
                    NodeModel end   = null;

                    if (badNodes.Contains(guidStart) || badNodes.Contains(guidEnd))
                    {
                        continue;
                    }

                    foreach (NodeModel e in ws.Nodes)
                    {
                        if (e.GUID == guidStart)
                        {
                            start = e;
                        }
                        else if (e.GUID == guidEnd)
                        {
                            end = e;
                        }
                        if (start != null && end != null)
                        {
                            break;
                        }
                    }

                    try
                    {
                        var newConnector = ConnectorModel.Make(
                            start, end,
                            startIndex, endIndex,
                            portType);
                        if (newConnector != null)
                        {
                            ws.Connectors.Add(newConnector);
                        }
                    }
                    catch
                    {
                        //DynamoCommands.WriteToLogCmd.Execute(string.Format("ERROR : Could not create connector between {0} and {1}.", start.NickName, end.NickName));
                        dynSettings.Controller.DynamoModel.WriteToLog(string.Format("ERROR : Could not create connector between {0} and {1}.", start.NickName, end.NickName));
                    }
                }

                #endregion

                #region instantiate notes

                if (nNodesList != null)
                {
                    foreach (XmlNode note in nNodesList.ChildNodes)
                    {
                        XmlAttribute textAttrib = note.Attributes[0];
                        XmlAttribute xAttrib    = note.Attributes[1];
                        XmlAttribute yAttrib    = note.Attributes[2];

                        string text = textAttrib.Value;
                        double x    = Convert.ToDouble(xAttrib.Value, CultureInfo.InvariantCulture);
                        double y    = Convert.ToDouble(yAttrib.Value, CultureInfo.InvariantCulture);

                        Guid guid    = Guid.NewGuid();
                        var  command = new DynCmd.CreateNoteCommand(guid, text, x, y, false);
                        dynSettings.Controller.DynamoModel.AddNoteInternal(command, ws);
                    }
                }

                #endregion

                foreach (var e in ws.Nodes)
                {
                    e.EnableReporting();
                }

                def.CompileAndAddToEnvironment(controller.FSchemeEnvironment);

                ws.WatchChanges = true;

                this.OnGetDefinitionFromPath(def);
            }
            catch (Exception ex)
            {
                dynSettings.Controller.DynamoModel.WriteToLog("There was an error opening the workbench.");
                dynSettings.Controller.DynamoModel.WriteToLog(ex);

                if (DynamoController.IsTestMode)
                {
                    Assert.Fail(ex.Message);
                }

                def = null;
                return(false);
            }

            return(true);
        }
コード例 #2
0
        /// <summary>
        ///     Deserialize a function definition from a given path.  A side effect of this function is that
        ///     the node is added to the dictionary of loadedNodes.
        /// </summary>
        /// <param name="funcDefGuid">The function guid we're currently loading</param>
        /// <param name="def">The resultant function definition</param>
        /// <returns></returns>
        private bool GetDefinitionFromPath(Guid funcDefGuid, out CustomNodeDefinition def)
        {
            try
            {
                var xmlPath = GetNodePath(funcDefGuid);

                #region read xml file

                var xmlDoc = new XmlDocument();
                xmlDoc.Load(xmlPath);

                string funName     = null;
                string category    = "";
                double cx          = 0;
                double cy          = 0;
                string description = "";
                string version     = "";

                double zoom = 1.0;
                string id   = "";

                // load the header

                // handle legacy workspace nodes called dynWorkspace
                // and new workspaces without the dyn prefix
                XmlNodeList workspaceNodes = xmlDoc.GetElementsByTagName("Workspace");
                if (workspaceNodes.Count == 0)
                {
                    workspaceNodes = xmlDoc.GetElementsByTagName("dynWorkspace");
                }

                foreach (XmlNode node in workspaceNodes)
                {
                    foreach (XmlAttribute att in node.Attributes)
                    {
                        if (att.Name.Equals("X"))
                        {
                            cx = double.Parse(att.Value, CultureInfo.InvariantCulture);
                        }
                        else if (att.Name.Equals("Y"))
                        {
                            cy = double.Parse(att.Value, CultureInfo.InvariantCulture);
                        }
                        else if (att.Name.Equals("zoom"))
                        {
                            zoom = double.Parse(att.Value, CultureInfo.InvariantCulture);
                        }
                        else if (att.Name.Equals("Name"))
                        {
                            funName = att.Value;
                        }
                        else if (att.Name.Equals("Category"))
                        {
                            category = att.Value;
                        }
                        else if (att.Name.Equals("Description"))
                        {
                            description = att.Value;
                        }
                        else if (att.Name.Equals("ID"))
                        {
                            id = att.Value;
                        }
                        else if (att.Name.Equals("Version"))
                        {
                            version = att.Value;
                        }
                    }
                }

                Version fileVersion = MigrationManager.VersionFromString(version);

                var currentVersion = MigrationManager.VersionFromWorkspace(dynamoModel.HomeSpace);

                if (fileVersion > currentVersion)
                {
                    bool resume = Utils.DisplayFutureFileMessage(this.dynamoModel, xmlPath, fileVersion, currentVersion);
                    if (!resume)
                    {
                        def = null;
                        return(false);
                    }
                }

                var decision = MigrationManager.ShouldMigrateFile(fileVersion, currentVersion);
                if (decision == MigrationManager.Decision.Abort)
                {
                    Utils.DisplayObsoleteFileMessage(this.dynamoModel, xmlPath, fileVersion, currentVersion);

                    def = null;
                    return(false);
                }
                else if (decision == MigrationManager.Decision.Migrate)
                {
                    string backupPath = string.Empty;
                    bool   isTesting  = DynamoModel.IsTestMode; // No backup during test.
                    if (!isTesting && MigrationManager.BackupOriginalFile(xmlPath, ref backupPath))
                    {
                        string message = string.Format(
                            "Original file '{0}' gets backed up at '{1}'",
                            Path.GetFileName(xmlPath), backupPath);

                        dynamoModel.Logger.Log(message);
                    }

                    MigrationManager.Instance.ProcessWorkspaceMigrations(this.dynamoModel, xmlDoc, fileVersion);
                    MigrationManager.Instance.ProcessNodesInWorkspace(this.dynamoModel, xmlDoc, fileVersion);
                }

                // we have a dyf and it lacks an ID field, we need to assign it
                // a deterministic guid based on its name.  By doing it deterministically,
                // files remain compatible
                if (string.IsNullOrEmpty(id) && !string.IsNullOrEmpty(funName))
                {
                    id = GuidUtility.Create(GuidUtility.UrlNamespace, funName).ToString();
                }

                #endregion

                //DynamoCommands.WriteToLogCmd.Execute("Loading node definition for \"" + funName + "\" from: " + xmlPath);
                this.dynamoModel.Logger.Log("Loading node definition for \"" + funName + "\" from: " + xmlPath);

                var ws = new CustomNodeWorkspaceModel(dynamoModel,
                                                      funName, category.Length > 0
                    ? category
                    : "Custom Nodes", description, cx, cy)
                {
                    WatchChanges = false,
                    FileName     = xmlPath,
                    Zoom         = zoom
                };

                def = new CustomNodeDefinition(Guid.Parse(id))
                {
                    WorkspaceModel = ws,
                    IsBeingLoaded  = true
                };

                // set the node as loaded
                LoadedCustomNodes.Remove(def.FunctionId);
                LoadedCustomNodes.Add(def.FunctionId, def);

                XmlNodeList elNodes = xmlDoc.GetElementsByTagName("Elements");
                XmlNodeList cNodes  = xmlDoc.GetElementsByTagName("Connectors");
                XmlNodeList nNodes  = xmlDoc.GetElementsByTagName("Notes");

                if (elNodes.Count == 0)
                {
                    elNodes = xmlDoc.GetElementsByTagName("dynElements");
                }
                if (cNodes.Count == 0)
                {
                    cNodes = xmlDoc.GetElementsByTagName("dynConnectors");
                }
                if (nNodes.Count == 0)
                {
                    nNodes = xmlDoc.GetElementsByTagName("dynNotes");
                }

                XmlNode elNodesList = elNodes[0];
                XmlNode cNodesList  = cNodes[0];
                XmlNode nNodesList  = nNodes[0];

                #region instantiate nodes

                foreach (XmlNode elNode in elNodesList.ChildNodes)
                {
                    XmlAttribute typeAttrib          = elNode.Attributes["type"];
                    XmlAttribute guidAttrib          = elNode.Attributes["guid"];
                    XmlAttribute nicknameAttrib      = elNode.Attributes["nickname"];
                    XmlAttribute xAttrib             = elNode.Attributes["x"];
                    XmlAttribute yAttrib             = elNode.Attributes["y"];
                    XmlAttribute lacingAttrib        = elNode.Attributes["lacing"];
                    XmlAttribute isVisAttrib         = elNode.Attributes["isVisible"];
                    XmlAttribute isUpstreamVisAttrib = elNode.Attributes["isUpstreamVisible"];

                    string typeName = typeAttrib.Value;

                    //test the GUID to confirm that it is non-zero
                    //if it is zero, then we have to fix it
                    //this will break the connectors, but it won't keep
                    //propagating bad GUIDs
                    var guid = new Guid(guidAttrib.Value);
                    if (guid == Guid.Empty)
                    {
                        guid = Guid.NewGuid();
                    }

                    string nickname = nicknameAttrib.Value;

                    double x = double.Parse(xAttrib.Value, CultureInfo.InvariantCulture);
                    double y = double.Parse(yAttrib.Value, CultureInfo.InvariantCulture);

                    bool isVisible = true;
                    if (isVisAttrib != null)
                    {
                        isVisible = isVisAttrib.Value == "true" ? true : false;
                    }

                    bool isUpstreamVisible = true;
                    if (isUpstreamVisAttrib != null)
                    {
                        isUpstreamVisible = isUpstreamVisAttrib.Value == "true" ? true : false;
                    }

                    // Retrieve optional 'function' attribute (only for DSFunction).
                    XmlAttribute signatureAttrib = elNode.Attributes["function"];
                    var          signature       = signatureAttrib == null ? null : signatureAttrib.Value;

                    NodeModel  el           = null;
                    XmlElement dummyElement = null;

                    try
                    {
                        // The attempt to create node instance may fail due to "type" being
                        // something else other than "NodeModel" derived object type. This
                        // is possible since some legacy nodes have been made to derive from
                        // "MigrationNode" object type that is not derived from "NodeModel".
                        //
                        typeName = Nodes.Utilities.PreprocessTypeName(typeName);
                        System.Type type = Nodes.Utilities.ResolveType(this.dynamoModel, typeName);
                        if (type != null)
                        {
                            el = ws.NodeFactory.CreateNodeInstance(type, nickname, signature, guid);
                        }

                        if (el != null)
                        {
                            el.Load(elNode);
                        }
                        else
                        {
                            var e = elNode as XmlElement;
                            dummyElement = MigrationManager.CreateMissingNode(e, 1, 1);
                        }
                    }
                    catch (UnresolvedFunctionException)
                    {
                        // If a given function is not found during file load, then convert the
                        // function node into a dummy node (instead of crashing the workflow).
                        //
                        var e = elNode as XmlElement;
                        dummyElement = MigrationManager.CreateUnresolvedFunctionNode(e);
                    }

                    if (dummyElement != null) // If a dummy node placement is desired.
                    {
                        // The new type representing the dummy node.
                        typeName = dummyElement.GetAttribute("type");
                        System.Type type = Dynamo.Nodes.Utilities.ResolveType(this.dynamoModel, typeName);

                        el = ws.NodeFactory.CreateNodeInstance(type, nickname, string.Empty, guid);
                        el.Load(dummyElement);
                    }

                    ws.Nodes.Add(el);

                    el.X = x;
                    el.Y = y;

                    if (lacingAttrib != null)
                    {
                        LacingStrategy lacing = LacingStrategy.First;
                        Enum.TryParse(lacingAttrib.Value, out lacing);
                        el.ArgumentLacing = lacing;
                    }

                    el.DisableReporting();

                    // This is to fix MAGN-3648. Method reference in CBN that gets
                    // loaded before method definition causes a CBN to be left in
                    // a warning state. This is to clear such warnings and set the
                    // node to "Dead" state (correct value of which will be set
                    // later on with a call to "EnableReporting" below). Please
                    // refer to the defect for details and other possible fixes.
                    //
                    if (el.State == ElementState.Warning && (el is CodeBlockNodeModel))
                    {
                        el.State = ElementState.Dead;
                    }

                    el.IsVisible         = isVisible;
                    el.IsUpstreamVisible = isUpstreamVisible;
                }

                #endregion

                #region instantiate connectors

                foreach (XmlNode connector in cNodesList.ChildNodes)
                {
                    XmlAttribute guidStartAttrib = connector.Attributes[0];
                    XmlAttribute intStartAttrib  = connector.Attributes[1];
                    XmlAttribute guidEndAttrib   = connector.Attributes[2];
                    XmlAttribute intEndAttrib    = connector.Attributes[3];
                    XmlAttribute portTypeAttrib  = connector.Attributes[4];

                    var guidStart  = new Guid(guidStartAttrib.Value);
                    var guidEnd    = new Guid(guidEndAttrib.Value);
                    int startIndex = Convert.ToInt16(intStartAttrib.Value);
                    int endIndex   = Convert.ToInt16(intEndAttrib.Value);
                    var portType   = ((PortType)Convert.ToInt16(portTypeAttrib.Value));

                    //find the elements to connect
                    NodeModel start = null;
                    NodeModel end   = null;

                    foreach (NodeModel e in ws.Nodes)
                    {
                        if (e.GUID == guidStart)
                        {
                            start = e;
                        }
                        else if (e.GUID == guidEnd)
                        {
                            end = e;
                        }
                        if (start != null && end != null)
                        {
                            break;
                        }
                    }

                    try
                    {
                        var newConnector = ws.AddConnection(
                            start, end,
                            startIndex, endIndex,
                            portType);
                    }
                    catch
                    {
                        dynamoModel.WriteToLog(string.Format("ERROR : Could not create connector between {0} and {1}.", start.NickName, end.NickName));
                    }
                }

                #endregion

                #region instantiate notes

                if (nNodesList != null)
                {
                    foreach (XmlNode note in nNodesList.ChildNodes)
                    {
                        XmlAttribute textAttrib = note.Attributes[0];
                        XmlAttribute xAttrib    = note.Attributes[1];
                        XmlAttribute yAttrib    = note.Attributes[2];

                        string text = textAttrib.Value;
                        double x    = Convert.ToDouble(xAttrib.Value, CultureInfo.InvariantCulture);
                        double y    = Convert.ToDouble(yAttrib.Value, CultureInfo.InvariantCulture);

                        ws.AddNote(false, x, y, text, Guid.NewGuid());
                    }
                }

                #endregion

                foreach (var e in ws.Nodes)
                {
                    e.EnableReporting();
                }

                def.IsBeingLoaded = false;

                def.Compile(this.dynamoModel, this.dynamoModel.EngineController);

                ws.WatchChanges = true;

                OnGetDefinitionFromPath(def);
            }
            catch (Exception ex)
            {
                dynamoModel.WriteToLog("There was an error opening the workbench.");
                dynamoModel.WriteToLog(ex);

                if (DynamoModel.IsTestMode)
                {
                    throw ex; // Rethrow for NUnit.
                }
                def = null;
                return(false);
            }

            return(true);
        }
コード例 #3
0
        /// <summary>
        ///     Get a guid from a specific path, internally this first calls GetDefinitionFromPath
        /// </summary>
        /// <param name="path">The path from which to get the guid</param>
        /// <param name="guid">A reference to the guid (OUT) Guid.Empty if function returns false. </param>
        /// <returns>Whether we successfully obtained the guid or not.  </returns>
        public static bool GetHeaderFromPath(string path, out Guid guid, out string name, out string category, out string description)
        {
            try
            {
                var funName = "";
                var id      = "";
                var cat     = "";
                var des     = "";

                #region Get xml document and parse

                var xmlDoc = new XmlDocument();
                xmlDoc.Load(path);

                // load the header
                // handle legacy workspace nodes called dynWorkspace
                // and new workspaces without the dyn prefix
                XmlNodeList workspaceNodes = xmlDoc.GetElementsByTagName("Workspace");
                if (workspaceNodes.Count == 0)
                {
                    workspaceNodes = xmlDoc.GetElementsByTagName("dynWorkspace");
                }

                foreach (XmlNode node in workspaceNodes)
                {
                    foreach (XmlAttribute att in node.Attributes)
                    {
                        if (att.Name.Equals("Name"))
                        {
                            funName = att.Value;
                        }
                        else if (att.Name.Equals("ID"))
                        {
                            id = att.Value;
                        }
                        else if (att.Name.Equals("Category"))
                        {
                            cat = att.Value;
                        }
                        else if (att.Name.Equals("Description"))
                        {
                            des = att.Value;
                        }
                    }
                }

                #endregion

                // we have a dyf and it lacks an ID field, we need to assign it
                // a deterministic guid based on its name.  By doing it deterministically,
                // files remain compatible
                if (string.IsNullOrEmpty(id) && !string.IsNullOrEmpty(funName))
                {
                    guid = GuidUtility.Create(GuidUtility.UrlNamespace, funName);
                }
                else
                {
                    guid = Guid.Parse(id);
                }

                name        = funName;
                category    = cat;
                description = des;
                return(true);
            }
            catch (Exception e)
            {
                DynamoLogger.Instance.Log("ERROR: The header for the custom node at " + path + " failed to load.  It will be left out of search.");
                DynamoLogger.Instance.Log(e.ToString());
                category    = "";
                guid        = Guid.Empty;
                name        = "";
                description = "";
                return(false);
            }
        }
コード例 #4
0
        /// <summary>
        ///     Deserialize a function definition from a given path.  A side effect of this function is that
        ///     the node is added to the dictionary of loadedNodes.
        /// </summary>
        /// <param name="funcDefGuid">The function guid we're currently loading</param>
        /// <param name="controller">Reference to the calling controller</param>
        /// <param name="def">The resultant function definition</param>
        /// <returns></returns>
        private bool GetDefinitionFromPath(Guid funcDefGuid, DynamoController controller, out FunctionDefinition def)
        {
            try
            {
                var xmlPath = GetNodePath(funcDefGuid);

                #region read xml file

                var xmlDoc = new XmlDocument();
                xmlDoc.Load(xmlPath);

                string funName     = null;
                string category    = "";
                string description = "";
                double cx          = DynamoView.CANVAS_OFFSET_X;
                double cy          = DynamoView.CANVAS_OFFSET_Y;
                double zoom        = 1.0;
                string id          = "";

                // load the header
                foreach (XmlNode node in xmlDoc.GetElementsByTagName("dynWorkspace"))
                {
                    foreach (XmlAttribute att in node.Attributes)
                    {
                        if (att.Name.Equals("X"))
                        {
                            cx = double.Parse(att.Value, CultureInfo.InvariantCulture);
                        }
                        else if (att.Name.Equals("Y"))
                        {
                            cy = double.Parse(att.Value, CultureInfo.InvariantCulture);
                        }
                        else if (att.Name.Equals("zoom"))
                        {
                            zoom = double.Parse(att.Value, CultureInfo.InvariantCulture);
                        }
                        else if (att.Name.Equals("Name"))
                        {
                            funName = att.Value;
                        }
                        else if (att.Name.Equals("Category"))
                        {
                            category = att.Value;
                        }
                        else if (att.Name.Equals("Description"))
                        {
                            description = att.Value;
                        }
                        else if (att.Name.Equals("ID"))
                        {
                            id = att.Value;
                        }
                    }
                }

                // we have a dyf and it lacks an ID field, we need to assign it
                // a deterministic guid based on its name.  By doing it deterministically,
                // files remain compatible
                if (string.IsNullOrEmpty(id) && !string.IsNullOrEmpty(funName))
                {
                    id = GuidUtility.Create(GuidUtility.UrlNamespace, funName).ToString();
                }

                #endregion

                DynamoCommands.WriteToLogCmd.Execute("Loading node definition for \"" + funName + "\" from: " + xmlPath);

                var ws = new FuncWorkspace(
                    funName, category.Length > 0
                    ? category
                    : BuiltinNodeCategories.SCRIPTING_CUSTOMNODES, description, cx, cy)
                {
                    WatchChanges = false
                };

                ws.Zoom = zoom;

                def = new FunctionDefinition(Guid.Parse(id))
                {
                    Workspace = ws
                };

                // load a dummy version, so any nodes depending on this node
                // will find an (empty) identifier on compilation
                FScheme.Expression dummyExpression = FScheme.Expression.NewNumber_E(0);
                controller.FSchemeEnvironment.DefineSymbol(def.FunctionId.ToString(), dummyExpression);
                this.loadedNodes.Add(def.FunctionId, def);

                XmlNodeList elNodes = xmlDoc.GetElementsByTagName("dynElements");
                XmlNodeList cNodes  = xmlDoc.GetElementsByTagName("dynConnectors");
                XmlNodeList nNodes  = xmlDoc.GetElementsByTagName("dynNotes");

                XmlNode elNodesList = elNodes[0];
                XmlNode cNodesList  = cNodes[0];
                XmlNode nNodesList  = nNodes[0];

                #region instantiate nodes

                var badNodes = new List <Guid>();

                foreach (XmlNode elNode in elNodesList.ChildNodes)
                {
                    XmlAttribute typeAttrib          = elNode.Attributes["type"];
                    XmlAttribute guidAttrib          = elNode.Attributes["guid"];
                    XmlAttribute nicknameAttrib      = elNode.Attributes["nickname"];
                    XmlAttribute xAttrib             = elNode.Attributes["x"];
                    XmlAttribute yAttrib             = elNode.Attributes["y"];
                    XmlAttribute lacingAttrib        = elNode.Attributes["lacing"];
                    XmlAttribute isVisAttrib         = elNode.Attributes["isVisible"];
                    XmlAttribute isUpstreamVisAttrib = elNode.Attributes["isUpstreamVisible"];


                    string typeName = typeAttrib.Value;

                    const string oldNamespace = "Dynamo.Elements.";
                    if (typeName.StartsWith(oldNamespace))
                    {
                        typeName = "Dynamo.Nodes." + typeName.Remove(0, oldNamespace.Length);
                    }

                    //test the GUID to confirm that it is non-zero
                    //if it is zero, then we have to fix it
                    //this will break the connectors, but it won't keep
                    //propagating bad GUIDs
                    var guid = new Guid(guidAttrib.Value);
                    if (guid == Guid.Empty)
                    {
                        guid = Guid.NewGuid();
                    }

                    string nickname = nicknameAttrib.Value;

                    double x = double.Parse(xAttrib.Value, CultureInfo.InvariantCulture);
                    double y = double.Parse(yAttrib.Value, CultureInfo.InvariantCulture);

                    bool isVisible = true;
                    if (isVisAttrib != null)
                    {
                        isVisible = isVisAttrib.Value == "true" ? true : false;
                    }

                    bool isUpstreamVisible = true;
                    if (isUpstreamVisAttrib != null)
                    {
                        isUpstreamVisible = isUpstreamVisAttrib.Value == "true" ? true : false;
                    }

                    //Type t = Type.GetType(typeName);
                    TypeLoadData tData;
                    Type         t;

                    if (!controller.BuiltInTypesByName.TryGetValue(typeName, out tData))
                    {
                        //try and get a system type by this name
                        t = Type.GetType(typeName);

                        //if we still can't find the type, try the also known as attributes
                        if (t == null)
                        {
                            //try to get the also known as values
                            foreach (KeyValuePair <string, TypeLoadData> kvp in controller.BuiltInTypesByName)
                            {
                                var akaAttribs = kvp.Value.Type.GetCustomAttributes(typeof(AlsoKnownAsAttribute), false);
                                if (akaAttribs.Any())
                                {
                                    if ((akaAttribs[0] as AlsoKnownAsAttribute).Values.Contains(typeName))
                                    {
                                        controller.DynamoViewModel.Log(string.Format("Found matching node for {0} also known as {1}", kvp.Key, typeName));
                                        t = kvp.Value.Type;
                                    }
                                }
                            }
                        }

                        if (t == null)
                        {
                            controller.DynamoViewModel.Log("Could not load node of type: " + typeName);
                            controller.DynamoViewModel.Log("Loading will continue but nodes might be missing from your workflow.");

                            //return false;
                            badNodes.Add(guid);
                            continue;
                        }
                    }
                    else
                    {
                        t = tData.Type;
                    }

                    dynNodeModel el = dynSettings.Controller.DynamoViewModel.CreateNodeInstance(t, nickname, guid);

                    if (lacingAttrib != null)
                    {
                        LacingStrategy lacing = LacingStrategy.First;
                        Enum.TryParse(lacingAttrib.Value, out lacing);
                        el.ArgumentLacing = lacing;
                    }

                    el.IsVisible         = isVisible;
                    el.IsUpstreamVisible = isUpstreamVisible;

                    // note - this is because the connectors fail to be created if there's not added
                    // to the canvas
                    ws.Nodes.Add(el);
                    el.WorkSpace = ws;
                    var node = el;

                    node.X = x;
                    node.Y = y;

                    if (el == null)
                    {
                        return(false);
                    }

                    el.DisableReporting();
                    el.Load(elNode); // inject the node properties from the xml

                    // moved this logic to LoadNode in dynFunction --SJE

                    //if (el is dynFunction)
                    //{
                    //    var fun = el as dynFunction;

                    //    // we've found a custom node, we need to attempt to load its guid.
                    //    // if it doesn't exist (i.e. its a legacy node), we need to assign it one,
                    //    // deterministically
                    //    Guid funId;
                    //    try
                    //    {
                    //        funId = Guid.Parse(fun.Symbol);
                    //    }
                    //    catch
                    //    {
                    //        funId = GuidUtility.Create(GuidUtility.UrlNamespace, nicknameAttrib.Value);
                    //        fun.Symbol = funId.ToString();
                    //    }

                    //    // if it's not a recurisve node and it's not yet loaded, load it
                    //    if (funcDefGuid != funId && !this.loadedNodes.ContainsKey(funId))
                    //    {
                    //        dynSettings.Controller.CustomNodeLoader.GetFunctionDefinition(funId);
                    //        fun.Definition = this.loadedNodes[funId];
                    //    }
                    //    else if ( this.loadedNodes.ContainsKey(funId ))
                    //    {
                    //        fun.Definition = this.loadedNodes[funId];
                    //    }

                    //}
                }

                #endregion

                #region instantiate connectors

                foreach (XmlNode connector in cNodesList.ChildNodes)
                {
                    XmlAttribute guidStartAttrib = connector.Attributes[0];
                    XmlAttribute intStartAttrib  = connector.Attributes[1];
                    XmlAttribute guidEndAttrib   = connector.Attributes[2];
                    XmlAttribute intEndAttrib    = connector.Attributes[3];
                    XmlAttribute portTypeAttrib  = connector.Attributes[4];

                    var guidStart  = new Guid(guidStartAttrib.Value);
                    var guidEnd    = new Guid(guidEndAttrib.Value);
                    int startIndex = Convert.ToInt16(intStartAttrib.Value);
                    int endIndex   = Convert.ToInt16(intEndAttrib.Value);
                    int portType   = Convert.ToInt16(portTypeAttrib.Value);

                    //find the elements to connect
                    dynNodeModel start = null;
                    dynNodeModel end   = null;

                    if (badNodes.Contains(guidStart) || badNodes.Contains(guidEnd))
                    {
                        continue;
                    }

                    foreach (dynNodeModel e in ws.Nodes)
                    {
                        if (e.GUID == guidStart)
                        {
                            start = e;
                        }
                        else if (e.GUID == guidEnd)
                        {
                            end = e;
                        }
                        if (start != null && end != null)
                        {
                            break;
                        }
                    }

                    try
                    {
                        var newConnector = dynConnectorModel.Make(
                            start, end,
                            startIndex, endIndex,
                            portType);
                        if (newConnector != null)
                        {
                            ws.Connectors.Add(newConnector);
                        }
                    }
                    catch
                    {
                        DynamoCommands.WriteToLogCmd.Execute(string.Format("ERROR : Could not create connector between {0} and {1}.", start.NickName, end.NickName));
                    }
                }

                #endregion

                #region instantiate notes

                if (nNodesList != null)
                {
                    foreach (XmlNode note in nNodesList.ChildNodes)
                    {
                        XmlAttribute textAttrib = note.Attributes[0];
                        XmlAttribute xAttrib    = note.Attributes[1];
                        XmlAttribute yAttrib    = note.Attributes[2];

                        string text = textAttrib.Value;
                        double x    = Convert.ToDouble(xAttrib.Value);
                        double y    = Convert.ToDouble(yAttrib.Value);

                        //dynNoteView n = Bench.AddNote(text, x, y, ws);
                        //Bench.AddNote(text, x, y, ws);

                        var paramDict = new Dictionary <string, object>();
                        paramDict.Add("x", x);
                        paramDict.Add("y", y);
                        paramDict.Add("text", text);
                        paramDict.Add("workspace", ws);
                        dynSettings.Controller.DynamoViewModel.AddNoteCommand.Execute(paramDict);
                    }
                }

                #endregion

                foreach (dynNodeModel e in ws.Nodes)
                {
                    e.EnableReporting();
                }

                ws.FilePath = xmlPath;

                var expression = CompileFunction(def);
                controller.FSchemeEnvironment.DefineSymbol(def.FunctionId.ToString(), expression);

                ws.WatchChanges = true;
            }
            catch (Exception ex)
            {
                DynamoCommands.WriteToLogCmd.Execute("There was an error opening the workbench.");
                DynamoCommands.WriteToLogCmd.Execute(ex);

                if (controller.Testing)
                {
                    Assert.Fail(ex.Message);
                }

                def = null;
                return(false);
            }

            return(true);
        }