private ProcessResult FillContent(XContainer contentControl, IContentItem item)
        {
            var processResult = ProcessResult.NotHandledResult;

            if (!(item is SingleContent))
            {
                processResult = ProcessResult.NotHandledResult;
                return(processResult);
            }

            var single = (SingleContent)item;

            // If there isn't a field with that name, add an error to the error string, and continue
            // with next field.
            if (contentControl == null)
            {
                processResult.AddError(new ContentControlNotFoundError(single));
                return(processResult);
            }

            var content = contentControl.Element(W.SdtContent);

            var childElement = content.FirstLevelDescendantsAndSelf(W.Sdt)
                               .First(sdt => single.ChildName == sdt.SdtTagName());

            childElement.ElementsAfterSelf(W.Sdt).ToList().ForEach(e => e.Remove());
            childElement.ElementsAfterSelf(W.R).ToList().ForEach(e => e.Remove());
            childElement.ElementsBeforeSelf(W.Sdt).ToList().ForEach(e => e.Remove());
            childElement.ElementsBeforeSelf(W.R).ToList().ForEach(e => e.Remove());
            processResult.AddItemToHandled(item);

            var contentProcessResult = new ContentProcessor(_context)
                                       .SetRemoveContentControls(_isNeedToRemoveContentControls)
                                       .FillContent(childElement.Element(W.SdtContent), single.Fields);

            processResult.Merge(contentProcessResult);

            processResult.AddItemToHandled(item);

            if (_isNeedToRemoveContentControls)
            {
                childElement.RemoveContentControl();
            }

            return(processResult);
        }
        /// <summary>
        /// Fills content with one content item
        /// </summary>
        /// <param name="contentControl">Content control</param>
        /// <param name="item">Content item</param>
        private ProcessResult FillContent(XContainer contentControl, IContentItem item)
        {
            if (!(item is TableContent))
            {
                return(ProcessResult.NotHandledResult);
            }

            var processResult = ProcessResult.NotHandledResult;

            var table = (TableContent)item;

            // If there isn't a table with that name, add an error to the error string, and continue
            // with next table.
            if (contentControl == null)
            {
                processResult.AddError(new ContentControlNotFoundError(table));

                return(processResult);
            }

            // If the table doesn't contain content controls in cells, then error and continue with
            // next table.
            var cellContentControl = contentControl
                                     .Descendants(W.Sdt)
                                     .FirstOrDefault();

            if (cellContentControl == null)
            {
                processResult.AddError(new CustomContentItemError(table, "doesn\'t contain content controls in cells"));

                return(processResult);
            }

            var fieldNames = table.FieldNames.ToList();

            var prototypeRows = GetPrototype(contentControl, fieldNames);

            //Select content controls tag names
            var contentControlTagNames = prototypeRows
                                         .Descendants(W.Sdt)
                                         .Select(sdt => sdt.SdtTagName())
                                         .Where(fieldNames.Contains)
                                         .ToList();

            //If there are not content controls with the one of specified field name we need to add the warning
            if (contentControlTagNames.Intersect(fieldNames).Count() != fieldNames.Count)
            {
                var invalidFileNames = fieldNames
                                       .Where(fn => !contentControlTagNames.Contains(fn))
                                       .ToList();

                processResult.AddError(
                    new CustomContentItemError(table,
                                               string.Format("doesn't contain rows with cell content {0} {1}",
                                                             invalidFileNames.Count > 1 ? "controls" : "control",
                                                             string.Join(", ", invalidFileNames.Select(fn => string.Format("'{0}'", fn))))));
            }

            // Create a list of new rows to be inserted into the document. Because this is a document
            // centric transform, this is written in a non-functional style, using tree modification.
            var newRows = new List <List <XElement> >();

            foreach (var row in table.Rows)
            {
                // Clone the prototypeRows into newRowsEntry.
                var newRowsEntry = prototypeRows.Select(prototypeRow => new XElement(prototypeRow)).ToList();

                // Create new rows that will contain the data that was passed in to this method in
                // the XML tree.
                foreach (var sdt in newRowsEntry.FirstLevelDescendantsAndSelf(W.Sdt).ToList())
                {
                    // Get fieldName from the content control tag.
                    var fieldName = sdt.SdtTagName();

                    var content = row.GetContentItem(fieldName);

                    if (content != null)
                    {
                        var contentProcessResult = new ContentProcessor(_context)
                                                   .SetRemoveContentControls(_isNeedToRemoveContentControls)
                                                   .FillContent(sdt, content);

                        processResult.Merge(contentProcessResult);
                    }
                }

                // Add the newRow to the list of rows that will be placed in the newly generated table.
                newRows.Add(newRowsEntry);
            }

            prototypeRows.Last().AddAfterSelf(newRows);

            // Remove the prototype rows
            prototypeRows.Remove();

            processResult.AddItemToHandled(table);

            return(processResult);
        }
        // Fills prototype with values recursive.
        private PropagationProcessResult PropagatePrototype(Prototype prototype,
                                                            IEnumerable <ListItemContent> content)
        {
            var processResult = new PropagationProcessResult();
            var newRows       = new List <XElement>();

            foreach (var contentItem in content)
            {
                var currentLevelPrototype = prototype.CurrentLevelPrototype(contentItem.GetFieldNames());

                if (currentLevelPrototype == null || !currentLevelPrototype.IsValid)
                {
                    processResult.AddError(new CustomError(
                                               string.Format("Prototype for list item '{0}' not found",
                                                             string.Join(", ", contentItem.GetFieldNames()))));

                    continue;
                }

                // Create new item from the prototype.
                var newItemEntry = currentLevelPrototype.Clone();

                foreach (var xElement in newItemEntry.PrototypeItems)
                {
                    var newElement = new XElement(xElement);
                    if (!newElement.DescendantsAndSelf(W.Sdt).Any())
                    {
                        newRows.Add(newElement);
                        continue;
                    }

                    foreach (var sdt in newElement.FirstLevelDescendantsAndSelf(W.Sdt).ToList())
                    {
                        var fieldContent = contentItem.GetContentItem(sdt.SdtTagName());
                        if (fieldContent == null)
                        {
                            processResult.AddError(new CustomError(
                                                       string.Format("Field content for field '{0}' not found",
                                                                     sdt.SdtTagName())));

                            continue;
                        }

                        var contentProcessResult = new ContentProcessor(_context)
                                                   .SetRemoveContentControls(_isNeedToRemoveContentControls)
                                                   .FillContent(sdt, fieldContent);

                        processResult.Merge(contentProcessResult);
                    }
                    newRows.Add(newElement);
                }

                // If there are nested items fill prototype for them.
                if (contentItem.NestedFields != null)
                {
                    var filledNestedFields = PropagatePrototype(
                        prototype.Exclude(currentLevelPrototype),
                        contentItem.NestedFields);

                    newRows.AddRange(filledNestedFields.Result);
                }
            }
            processResult.Result = newRows;
            return(processResult);
        }