Esempio n. 1
0
        /// <summary>Intersect this tree reference with another, returning a new tree reference
        /// which contains all of the common elements, starting with the root element.
        ///
        /// Note that relative references by their nature can't share steps, so intersecting
        /// any (or by any) relative ref will result in the root ref. Additionally, if the
        /// two references don't share any steps, the intersection will consist of the root
        /// reference.
        ///
        /// </summary>
        /// <param name="b">The tree reference to intersect
        /// </param>
        /// <returns> The tree reference containing the common basis of this ref and b
        /// </returns>
        public virtual TreeReference intersect(TreeReference b)
        {
            if (!this.Absolute || !b.Absolute)
            {
                return(TreeReference.rootRef());
            }
            if (this.Equals(b))
            {
                return(this);
            }


            TreeReference a;

            //A should always be bigger if one ref is larger than the other
            if (this.size() < b.size())
            {
                a = b.Clone(); b = this.Clone();
            }
            else
            {
                a = this.Clone(); b = b.Clone();
            }

            //Now, trim the refs to the same length.
            int diff = a.size() - b.size();

            for (int i = 0; i < diff; ++i)
            {
                a.removeLastLevel();
            }

            int aSize = a.size();

            //easy, but requires a lot of re-evaluation.
            for (int i = 0; i <= aSize; ++i)
            {
                if (a.Equals(b))
                {
                    return(a);
                }
                else if (a.size() == 0)
                {
                    return(TreeReference.rootRef());
                }
                else
                {
                    if (!a.removeLastLevel() || !b.removeLastLevel())
                    {
                        //I don't think it should be possible for us to get here, so flip if we do
                        throw new System.SystemException("Dug too deply into TreeReference during intersection");
                    }
                }
            }

            //The only way to get here is if a's size is -1
            throw new System.SystemException("Impossible state");
        }
Esempio n. 2
0
        //return a new reference that is this reference anchored to a passed-in parent reference
        //if this reference is absolute, return self
        //if this ref has 'parent' steps (..), it can only be anchored if the parent ref is a relative ref consisting only of other 'parent' steps
        //return null in these invalid situations
        public virtual TreeReference parent(TreeReference parentRef)
        {
            if (Absolute)
            {
                return(this);
            }
            else
            {
                TreeReference newRef = parentRef.Clone();

                if (refLevel > 0)
                {
                    if (!parentRef.Absolute && parentRef.size() == 0)
                    {
                        parentRef.refLevel += refLevel;
                    }
                    else
                    {
                        return(null);
                    }
                }


                for (TreeReferenceLevel l: data)
                {
                    newRef.add(l.shallowCopy());
                }

                return(newRef);
            }
        }
Esempio n. 3
0
        //very similar to parent(), but assumes contextRef refers to a singular, existing node in the model
        //this means we can do '/a/b/c + ../../d/e/f = /a/d/e/f', which we couldn't do in parent()
        //return null if context ref is not absolute, or we parent up past the root node
        //NOTE: this function still works even when contextRef contains INDEX_UNBOUND multiplicites... conditions depend on this behavior,
        //  even though it's slightly icky
        public virtual TreeReference anchor(TreeReference contextRef)
        {
            //TODO: Technically we should possibly be modifying context stuff here
            //instead of in the xpath stuff;

            if (Absolute)
            {
                return(this.Clone());
            }
            else if (!contextRef.Absolute)
            {
                throw new XPathException("Could not resolve " + this.toString(true));
            }
            else
            {
                TreeReference newRef      = contextRef.Clone();
                int           contextSize = contextRef.size();
                if (refLevel > contextSize)
                {
                    //tried to do '/..'
                    throw new XPathException("Could not resolve " + this.toString(true));
                }
                else
                {
                    for (int i = 0; i < refLevel; i++)
                    {
                        newRef.removeLastLevel();
                    }
                    for (int i = 0; i < size(); i++)
                    {
                        newRef.add(data.elementAt(i).shallowCopy());
                    }
                    return(newRef);
                }
            }
        }