예제 #1
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 TreeReference anchor(TreeReference contextRef)
 {
     if (isAbsolute())
     {
         return(this.clone());
     }
     else if (!contextRef.isAbsolute())
     {
         return(null);
     }
     else
     {
         TreeReference newRef      = contextRef.clone();
         int           contextSize = contextRef.size();
         if (refLevel > contextSize)
         {
             return(null); //tried to do '/..'
         }
         else
         {
             for (int i = 0; i < refLevel; i++)
             {
                 newRef.removeLastLevel();
             }
             for (int i = 0; i < size(); i++)
             {
                 newRef.add(this.getName(i), this.getMultiplicity(i));
             }
             return(newRef);
         }
     }
 }
예제 #2
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");
        }
예제 #3
0
        public TreeReference getParentRef()
        {
            //TODO: level
            TreeReference ref_ = this.clone();

            if (ref_.removeLastLevel())
            {
                return(ref_);
            }
            else
            {
                return(null);
            }
        }
예제 #4
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);
                }
            }
        }