示例#1
0
        /// <summary>
        /// Event handler that is called when the document node has disposed or name changed. Because the path to the node can have changed too,
        /// the path is renewed in this case.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="source">Source of the tunneled event.</param>
        /// <param name="e"></param>
        private void EhDocNode_TunneledEvent(object sender, object source, Main.TunnelingEventArgs e)
        {
            if (IsDisposeInProgress)
            {
                return;
            }

#if DEBUG_DOCNODEPROXYLOGGING
            Current.Console.WriteLine("DocNodeProxy.EhDocNode_TunneledEvent: sender={0}, source={1} e={2}", sender, source, e);
#endif

            bool shouldFireChangedEvent = false;

            var senderAsNode = source as IDocumentLeafNode;
            if (!(senderAsNode != null))
            {
                throw new InvalidProgramException();
            }

            if (e is DisposeEventArgs)
            {
                // when our DocNode was disposed, it is probable that the parent of this node (and further parents) are disposed too
                // thus we need to watch the first node that is not disposed
                var docNode = InternalDocumentNode;
                ClearDocNode();

                if (!(sender is IProject)) // if the whole project is disposed, there is no point in trying to watch something
                {
                    // note Dispose is designed to let the hierarchy from child to parent (root) valid, but not from root to child!
                    // thus trying to get an actual document path here is in must cases unsuccessfull. We have to rely on our stored path, and that it was always updated!
                    // the only case were it is successfull if a new node immediately replaces an old document node
                    var node = AbsoluteDocumentPath.GetNodeOrLeastResolveableNode(_docNodePath, senderAsNode, out var wasResolvedCompletely);
                    if (wasResolvedCompletely)
                    {
                        SetDocNode(node);
                    }
                    else
                    {
                        SetWatchOnNode(node);
                    }

                    shouldFireChangedEvent = true;
                }
            }
            else if (e is DocumentPathChangedEventArgs)
            {
                if (null != InternalDocumentNode)
                {
                    InternalDocumentPath = Main.AbsoluteDocumentPath.GetAbsolutePath(InternalDocumentNode);
                    InternalCheckAbsolutePath();
                }

                shouldFireChangedEvent = true;
            }

            if (shouldFireChangedEvent)
            {
                EhSelfChanged(EventArgs.Empty);
            }
        }
示例#2
0
        /// <summary>
        /// Replaces parts of the part by another part.
        /// </summary>
        /// <param name="partToReplace">Part of the path that should be replaced. This part has to match the beginning of this part. The last item of the part
        /// is allowed to be given only partially.</param>
        /// <param name="newPart">The new part to replace that piece of the path, that match the <c>partToReplace</c>.</param>
        /// <param name="newPath">The resulting new path (if the return value is <c>true</c>), or the original path, if the return value is <c>false</c>.</param>
        /// <returns>True if the part could be replaced. Returns false if the path does not fulfill the presumtions given above.</returns>
        /// <remarks>
        /// As stated above, the last item of the partToReplace can be given only partially. As an example, the path (here separated by space)
        /// <para>Tables Preexperiment1/WDaten Time</para>
        /// <para>should be replaced by </para>
        /// <para>Tables Preexperiment2\WDaten Time</para>
        /// <para>To make this replacement, the partToReplace should be given by</para>
        /// <para>Tables Preexperiment1/</para>
        /// <para>and the newPart should be given by</para>
        /// <para>Tables Preexperiment2\</para>
        /// <para>Note that Preexperiment1\ and Preexperiment2\ are only partially defined items of the path.</para>
        /// </remarks>
        public bool ReplacePathParts(AbsoluteDocumentPath partToReplace, AbsoluteDocumentPath newPart, out AbsoluteDocumentPath newPath)
        {
            newPath = this;
            // Test if the start of my path is identical to that of partToReplace
            if (Count < partToReplace.Count)
            {
                return(false);
            }

            for (int i = 0; i < partToReplace.Count - 1; i++)
            {
                if (0 != string.Compare(this[i], partToReplace[i]))
                {
                    return(false);
                }
            }

            if (!this[partToReplace.Count - 1].StartsWith(partToReplace[partToReplace.Count - 1]))
            {
                return(false);
            }

            // ok, the beginning of my path and partToReplace is identical,
            // thus we replace the beginning of my path with that of newPart

            var    list = new List <string>(_pathParts);
            string s    = list[partToReplace.Count - 1].Substring(partToReplace[partToReplace.Count - 1].Length);

            list[partToReplace.Count - 1] = newPart[newPart.Count - 1] + s;

            int j, k;

            for (j = partToReplace.Count - 2, k = newPart.Count - 2; j >= 0 && k >= 0; --j, --k)
            {
                list[j] = newPart[k];
            }

            if (k > 0)
            {
                for (; k >= 0; --k)
                {
                    list.Insert(0, newPart[k]);
                }
            }
            else if (j > 0)
            {
                for (; j >= 0; --j)
                {
                    list.RemoveAt(0);
                }
            }

            newPath = new AbsoluteDocumentPath(list.ToArray());
            return(true);
        }
示例#3
0
        /// <summary>
        /// Resolves the path by first using startnode as starting point. If that failed, try using documentRoot as starting point.
        /// </summary>
        /// <param name="path">The path to resolve.</param>
        /// <param name="startnode">The node object which is considered as the starting point of the path.</param>
        /// <param name="documentRoot">An alternative node which is used as starting point of the path if the first try failed.</param>
        /// <returns>The resolved object. If the resolving process failed, the return value is null.</returns>
        public static IDocumentLeafNode GetObject(AbsoluteDocumentPath path, IDocumentLeafNode startnode, IDocumentNode documentRoot)
        {
            var retval = GetObject(path, startnode);

            if (null == retval && null != documentRoot)
            {
                retval = GetObject(path, documentRoot);
            }

            return(retval);
        }
示例#4
0
        private void SortItemsByDependencyProxyReporter(IProxy proxy, object owner, string propertyName, HashSet <IProjectItem> dependenciesOfItem)
        {
            var proxyDoc = proxy?.DocumentObject as IDocumentLeafNode;

            if (proxyDoc != null)
            {
                var dependentOnItem = AbsoluteDocumentPath.GetRootNodeImplementing <IProjectItem>(proxyDoc);
                if (null != dependentOnItem)
                {
                    dependenciesOfItem.Add(dependentOnItem);
                }
            }
        }
示例#5
0
        /// <summary>
        /// Gets the node that is designated by the provided <paramref name="path"/>  or the least resolveable node.
        /// </summary>
        /// <param name="path">The document path to resolve.</param>
        /// <param name="startnode">The startnode.</param>
        /// <param name="pathWasCompletelyResolved">If set to <c>true</c> on return, the path was completely resolved. Otherwise, <c>false</c>.</param>
        /// <returns>The resolved node, or the least node on the path that could be resolved.</returns>
        /// <exception cref="System.ArgumentNullException">
        /// path
        /// or
        /// startnode
        /// </exception>
        public static IDocumentLeafNode GetNodeOrLeastResolveableNode(AbsoluteDocumentPath path, IDocumentLeafNode startnode, out bool pathWasCompletelyResolved)
        {
            if (null == path)
            {
                throw new ArgumentNullException("path");
            }
            if (null == startnode)
            {
                throw new ArgumentNullException("startnode");
            }

            var node = startnode;

            node = GetRootNode(node);
            if (null == node)
            {
                throw new InvalidProgramException("startnote is not rooted");
            }

            var prevNode = node;

            pathWasCompletelyResolved = true;

            for (int i = 0; i < path.Count; i++)
            {
                prevNode = node;
                if (path[i] == "..")
                {
                    node = node.ParentObject;
                }
                else
                {
                    if (node is Main.IDocumentNode)
                    {
                        node = ((Main.IDocumentNode)node).GetChildObjectNamed(path[i]);
                    }
                    else
                    {
                        node = null;
                    }
                }

                if (node == null)
                {
                    pathWasCompletelyResolved = false;
                    break;
                }
            } // end for

            return(node ?? prevNode);
        }
示例#6
0
        public AbsoluteDocumentPath Append(AbsoluteDocumentPath other)
        {
            if (null == other)
            {
                throw new ArgumentNullException("other");
            }

            var arr = new string[_pathParts.Length + other._pathParts.Length];

            Array.Copy(_pathParts, arr, _pathParts.Length);
            Array.Copy(other._pathParts, 0, arr, _pathParts.Length, other._pathParts.Length);

            return(new AbsoluteDocumentPath(arr));
        }
示例#7
0
        public bool StartsWith(AbsoluteDocumentPath another)
        {
            if (Count < another.Count)
            {
                return(false);
            }

            for (int i = 0; i < another.Count; ++i)
            {
                if (this[i] != another[i])
                {
                    return(false);
                }
            }

            return(true);
        }
示例#8
0
        /// <summary>
        /// Event handler that is called when the watched node (a node that is not the document node) has changed. Maybe this watched node had now created a parent node, and our
        /// document path can resolved now. That's why we try to resolve our document path now.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void EhWatchedNode_Changed(object sender, EventArgs e)
        {
            if (IsDisposeInProgress)
            {
                return;
            }

#if DEBUG_DOCNODEPROXYLOGGING
            Current.Console.WriteLine("DocNodeProxy.EhWatchedNode_Changed: sender={0}, e={1}", sender, e);
#endif

            if (!(InternalDocumentNode == null))
            {
                throw new InvalidProgramException();
            }

            var senderAsDocNode = sender as IDocumentLeafNode;
            if (!(senderAsDocNode != null))
            {
                throw new InvalidProgramException();
            }


            var node = AbsoluteDocumentPath.GetNodeOrLeastResolveableNode(_docNodePath, senderAsDocNode, out var wasResolvedCompletely);
            if (null == node)
            {
                throw new InvalidProgramException("node should always be != null, since we use absolute paths, and at least an AltaxoDocument should be resolved here.");
            }

            if (wasResolvedCompletely)
            {
                ClearWatch();
                SetDocNode(node);
            }
            else // not completely resolved
            {
                if (!object.ReferenceEquals(sender, node))
                {
                    ClearWatch();
                    SetWatchOnNode(node);
                }
            }
        }
示例#9
0
        public static IDocumentLeafNode GetObject(AbsoluteDocumentPath path, IDocumentLeafNode startnode)
        {
            if (null == path)
            {
                throw new ArgumentNullException("path");
            }
            if (null == startnode)
            {
                throw new ArgumentNullException("startnode");
            }

            var node = startnode;

            node = GetRootNode(node);

            for (int i = 0; i < path.Count; i++)
            {
                if (path[i] == "..")
                {
                    if (null != node)
                    {
                        node = node.ParentObject;
                    }
                    else
                    {
                        return(null);
                    }
                }
                else
                {
                    if (node is Main.IDocumentNode)
                    {
                        node = ((Main.IDocumentNode)node).GetChildObjectNamed(path[i]);
                    }
                    else
                    {
                        return(null);
                    }
                }
            } // end for
            return(node);
        }
示例#10
0
        /// <summary>
        /// Replaces parts of the part of the document node by another part. If the replacement was successful, the original document node is cleared.
        /// See <see cref="M:DocumentPath.ReplacePathParts"/> for details of the part replacement.
        /// </summary>
        /// <param name="partToReplace">Part of the path that should be replaced. This part has to match the beginning of this part. The last item of the part
        /// is allowed to be given only partially.</param>
        /// <param name="newPart">The new part to replace that piece of the path, that match the <c>partToReplace</c>.</param>
        /// <param name="rootNode">Any document node in the hierarchy that is used to find the root node of the hierarchy.</param>
        /// <returns>True if the path could be replaced. Returns false if the path does not fulfill the presumptions given above.</returns>
        /// <remarks>
        /// As stated above, the last item of the partToReplace can be given only partially. As an example, the path (here separated by space)
        /// <para>Tables Preexperiment1/WDaten Time</para>
        /// <para>should be replaced by </para>
        /// <para>Tables Preexperiment2\WDaten Time</para>
        /// <para>To make this replacement, the partToReplace should be given by</para>
        /// <para>Tables Preexperiment1/</para>
        /// <para>and the newPart should be given by</para>
        /// <para>Tables Preexperiment2\</para>
        /// <para>Note that Preexperiment1\ and Preexperiment2\ are only partially defined items of the path.</para>
        /// </remarks>
        public bool ReplacePathParts(AbsoluteDocumentPath partToReplace, AbsoluteDocumentPath newPart, IDocumentLeafNode rootNode)
        {
            if (!(_docNodePath != null || IsDisposeInProgress))
            {
                throw new InvalidProgramException();
            }
            if (null == rootNode)
            {
                throw new ArgumentNullException(nameof(rootNode));
            }

            var success = _docNodePath.ReplacePathParts(partToReplace, newPart, out var newPath);

            if (success)
            {
                _docNodePath = newPath;
                ClearDocNode();
                ResolveDocumentObject(rootNode);
            }

            return(success);
        }
示例#11
0
        public static RelativeDocumentPath FromOldDeprecated(AbsoluteDocumentPath absPath)
        {
            if (null == absPath)
            {
                throw new ArgumentNullException(nameof(absPath));
            }

            int numberOfLevelsDown = 0;
            var pathList           = new List <string>();

            for (int i = 0; i < absPath.Count; ++i)
            {
                if (absPath[i] == "..")
                {
                    numberOfLevelsDown++;
                }
                else
                {
                    pathList.Add(absPath[i]);
                }
            }
            return(new RelativeDocumentPath(numberOfLevelsDown, pathList));
        }
示例#12
0
        /// <summary>
        /// Get the absolute path of the node <code>node</code> starting from the root.
        /// </summary>
        /// <param name="node">The node for which the path is retrieved.</param>
        /// <returns>The absolute path of the node. The first element is a "/" to mark this as absolute path.</returns>
        public static AbsoluteDocumentPath GetAbsolutePath(IDocumentLeafNode node)
        {
            AbsoluteDocumentPath path = GetPath(node, int.MaxValue);

            return(path);
        }
示例#13
0
 /// <summary>
 /// Adds a replacement entry for a project item. The paths given should be complete paths of the project item (original path and new path).
 /// </summary>
 /// <param name="originalPath">The original path of the project item (DataTable, Graph, ProjectFolderPropertyBag).</param>
 /// <param name="newPath">The new path of the project item.</param>
 public void AddProjectItemReplacement(AbsoluteDocumentPath originalPath, AbsoluteDocumentPath newPath)
 {
     _itemRelocationDictionary.Add(originalPath, newPath);
 }
示例#14
0
        /// <summary>
        /// Event handler that is called when the watched node or a parent node below has disposed or its name changed. We then try to resolve the path again.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="source">Source of the tunneled event.</param>
        /// <param name="e"></param>
        private void EhWatchedNode_TunneledEvent(object sender, object source, Main.TunnelingEventArgs e)
        {
            if (IsDisposeInProgress)
            {
                return;
            }

            if (!(InternalDocumentNode == null))
            {
                throw new InvalidProgramException();
            }
            var senderAsDocNode = sender as IDocumentLeafNode;
            var sourceAsDocNode = source as IDocumentLeafNode;

            if (!(senderAsDocNode != null))
            {
                throw new InvalidProgramException();
            }
            if (!(sourceAsDocNode != null))
            {
                throw new InvalidProgramException();
            }

            if (e is DocumentPathChangedEventArgs) // here, we activly change our stored path, if the watched node or a parent has changed its name
            {
                var watchedPath = AbsoluteDocumentPath.GetAbsolutePath(senderAsDocNode);
                watchedPath = watchedPath.Append(_docNodePath.SubPath(watchedPath.Count, _docNodePath.Count - watchedPath.Count));
                var oldPath = _docNodePath;
                _docNodePath = watchedPath;

#if DEBUG_DOCNODEPROXYLOGGING
                Current.Console.WriteLine("DocNodeProxy.EhWatchedNode_TunneledEvent: Modified path, oldpath={0}, newpath={1}", oldPath, _docNodePath);
#endif
            }

            // then we try to resolve the path again
            if ((e is DisposeEventArgs) || (e is DocumentPathChangedEventArgs))
            {
#if DEBUG_DOCNODEPROXYLOGGING
                Current.Console.WriteLine("DocNodeProxy.EhWatchedNode_TunneledEvent");
#endif

                var node = AbsoluteDocumentPath.GetNodeOrLeastResolveableNode(_docNodePath, sourceAsDocNode, out var wasResolvedCompletely);
                if (null == node)
                {
                    throw new InvalidProgramException(nameof(node) + " should always be != null, since we use absolute paths, and at least an AltaxoDocument should be resolved here.");
                }

                if (wasResolvedCompletely)
                {
                    ClearWatch();
                    SetDocNode(node);
                }
                else // not completely resolved
                {
                    if (!object.ReferenceEquals(sender, node))
                    {
                        ClearWatch();
                        SetWatchOnNode(node);
                    }
                }
            }
        }
示例#15
0
        /// <summary>
        /// Sets the watch on a node that is not our document node, but a node lower in the hierarchy. We watch both the Changed event and the TunneledEvent of this node.
        /// </summary>
        /// <param name="node">The node to watch.</param>
        protected virtual void SetWatchOnNode(IDocumentLeafNode node)
        {
#if DOCNODEPROXY_CONCURRENTDEBUG
            int debugUsn = System.Threading.Interlocked.Increment(ref _debugUSN);
            _debug.Enqueue("START SetWatchOnNode " + debugUsn.ToString());
#endif

            if (null == node)
            {
                throw new ArgumentNullException(nameof(node));
            }

            if (null != _weakDocNodeChangedHandler)
            {
                _weakDocNodeChangedHandler.Remove();
                _weakDocNodeChangedHandler = null;
            }
            if (null != _weakDocNodeTunneledEventHandler)
            {
                _weakDocNodeTunneledEventHandler.Remove();
                _weakDocNodeTunneledEventHandler = null;
            }

            node.TunneledEvent += (_weakDocNodeTunneledEventHandler = new WeakActionHandler <object, object, TunnelingEventArgs>(EhWatchedNode_TunneledEvent, handler => node.TunneledEvent -= handler));
            node.Changed       += (_weakDocNodeChangedHandler = new WeakEventHandler(EhWatchedNode_Changed, handler => node.Changed -= handler));

#if DEBUG_DOCNODEPROXYLOGGING
            Current.Console.WriteLine("Start watching node <<{0}>> of total path <<{1}>>", AbsoluteDocumentPath.GetAbsolutePath(node), _docNodePath);
#endif

#if DOCNODEPROXY_CONCURRENTDEBUG
            _debug.Enqueue("STOP  SetWatchOnNode " + debugUsn.ToString() + (_docNodeRef == null).ToString());
#endif
        }
示例#16
0
        /// <summary>
        /// Sets the watch on a node that is not our document node, but a node lower in the hierarchy. We watch both the Changed event and the TunneledEvent of this node.
        /// </summary>
        /// <param name="node">The node to watch.</param>
        protected virtual void SetWatchOnNode(IDocumentLeafNode node)
        {
            if (null == node)
            {
                throw new ArgumentNullException(nameof(node));
            }

            if (null != _weakDocNodeChangedHandler)
            {
                _weakDocNodeChangedHandler.Remove();
                _weakDocNodeChangedHandler = null;
            }
            if (null != _weakDocNodeTunneledEventHandler)
            {
                _weakDocNodeTunneledEventHandler.Remove();
                _weakDocNodeTunneledEventHandler = null;
            }

            node.TunneledEvent += (_weakDocNodeTunneledEventHandler = new WeakActionHandler <object, object, TunnelingEventArgs>(EhWatchedNode_TunneledEvent, handler => node.TunneledEvent -= handler));
            node.Changed       += (_weakDocNodeChangedHandler = new WeakEventHandler(EhWatchedNode_Changed, handler => node.Changed -= handler));

#if DEBUG_DOCNODEPROXYLOGGING
            Current.Console.WriteLine("Start watching node <<{0}>> of total path <<{1}>>", AbsoluteDocumentPath.GetAbsolutePath(node), _docNodePath);
#endif
        }
示例#17
0
 public AbsoluteDocumentPath(AbsoluteDocumentPath from)
 {
     _pathParts = (string[])from._pathParts.Clone();
 }