/// <summary>
        /// Insert the children of the current source node under the node pointed to by the destination.
        /// </summary>
        /// <param name="dest"></param>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool CopyChildren(this BaseElementNavigator dest, ElementNavigator source)
        {
            if (dest.HasChildren)
            {
                return(false);                    // Protect children from being overwritten
            }
            if (!source.MoveToFirstChild())
            {
                return(true);                               // Nothing to copy, but successful anyway
            }
            bool firstChild = true;

            do
            {
                var copiedChild = (ElementDefinition)source.Current.DeepCopy();

                if (firstChild)
                {
                    // The first time, create a new child in the destination
                    dest.InsertFirstChild(copiedChild);
                    firstChild = false;
                }
                else
                {
                    // Then insert other childs after that
                    dest.InsertAfter(copiedChild);
                }

                // If there are nested children in the source, insert them under
                // the newly inserted node in the destination
                if (source.HasChildren)
                {
                    dest.CopyChildren(source);
                }
            }while (source.MoveToNext());

            // Bring both source & destination back one step to the original parents
            source.MoveToParent();
            dest.MoveToParent();

            return(true);
        }
        /// <summary>
        /// Insert the children of the source navigator under the node pointed to by this Navigator.
        /// </summary>
        /// <param name="dest"></param>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool CopyChildren(this BaseElementNavigator dest, ElementNavigator source)
        {
            if (dest.HasChildren) return false;   // Protect children from being overwritten
            if (!source.MoveToFirstChild()) return true;    // Nothing to copy, but successful anyway

            bool firstChild = true;

            do
            {
                var copiedChild = (ElementDefinition)source.Current.DeepCopy();

                if (firstChild)
                {
                    // The first time, create a new child in the destination                    
                    dest.InsertFirstChild(copiedChild);
                    firstChild = false;
                }
                else
                    // Then insert other childs after that
                    dest.InsertAfter(copiedChild);
                
                // If there are nested children in the source, insert them under
                // the newly inserted node in the destination
                if (source.HasChildren) dest.CopyChildren(source);
            }
            while (source.MoveToNext());

            // Bring both source & destination back one step to the original parents
            source.MoveToParent();
            dest.MoveToParent();

            return true;
        }
        private void genElement(HierarchicalTableGenerator gen, List<Row> rows, ElementNavigator nav, 
                    Profile profile, bool showMissing)
        {
            var element = nav.Current;

            if(onlyInformationIsMapping(nav.Structure.Element, element)) return;  // we don't even show it in this case

            Row row = new Row();
            row.setAnchor(element.Path);
            String s = element.GetNameFromPath();

            bool hasDef = element.Definition != null;
            bool ext = false;
    
            if (s == "extension" || s == "modifierExtension")
            { 
                row.setIcon("icon_extension_simple.png");
                ext = true;
            }
            else if (!hasDef || element.Definition.Type == null || element.Definition.Type.Count == 0)
            {
                row.setIcon("icon_element.gif");
            }
            else if (hasDef && element.Definition.Type.Count > 1)
            {
                if (allTypesAre(element.Definition.Type, "ResourceReference"))
                    row.setIcon("icon_reference.png");
                else
                    row.setIcon("icon_choice.gif");
            }
            else if (hasDef && element.Definition.Type[0].Code.StartsWith("@"))
            {
                //TODO: That's not a legal code, will this ever appear?
                //I am pretty sure this depends on ElementDefn.NameReference
                row.setIcon("icon_reuse.png");
            }
            else if (hasDef && _pkp.isPrimitive(element.Definition.Type[0].Code))
                row.setIcon("icon_primitive.png");
            else if (hasDef && _pkp.isReference(element.Definition.Type[0].Code))
                row.setIcon("icon_reference.png");
            else if (hasDef && _pkp.isDataType(element.Definition.Type[0].Code))
                row.setIcon("icon_datatype.gif");
            else
                row.setIcon("icon_resource.png");


            var reference = _pkp.GetLinkForElementDefinition(nav.Structure, profile, element);
            //String reference = defPath == null ? null : defPath + makePathLink(element);
            UnusedTracker used = new UnusedTracker();
            used.used = true;
            
            Cell left = new Cell(null, reference, s, !hasDef ? null : element.Definition.Formal, null);
            row.getCells().Add(left);
    
            if (ext)
            {
                // If this element (row) in the table is an extension...
                if (element.Definition != null && element.Definition.Type.Count == 1 && element.Definition.Type[0].Profile != null) 
                {
                    Profile.ProfileExtensionDefnComponent extDefn = _pkp.getExtensionDefinition(profile, element.Definition.Type[0].Profile);
        
                    if (extDefn == null) 
                    {
                        row.getCells().Add(new Cell(null, null, !hasDef ? null : describeCardinality(element.Definition, null, used), null, null));
                        row.getCells().Add(new Cell(null, null, "?? "+element.Definition.Type[0].Profile, null, null));
                        generateDescription(gen, row, element, null, used.used, element.Definition.Type[0].Profile, profile);
                    }
                    else 
                    {
                        row.getCells().Add(new Cell(null, null, !hasDef ? null : describeCardinality(element.Definition, extDefn.Definition, used), null, null));
                        genTypes(gen, row, extDefn.Definition, profile);
                        generateDescription(gen, row, element, extDefn.Definition, used.used, element.Definition.Type[0].Profile, profile);
                    } 
                }
                else if (element.Definition != null) 
                {
                    row.getCells().Add(new Cell(null, null, !hasDef ? null : describeCardinality(element.Definition, null, used), null, null));
                    genTypes(gen, row, element.Definition, profile);
                    generateDescription(gen, row, element, null, used.used, null, profile);
                } 
                else 
                {
                    row.getCells().Add(new Cell(null, null, !hasDef ? null : describeCardinality(element.Definition, null, used), null, null));
                    row.getCells().Add(new Cell());
                    generateDescription(gen, row, element, null, used.used, null, profile);
                }
            } 
            else 
            {
                row.getCells().Add(new Cell(null, null, !hasDef ? null : describeCardinality(element.Definition, null, used), null, null));
                
                if (element.Definition != null)
                    genTypes(gen, row, element.Definition, profile);
                else
                    row.getCells().Add(new Cell());
        
                generateDescription(gen, row, element, null, used.used, null, profile);
            }
      
            if (element.Slicing != null) 
            {
                row.setIcon("icon_slice.png");
                row.getCells()[2].getPieces().Clear();
        
                foreach (Cell cell in row.getCells())
                    foreach (Piece p in cell.getPieces())
                    {
                        p.addStyle("font-style: italic");
                    }        
            }

            if (used.used || showMissing)
                rows.Add(row);
      
            if (!used.used) 
            {
                foreach (Cell cell in row.getCells())
                foreach (Piece p in cell.getPieces()) 
                {
                    p.setStyle("text-decoration:line-through");
                    p.setReference(null);
                }
            } 
            else
            {
                if (nav.MoveToFirstChild())
                {
                    do
                    {
                        genElement(gen, row.getSubRows(), nav, profile, showMissing);
                    } while (nav.MoveToNext());

                   nav.MoveToParent();
                }
            }
        }
        //private static void mergeStructure(Profile.ConstraintComponent snapshot, Profile.ConstraintComponent differential)
        //{
        //    if (differential.Name != null) snapshot.Name = differential.Name;
        //    if (differential.Publish != null) snapshot.Publish = differential.Publish;
        //    if (differential.Purpose != null) snapshot.Purpose = differential.Purpose;
        //}


        private void merge(ElementNavigator snap, ElementNavigator diff)
        {
            mergeElementAttributes(snap.Current, diff.Current);

            // If there are children, move into them, and recursively merge them
            if (diff.MoveToFirstChild())
            {
                if (!snap.HasChildren)
                {
                    // The differential moves into an element that has no children in the base.
                    // This is allowable if the base's element has a nameReference or a TypeRef,
                    // in which case needs to be expanded before we can move to the path indicated
                    // by the differential
                    expandBaseElement(snap, diff);
                }

                // Due to how MoveToFirstChild() works, we have to move to the first matching *child*
                // when entering the loop for the first time, after that we can look for the next
                // matching *sibling*.
                bool firstEntry = true;

                do
                {
                    if( (firstEntry && !snap.MoveToChild(diff.PathName)) ||
                        (!firstEntry && !snap.MoveToNext(diff.PathName)) )
                             throw Error.InvalidOperation("Differential has a constraint for path '{0}', which does not exist in its base", diff.PathName);                   
                    firstEntry = false;

                    // Child found in both, merge them
                    if (countChildNameRepeats(diff) > 1 || diff.Current.IsExtension())
                    {
                        // The child in the diff repeats or we recognize it as an extension slice -> we're on the first element of a slice!
                        mergeSlice(snap, diff); 
                    }
                    else
                        merge(snap, diff);
                }
                while (diff.MoveToNext());

                // After the merge, return the diff and snapho back to their original position
                diff.MoveToParent();
                snap.MoveToParent();
            }
        }
        private void merge(ElementNavigator snap, ElementNavigator diff)
        {
            (new ElementDefnMerger(_markChanges)).Merge(snap.Current, diff.Current);

            // If there are children, move into them, and recursively merge them
            if (diff.MoveToFirstChild())
            {
                if (!snap.HasChildren)
                {
                    // The differential moves into an element that has no children in the base.
                    // This is allowable if the base's element has a nameReference or a TypeRef,
                    // in which case needs to be expanded before we can move to the path indicated
                    // by the differential

                    if (snap.Current.Type.Count > 1)
                        throw new NotSupportedException("Differential has a constraint on a choice element {0}, but does so without using a type slice".FormatWith(diff.Path));

                    expandBaseElement(snap, diff);
                }

                // Due to how MoveToFirstChild() works, we have to move to the first matching *child*
                // when entering the loop for the first time, after that we can look for the next
                // matching *sibling*.
                bool firstEntry = true;

                do
                {
                    if ((firstEntry && !snap.MoveToChild(diff.PathName)) ||
                        (!firstEntry && !snap.MoveTo(diff.PathName)) ) // HACK: I don't think it should be allowed for a diff to list constraints in the wrong order...
                    {
                        throw Error.InvalidOperation("Differential has a constraint for path '{0}', which does not exist in its base", diff.Path);
                    }
                    firstEntry = false;

                    // Child found in both, merge them
                    if (countChildNameRepeats(diff) > 1 || diff.Current.IsExtension())
                    {
                        // The child in the diff repeats or we recognize it as an extension slice -> we're on the first element of a slice!
                        mergeSlice(snap, diff);
                    }
                    else
                        merge(snap, diff);
                }
                while (diff.MoveToNext());

                // After the merge, return the diff and snapho back to their original position
                diff.MoveToParent();
                snap.MoveToParent();
            }
        }