/// <summary>
        /// Remove loops from pluglet
        /// </summary>
        /// <param name="pluglet"></param>
        /// <param name="canonicalPluglet"></param>
        /// <returns></returns>
        public static Pluglet RemoveLoops(this IPluglet pluglet, IPluglet canonicalPluglet)
        {
            if (pluglet == null)
            {
                throw new ArgumentNullException("pluglet");
            }

            Pluglet resultPluglet = pluglet.Clone(false);

            if (pluglet.Children != null && pluglet.Children.Count > 0)
            {
                int      childIndex;
                IPluglet prevChild, mergedChild, canonicalChildPluglet = null;
                prevChild = mergedChild = canonicalChildPluglet = null;

                for (childIndex = 0; childIndex < pluglet.Children.Count; childIndex++)
                {
                    canonicalChildPluglet        = canonicalPluglet.Children.First(p => p.Name == pluglet.Children[childIndex].Name);
                    pluglet.Children[childIndex] = pluglet.Children[childIndex].RemoveLoops(canonicalChildPluglet);

                    if (prevChild != null)
                    {
                        if (string.Equals(prevChild.Name, pluglet.Children[childIndex].Name, StringComparison.OrdinalIgnoreCase))
                        {
                            mergedChild = mergedChild.Merge(pluglet.Children[childIndex], canonicalChildPluglet);
                        }
                        else
                        {
                            resultPluglet.Children.Add(mergedChild);
                            mergedChild = null;
                        }
                    }

                    prevChild = pluglet.Children[childIndex];
                    if (mergedChild == null)
                    {
                        mergedChild = pluglet.Children[childIndex];
                    }
                }

                if (mergedChild == null)
                {
                    mergedChild = pluglet.Children[childIndex - 1];
                }

                resultPluglet.Children.Add(mergedChild);
            }

            return(resultPluglet);
        }
        /// <summary>
        /// Merge pluglet and newPluglet and return merged pluglet.
        /// Assumption: pluglet and newPluglet does not have loops
        /// </summary>
        /// <param name="pluglet"></param>
        /// <param name="newPluglet"></param>
        /// <param name="canonicalPluglet"></param>
        /// <returns></returns>
        public static Pluglet Merge(this IPluglet pluglet, IPluglet newPluglet, IPluglet canonicalPluglet)
        {
            if (pluglet == null)
            {
                throw new ArgumentNullException("pluglet");
            }
            if (newPluglet == null)
            {
                throw new ArgumentNullException("newPluglet");
            }
            if (canonicalPluglet == null)
            {
                throw new ArgumentNullException("canonicalPluglet");
            }

            Pluglet mergedPluglet;

            // Make sure that both pluglet has same name
            if (string.Equals(pluglet.Name, newPluglet.Name, StringComparison.OrdinalIgnoreCase) == false)
            {
                throw new PlugDataModelException(
                          string.Format("Merge operation is invalid: pluglet ({0}) and newpluglet({1}) does not match.", pluglet.Name, newPluglet.Name));
            }

            if (string.Equals(pluglet.Name, canonicalPluglet.Name, StringComparison.OrdinalIgnoreCase) == false)
            {
                throw new PlugDataModelException(string.Format("Merge operation params are invalid: {0} and {1}", pluglet.Name, canonicalPluglet.Name));
            }

            // If one of the pluglet does not have children then assign non-null to tempPluglet, clone it with
            // childrens and return
            IPluglet tempPluglet = null;

            if (pluglet.Children == null || newPluglet.Children == null)
            {
                tempPluglet = pluglet ?? newPluglet;
            }

            if (tempPluglet != null)
            {
                mergedPluglet = tempPluglet.Clone(true);
            }
            else
            {
                mergedPluglet = pluglet.Clone(false);

                int  plugletChildIndex, newPlugletChildIndex;
                bool plugletChildExist, newPlugletChildExist;
                plugletChildIndex = newPlugletChildIndex = 0;

                foreach (IPluglet child in canonicalPluglet.Children)
                {
                    plugletChildExist = newPlugletChildExist = false;

                    if (plugletChildIndex < pluglet.Children.Count &&
                        string.Equals(child.Name, pluglet.Children[plugletChildIndex].Name, StringComparison.OrdinalIgnoreCase))
                    {
                        plugletChildExist = true;
                    }

                    if (newPlugletChildIndex < newPluglet.Children.Count &&
                        string.Equals(child.Name, newPluglet.Children[newPlugletChildIndex].Name, StringComparison.OrdinalIgnoreCase))
                    {
                        newPlugletChildExist = true;
                    }

                    // If both pluglet has same child then call Merge
                    if (plugletChildExist && newPlugletChildExist)
                    {
                        // TODO: Perf optimization - We don't need to call Merge if child does not have childrens
                        mergedPluglet.Children.Add(pluglet.Children[plugletChildIndex].Merge(newPluglet.Children[newPlugletChildIndex], child));

                        plugletChildIndex++;
                        newPlugletChildIndex++;
                    }
                    // If only one pluglet has child then clone it with childrens
                    else if (plugletChildExist == true)
                    {
                        mergedPluglet.Children.Add(pluglet.Children[plugletChildIndex].Clone(true));

                        plugletChildIndex++;
                    }
                    else if (newPlugletChildExist == true)
                    {
                        mergedPluglet.Children.Add(newPluglet.Children[newPlugletChildIndex].Clone(true));

                        newPlugletChildIndex++;
                    }

                    if (plugletChildIndex == pluglet.Children.Count && newPlugletChildIndex == newPluglet.Children.Count)
                    {
                        break;
                    }
                }
            }

            return(mergedPluglet);
        }