Beispiel #1
0
        /// <summary>
        ///     Merges this ContentLocator with a ContentLocatorBase.  If other is a
        ///     ContentLocatorGroup, each of its Locators are added to clones of
        ///     this ContentLocatorBase and are added to a new ContentLocatorGroup which is
        ///     returned.  If other is a ContentLocatorBase, its appended to this
        ///     ContentLocatorBase and this ContentLocatorBase is returned.
        ///     Both operation modify this ContentLocatorBase.
        /// </summary>
        /// <param name="other">the ContentLocatorBase to merge with</param>
        /// <returns>a ContentLocatorBase containing the final merged product</returns>
        internal override ContentLocatorBase Merge(ContentLocatorBase other)
        {
            if (other == null)
            {
                return(this);
            }

            ContentLocatorGroup locatorGroup = other as ContentLocatorGroup;

            if (locatorGroup != null)
            {
                ContentLocatorGroup newGroup = new ContentLocatorGroup();

                ContentLocator temp = null;
                // Create n-1 clones of this LPS and append all but one
                // LPSs in the set to the clones, adding the clones to a
                // new ContentLocatorGroup
                foreach (ContentLocator loc in locatorGroup.Locators)
                {
                    if (temp == null)
                    {
                        temp = loc;
                    }
                    else
                    {
                        ContentLocator clone = (ContentLocator)this.Clone();
                        clone.Append(loc);
                        newGroup.Locators.Add(clone);
                    }
                }

                // Finally, add the remaining LPS in the set to this LPS
                // and add this to the new ContentLocatorGroup
                if (temp != null)
                {
                    this.Append(temp);
                    newGroup.Locators.Add(this);
                }

                if (newGroup.Locators.Count == 0)
                {
                    return(this);
                }
                else
                {
                    return(newGroup);
                }
            }
            else
            {
                // Safe cast - ContentLocator only has two subclasses
                this.Append((ContentLocator)other);
                return(this);
            }
        }
Beispiel #2
0
        //------------------------------------------------------
        //
        //  Internal Methods
        //
        //------------------------------------------------------

        #region Internal Methods

        /// <summary>
        ///     Merges the ContentLocatorGroup with a ContentLocatorBase.  If other is a ContentLocatorBase,
        ///     it is added to the end of every ContentLocatorBase in this ContentLocatorGroup.
        ///     If other is a ContentLocatorGroup, then each ContentLocatorBase in it must be added to
        ///     each ContentLocatorBase (or a clone) in this ContentLocatorGroup.  The result is this
        ///     ContentLocatorGroup will contain n*m ContentLocatorBase.
        ///     In both cases, this ContentLocatorGroup is modified.
        /// </summary>
        /// <param name="other">other ContentLocatorBase to merge with</param>
        /// <returns>this ContentLocatorGroup</returns>
        internal override ContentLocatorBase Merge(ContentLocatorBase other)
        {
            if (other == null)
            {
                return(this);
            }

            ContentLocator      firstRight   = null;
            ContentLocatorGroup locatorGroup = other as ContentLocatorGroup;

            if (locatorGroup != null)
            {
                List <ContentLocatorBase> tempList = new List <ContentLocatorBase>(locatorGroup.Locators.Count * (this.Locators.Count - 1));
                foreach (ContentLocator left in this.Locators)
                {
                    foreach (ContentLocator right in locatorGroup.Locators)
                    {
                        if (firstRight == null)
                        {
                            firstRight = right;
                        }
                        else
                        {
                            ContentLocator clone = (ContentLocator)left.Clone();
                            clone.Append(right);
                            tempList.Add(clone);
                        }
                    }

                    // No need to clone or add here - just use the locator
                    // already in the ContentLocatorGroup
                    left.Append(firstRight);
                    firstRight = null;
                }

                foreach (ContentLocator list in tempList)
                {
                    this.Locators.Add(list);
                }
            }
            else
            {
                ContentLocator otherLoc = other as ContentLocator;
                Invariant.Assert(otherLoc != null, "other should be of type ContentLocator");  // Only other possible type for the ContentLocatorBase

                foreach (ContentLocator loc in this.Locators)
                {
                    loc.Append(otherLoc);
                }
            }
            return(this);
        }
        // Token: 0x06006347 RID: 25415 RVA: 0x001BED58 File Offset: 0x001BCF58
        internal override ContentLocatorBase Merge(ContentLocatorBase other)
        {
            if (other == null)
            {
                return(this);
            }
            ContentLocator      contentLocator      = null;
            ContentLocatorGroup contentLocatorGroup = other as ContentLocatorGroup;

            if (contentLocatorGroup != null)
            {
                List <ContentLocatorBase> list = new List <ContentLocatorBase>(contentLocatorGroup.Locators.Count * (this.Locators.Count - 1));
                foreach (ContentLocator contentLocator2 in this.Locators)
                {
                    foreach (ContentLocator contentLocator3 in contentLocatorGroup.Locators)
                    {
                        if (contentLocator == null)
                        {
                            contentLocator = contentLocator3;
                        }
                        else
                        {
                            ContentLocator contentLocator4 = (ContentLocator)contentLocator2.Clone();
                            contentLocator4.Append(contentLocator3);
                            list.Add(contentLocator4);
                        }
                    }
                    contentLocator2.Append(contentLocator);
                    contentLocator = null;
                }
                using (List <ContentLocatorBase> .Enumerator enumerator3 = list.GetEnumerator())
                {
                    while (enumerator3.MoveNext())
                    {
                        ContentLocatorBase contentLocatorBase = enumerator3.Current;
                        ContentLocator     item = (ContentLocator)contentLocatorBase;
                        this.Locators.Add(item);
                    }
                    return(this);
                }
            }
            ContentLocator contentLocator5 = other as ContentLocator;

            Invariant.Assert(contentLocator5 != null, "other should be of type ContentLocator");
            foreach (ContentLocator contentLocator6 in this.Locators)
            {
                contentLocator6.Append(contentLocator5);
            }
            return(this);
        }
Beispiel #4
0
        /// <summary>
        ///     Deserializes an Resource from the XmlReader passed in.
        /// </summary>
        /// <param name="reader">reader to deserialize from</param>
        /// <exception cref="ArgumentNullException">reader is null</exception>
        public void ReadXml(XmlReader reader)
        {
            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }

            XmlDocument doc = new XmlDocument();

            ReadAttributes(reader);

            if (!reader.IsEmptyElement)
            {
                reader.Read();  // Reads the remainder of "Resource" start tag

                while (!(AnnotationXmlConstants.Elements.Resource == reader.LocalName && XmlNodeType.EndElement == reader.NodeType))
                {
                    if (AnnotationXmlConstants.Elements.ContentLocatorGroup == reader.LocalName)
                    {
                        ContentLocatorBase locator = (ContentLocatorBase)LocatorGroupSerializer.Deserialize(reader);
                        InternalLocators.Add(locator);
                    }
                    else if (AnnotationXmlConstants.Elements.ContentLocator == reader.LocalName)
                    {
                        ContentLocatorBase locator = (ContentLocatorBase)ListSerializer.Deserialize(reader);
                        InternalLocators.Add(locator);
                    }
                    else if (XmlNodeType.Element == reader.NodeType)
                    {
                        XmlElement element = doc.ReadNode(reader) as XmlElement;
                        InternalContents.Add(element);
                    }
                    else
                    {
                        // The resource must contain a non-XmlElement child such as plain
                        // text which is not part of the schema.
                        throw new XmlException(SR.Get(SRID.InvalidXmlContent, AnnotationXmlConstants.Elements.Resource));
                    }
                }
            }

            reader.Read();   // Reads the end of the "Resource" element (or whole element if empty)
        }
Beispiel #5
0
        // Token: 0x0600633E RID: 25406 RVA: 0x001BEA54 File Offset: 0x001BCC54
        internal override ContentLocatorBase Merge(ContentLocatorBase other)
        {
            if (other == null)
            {
                return(this);
            }
            ContentLocatorGroup contentLocatorGroup = other as ContentLocatorGroup;

            if (contentLocatorGroup == null)
            {
                this.Append((ContentLocator)other);
                return(this);
            }
            ContentLocatorGroup contentLocatorGroup2 = new ContentLocatorGroup();
            ContentLocator      contentLocator       = null;

            foreach (ContentLocator contentLocator2 in contentLocatorGroup.Locators)
            {
                if (contentLocator == null)
                {
                    contentLocator = contentLocator2;
                }
                else
                {
                    ContentLocator contentLocator3 = (ContentLocator)this.Clone();
                    contentLocator3.Append(contentLocator2);
                    contentLocatorGroup2.Locators.Add(contentLocator3);
                }
            }
            if (contentLocator != null)
            {
                this.Append(contentLocator);
                contentLocatorGroup2.Locators.Add(this);
            }
            if (contentLocatorGroup2.Locators.Count == 0)
            {
                return(this);
            }
            return(contentLocatorGroup2);
        }
Beispiel #6
0
        /// <summary>Deserializes the <see cref="T:System.Windows.Annotations.AnnotationResource" /> from a specified <see cref="T:System.Xml.XmlReader" />.</summary>
        /// <param name="reader">The XML reader to deserialize the <see cref="T:System.Windows.Annotations.AnnotationResource" /> from.</param>
        /// <exception cref="T:System.ArgumentNullException">
        ///         <paramref name="reader" /> is <see langword="null" />.</exception>
        /// <exception cref="T:System.Xml.XmlException">The serialized XML for the <see cref="T:System.Windows.Annotations.AnnotationResource" /> is not valid.</exception>
        // Token: 0x060062A1 RID: 25249 RVA: 0x001BADB8 File Offset: 0x001B8FB8
        public void ReadXml(XmlReader reader)
        {
            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }
            XmlDocument xmlDocument = new XmlDocument();

            this.ReadAttributes(reader);
            if (!reader.IsEmptyElement)
            {
                reader.Read();
                while (!("Resource" == reader.LocalName) || XmlNodeType.EndElement != reader.NodeType)
                {
                    if ("ContentLocatorGroup" == reader.LocalName)
                    {
                        ContentLocatorBase item = (ContentLocatorBase)AnnotationResource.LocatorGroupSerializer.Deserialize(reader);
                        this.InternalLocators.Add(item);
                    }
                    else if ("ContentLocator" == reader.LocalName)
                    {
                        ContentLocatorBase item2 = (ContentLocatorBase)AnnotationResource.ListSerializer.Deserialize(reader);
                        this.InternalLocators.Add(item2);
                    }
                    else
                    {
                        if (XmlNodeType.Element != reader.NodeType)
                        {
                            throw new XmlException(SR.Get("InvalidXmlContent", new object[]
                            {
                                "Resource"
                            }));
                        }
                        XmlElement item3 = xmlDocument.ReadNode(reader) as XmlElement;
                        this.InternalContents.Add(item3);
                    }
                }
            }
            reader.Read();
        }
        /// <summary>
        ///     Resolves a locator starting on a specified locator part with a specified tree node.
        ///     The tree node can optionally be skipped (if some previous locator part has already
        ///     matched it) in which case the resolution starts with its children.
        /// </summary>
        /// <param name="locator">the locator to resolve</param>
        /// <param name="offset">the index of the first locator part to resolve</param>
        /// <param name="startNode">the node to start the resolution at</param>
        /// <param name="skipStartNode">specifies whether to start with the startNode or its children</param>
        /// <param name="attachmentLevel">return value specifying how successful the resolution was</param>
        /// <returns>the attached anchor the locator was resolved to</returns>
        /// <exception cref="InvalidOperationException">if a locator set is resolved and the individual selections
        /// can't be merged</exception>
        private Object InternalResolveLocator(ContentLocatorBase locator, int offset, DependencyObject startNode, bool skipStartNode, out AttachmentLevel attachmentLevel)
        {
            Debug.Assert(locator != null, "locator can not be null");
            Debug.Assert(startNode != null, "startNode can not be null");

            // Set it to unresolved initially
            attachmentLevel = AttachmentLevel.Full;
            Object selection = null;            
            ContentLocatorGroup locatorGroup = locator as ContentLocatorGroup;
            ContentLocator realLocator = locator as ContentLocator;
            AttachmentLevel individualAttachmentLevel = AttachmentLevel.Unresolved;

            // If only one locator part left, it might represent a selection so we take
            // care of that case before trying to resolve the locator part
            if (realLocator != null && offset == realLocator.Parts.Count - 1)
            {
                ContentLocatorPart locatorPart = realLocator.Parts[offset];
                SelectionProcessor selProcessor = GetSelectionProcessorForLocatorPart(locatorPart);

                if (selProcessor != null)
                {
                    selection = selProcessor.ResolveLocatorPart(locatorPart, startNode, out individualAttachmentLevel);
                    attachmentLevel = individualAttachmentLevel;
                    // No node has actually been matched in this case so we 
                    // return the default Unresolved (set at top of method).  
                    // Its up to the caller to know if the node and 
                    // index passed in represented an incomplete resolution.

                    return selection;
                }
            }
            
            IList<ContentLocator> locators = null;             

            // Setup the locators and other inputs before the loop.  Normal locators
            // are put in an array of locators (with one element).  LocatorGroups have
            // their Locators collection used.
            if (locatorGroup == null)
            {
                Debug.Assert(offset >= 0 && offset < realLocator.Parts.Count, "offset out of range");

                locators = new List <ContentLocator> (1);
                locators.Add(realLocator);                
            }
            else
            {
                // If there is a service, start at its root.
                AnnotationService svc = AnnotationService.GetService(startNode);
                if (svc != null)
                {
                    startNode = svc.Root; 
                }

                locators = locatorGroup.Locators;

                // Always start resolving locator groups from the beginning
                // and use the node the service is enabled on to start
                offset = 0;
                skipStartNode = false;
            }

            bool middlePortionExists = true;

            if (locators.Count > 0)
            {
                // Otherwise we need to resolve each of the locators in the locator set
                // and then try to merge the anchors that are returned
                ResolvingLocatorState data = ResolveSingleLocator(ref selection, ref attachmentLevel, AttachmentLevel.StartPortion, locators[0], offset, startNode, skipStartNode);
                
                // Special case - when there is only one locator we simply use the anchor and level
                // returned from resolving that single locator
                if (locators.Count == 1)
                {
                    selection = data.AttachedAnchor;
                    attachmentLevel = data.AttachmentLevel;
                }
                else
                {
                    // Resolve all locators after the first and before the last
                    if (locators.Count > 2)
                    {
                        AttachmentLevel tempLevel = AttachmentLevel.Unresolved;
                        AttachmentLevel savedLevel = attachmentLevel;
                        for (int i = 1; i < locators.Count - 1; i++)
                        {
                            data = ResolveSingleLocator(ref selection, ref attachmentLevel, AttachmentLevel.MiddlePortion, locators[i], offset, startNode, skipStartNode);

                            //if there are >1 middle locators some of them might be resolved, some other - not
                            //if even one middle locator is resolved we should save its attachmenLevel
                            if ((tempLevel == AttachmentLevel.Unresolved) || ((attachmentLevel & AttachmentLevel.MiddlePortion) != 0))
                                tempLevel = attachmentLevel;

                            attachmentLevel = savedLevel;
                        }
                        attachmentLevel = tempLevel;
                    }
                    else
                    {
                        // We make note that there were no middle portion locators
                        middlePortionExists = false;
                    }

                    // Process the last locator
                    data = ResolveSingleLocator(ref selection, ref attachmentLevel, AttachmentLevel.EndPortion, locators[locators.Count - 1], offset, startNode, skipStartNode);

                    // If no locators exists for the middle portion we need to make
                    // sure its not the only portion left on.
                    if (!middlePortionExists && attachmentLevel == AttachmentLevel.MiddlePortion)
                    {
                        attachmentLevel &= ~AttachmentLevel.MiddlePortion;
                    }

                    //if start and end is resolved we consider this as fully resolved
                    //this will handle the case of empty middle page in fixed
                    if (attachmentLevel == (AttachmentLevel.StartPortion | AttachmentLevel.EndPortion))
                        attachmentLevel = AttachmentLevel.Full;
                }
            }
            else
            {
                // There are no locators to resolve
                attachmentLevel = AttachmentLevel.Unresolved;
            }

            return selection;
        }
        /// <summary>
        ///    Determines if the locator matches any of the prefixes, and if so, returns
        ///    the length of the prefix that was matched.  Resolving of the locator can
        ///    begin with the first locator part after those that were matched by the prefix.
        /// </summary>
        /// <param name="prefixes">locators representing prefixes to match</param>
        /// <param name="locator">locator to find a match for</param>
        /// <param name="matched">whether or not a match was found</param>
        /// <returns>index of the next locator part to resolve</returns>
        private int FindMatchingPrefix(ContentLocator[] prefixes, ContentLocatorBase locator, out bool matched)
        {
            matched = true;
            int locatorPartIdx = 0;        
            ContentLocator realLocator = locator as ContentLocator;

            // If we have a locator set or there are no prefixes then we
            // are 'matched' implicitly.
            if (realLocator != null && prefixes != null && prefixes.Length > 0)
            {
                matched = false;
                foreach (ContentLocator prefix in prefixes)
                {
                    if (realLocator.StartsWith(prefix))
                    {
                        locatorPartIdx = prefix.Parts.Count;
                        matched = true;
                        break;
                    }
                }
            }

            return locatorPartIdx;
        }
        /// <summary>
        ///     Searches the element subtree for a node that maps to the 
        ///     passed in ContentLocatorBase.  
        ///     Note: For LocatorGroups the startNode, offset, and prefixes
        ///     are ignored.  Due to the nature of LocatorGroups, we always
        ///     start searching at the node with the service enabled, with
        ///     the first locator part, ignoring all prefixes.
        /// </summary>
        /// <param name="startNode">the root of the subtree to search</param>
        /// <param name="prefixes">locators for the root of the subtree</param>
        /// <param name="locator">the ContentLocatorBase we are resolving to an anchor</param>
        /// <param name="attachmentLevel">type of the anchor returned</param>
        /// <returns>the anchor for the passed in ContentLocatorBase; will return null if no match can be found</returns>
        /// <exception cref="ArgumentNullException">startNode or locator is null</exception>
        internal Object FindAttachedAnchor(DependencyObject startNode, ContentLocator[] prefixes, ContentLocatorBase locator, out AttachmentLevel attachmentLevel)
        {
            if (startNode == null)
                throw new ArgumentNullException("startNode");

            if (locator == null)
                throw new ArgumentNullException("locator");
        
            // Set it to unresolved initially
            attachmentLevel = AttachmentLevel.Unresolved;

            Object anchor = null;            
            bool matched = true;
            int locatorPartIdx = FindMatchingPrefix(prefixes, locator, out matched);

            // The annotation's locator starts with at least 
            // one of the locators for the local root.
            if (matched)
            {
                ContentLocator realLocator = locator as ContentLocator;
                if (realLocator == null || locatorPartIdx < realLocator.Parts.Count)
                {
                    // Now we try to resolve.  If any locator parts were matched to the startNode we want to 
                    // start resolving with its children, skipping a revisit to the startNode.
                    anchor = InternalResolveLocator(locator, locatorPartIdx, startNode, locatorPartIdx != 0 /*skipStartNode*/, out attachmentLevel);
                }

                // If nothing was returned, we base our return values on the results
                // of matching against the local root.
                if (attachmentLevel == AttachmentLevel.Unresolved && locatorPartIdx > 0)
                {
                    if (locatorPartIdx == 0)
                    {
                        attachmentLevel = AttachmentLevel.Unresolved;
                    }
                    // If there was anything left to resolve then its incomplete
                    // 
                    else if (realLocator != null && locatorPartIdx < realLocator.Parts.Count)
                    {
                        attachmentLevel = AttachmentLevel.Incomplete;
                        anchor = startNode;
                    }
                    // otherwise its fully resolved 
                    else
                    {
                        attachmentLevel = AttachmentLevel.Full;
                        anchor = startNode;
                    }
                }
            }

            return anchor;
        }
        /// <summary>
        ///     Produces an anchor spanning the content specified by 'locator'.
        ///     This method traverses the tree and, using the registered 
        ///     processors, resolves the locator in the current element tree.
        /// </summary>
        /// <param name="locator">the locator to be resolved</param>
        /// <param name="offset">the index of the locator part to begin resolution with, ignored for 
        /// LocatorGroups which always start with the first locator part</param>
        /// <param name="startNode">the tree node to start the resolution from</param>
        /// <param name="attachmentLevel">type of the returned anchor</param>
        /// <returns>an anchor that spans the content specified by locator; may return
        /// null if the locator could not be resolved (in which case type is set to
        /// AttachmentLevel.Unresolved</returns>
        /// <exception cref="ArgumentNullException">locator or startNode are null</exception>
        /// <exception cref="ArgumentException">offset is negative or greater than
        /// locator.Count - 1</exception>
        public Object ResolveLocator(ContentLocatorBase locator, int offset, DependencyObject startNode, out AttachmentLevel attachmentLevel)
        {
            VerifyAccess();

            if (locator == null)
                throw new ArgumentNullException("locator");

            if (startNode == null)
                throw new ArgumentNullException("startNode");
   
            // Offset need only be checked for Locators
            ContentLocator realLocator = locator as ContentLocator;
            if (realLocator != null)
            {
                if (offset < 0 || offset >= realLocator.Parts.Count)
                    throw new ArgumentOutOfRangeException("offset");
            }

            return InternalResolveLocator(locator, offset, startNode, false /*skipStartNode*/, out attachmentLevel);
        }        
        /// <summary>
        ///     Adds the additionalLocators to the end of initialLocator.  If
        ///     there are more than one additional locators, clones of
        ///     initialLocator are created.  This method may be destructive -
        ///     the locators passed in may be modified.
        /// </summary>
        /// <param name="initialLocator">the locator to append the additional locators to</param>
        /// <param name="additionalLocators">array of locators that need to be appended</param>
        /// <returns>list of merged locators</returns>
        private IList<ContentLocatorBase> Merge(ContentLocatorBase initialLocator, IList<ContentLocatorBase> additionalLocators)
        {
            if (additionalLocators == null || additionalLocators.Count == 0)
            {
                List<ContentLocatorBase> res = new List<ContentLocatorBase>(1);

                res.Add(initialLocator);
                return res; 
            }

            for (int i = 1; i < additionalLocators.Count; i++)
            {
                additionalLocators[i] = ((ContentLocatorBase)initialLocator.Clone()).Merge(additionalLocators[i]);
            }

            // Avoid making one too many clones...
            additionalLocators[0] = initialLocator.Merge(additionalLocators[0]);
            return additionalLocators;
        }
Beispiel #12
0
 /// <summary> 
 ///     Internal Merge method used by the LocatorManager as it builds up
 ///     Locators.  We don't expose these methods publicly because they
 ///     are of little use and are optimized for use by the LM (e.g., we
 ///     know the arguments aren't owned by anyone and can be modified in 
 ///     place).
 /// </summary> 
 /// <param name="other">the ContentLocatorBase to merge</param> 
 /// <returns>the resulting ContentLocatorBase (may be the same object the method
 /// was called on for perf reasons)</returns> 
 internal abstract ContentLocatorBase Merge(ContentLocatorBase other);
 /// <summary>
 ///     Internal Merge method used by the LocatorManager as it builds up
 ///     Locators.  We don't expose these methods publicly because they
 ///     are of little use and are optimized for use by the LM (e.g., we
 ///     know the arguments aren't owned by anyone and can be modified in
 ///     place).
 /// </summary>
 /// <param name="other">the ContentLocatorBase to merge</param>
 /// <returns>the resulting ContentLocatorBase (may be the same object the method
 /// was called on for perf reasons)</returns>
 internal abstract ContentLocatorBase Merge(ContentLocatorBase other);
        /// <summary>
        ///     Merges this ContentLocator with a ContentLocatorBase.  If other is a 
        ///     ContentLocatorGroup, each of its Locators are added to clones of 
        ///     this ContentLocatorBase and are added to a new ContentLocatorGroup which is 
        ///     returned.  If other is a ContentLocatorBase, its appended to this 
        ///     ContentLocatorBase and this ContentLocatorBase is returned.
        ///     Both operation modify this ContentLocatorBase.
        /// </summary>
        /// <param name="other">the ContentLocatorBase to merge with</param>
        /// <returns>a ContentLocatorBase containing the final merged product</returns>
        internal override ContentLocatorBase Merge(ContentLocatorBase other)
        {
            if (other == null)
                return this;

            ContentLocatorGroup locatorGroup = other as ContentLocatorGroup;
            if (locatorGroup != null)
            {
                ContentLocatorGroup newGroup = new ContentLocatorGroup();

                ContentLocator temp = null;
                // Create n-1 clones of this LPS and append all but one
                // LPSs in the set to the clones, adding the clones to a
                // new ContentLocatorGroup
                foreach (ContentLocator loc in locatorGroup.Locators)
                {
                    if (temp == null)
                    {
                        temp = loc;
                    }
                    else
                    {
                        ContentLocator clone = (ContentLocator)this.Clone();
                        clone.Append(loc);
                        newGroup.Locators.Add(clone);
                    }
                }

                // Finally, add the remaining LPS in the set to this LPS
                // and add this to the new ContentLocatorGroup
                if (temp != null)
                {
                    this.Append(temp);
                    newGroup.Locators.Add(this);
                }

                if (newGroup.Locators.Count == 0)
                    return this;
                else
                    return newGroup;
            }
            else
            {
                // Safe cast - ContentLocator only has two subclasses
                this.Append((ContentLocator)other);
                return this;
            }
        }
Beispiel #15
0
        //------------------------------------------------------
        //
        //  Internal Methods
        //
        //------------------------------------------------------

        #region Internal Methods

        /// <summary>
        ///     Merges the ContentLocatorGroup with a ContentLocatorBase.  If other is a ContentLocatorBase, 
        ///     it is added to the end of every ContentLocatorBase in this ContentLocatorGroup.
        ///     If other is a ContentLocatorGroup, then each ContentLocatorBase in it must be added to
        ///     each ContentLocatorBase (or a clone) in this ContentLocatorGroup.  The result is this 
        ///     ContentLocatorGroup will contain n*m ContentLocatorBase.
        ///     In both cases, this ContentLocatorGroup is modified.
        /// </summary>
        /// <param name="other">other ContentLocatorBase to merge with</param>
        /// <returns>this ContentLocatorGroup</returns>
        internal override ContentLocatorBase Merge(ContentLocatorBase other)
        {
            if (other == null)
                return this;

            ContentLocator firstRight = null;
            ContentLocatorGroup locatorGroup = other as ContentLocatorGroup;
            if (locatorGroup != null)
            {
                List<ContentLocatorBase> tempList = new List<ContentLocatorBase>(locatorGroup.Locators.Count * (this.Locators.Count - 1));
                foreach (ContentLocator left in this.Locators)
                {
                    foreach (ContentLocator right in locatorGroup.Locators)
                    {
                        if (firstRight == null)
                        {
                            firstRight = right;
                        }
                        else
                        {
                            ContentLocator clone = (ContentLocator)left.Clone();
                            clone.Append(right);
                            tempList.Add(clone);
                        }
                    }

                    // No need to clone or add here - just use the locator
                    // already in the ContentLocatorGroup
                    left.Append(firstRight);
                    firstRight = null;
                }

                foreach (ContentLocator list in tempList)
                {
                    this.Locators.Add(list);
                }
            }
            else
            {
                ContentLocator otherLoc = other as ContentLocator;
                Invariant.Assert(otherLoc != null, "other should be of type ContentLocator");  // Only other possible type for the ContentLocatorBase

                foreach(ContentLocator loc in this.Locators)
                {
                    loc.Append(otherLoc);
                }
            }
            return this;
        }