public TModel Parse <TModel>([NotNull] ITableParser tableParser, [NotNull] RenderingTemplate template, Action <string, string> addFieldMapping)
            where TModel : new()
        {
            var model = new TModel();

            var enumerablesLengths = GetEnumerablesLengths <TModel>(tableParser, template);

            foreach (var row in template.Content.Cells)
            {
                foreach (var cell in row)
                {
                    tableParser.PushState(cell.CellPosition);

                    var expression = cell.StringValue;

                    if (TemplateDescriptionHelper.IsCorrectValueDescription(expression))
                    {
                        ParseCellularValue(tableParser, addFieldMapping, model, ExcelTemplatePath.FromRawExpression(expression), enumerablesLengths);
                        continue;
                    }
                    if (TemplateDescriptionHelper.IsCorrectFormValueDescription(expression))
                    {
                        ParseFormValue(tableParser, addFieldMapping, model, cell, ExcelTemplatePath.FromRawExpression(expression));
                        continue;
                    }

                    tableParser.PopState();
                }
            }

            return(model);
        }
        private static object ExtractChildModel(object model, ICell cell)
        {
            var expression = cell.StringValue;

            if (!TemplateDescriptionHelper.IsCorrectValueDescription(expression))
            {
                return(expression ?? "");
            }
            return(ExtractChildIfCorrectDescription(expression, model) ?? "");
        }
        private Dictionary <ExcelTemplatePath, int> GetEnumerablesLengths <TModel>([NotNull] ITableParser tableParser, [NotNull] RenderingTemplate template)
        {
            var enumerableCellsGroups = new Dictionary <ExcelTemplatePath, List <ICell> >();

            foreach (var row in template.Content.Cells)
            {
                foreach (var cell in row)
                {
                    var expression = cell.StringValue;

                    if (TemplateDescriptionHelper.IsCorrectValueDescription(expression) && ExcelTemplatePath.FromRawExpression(expression).HasArrayAccess)
                    {
                        var cleanPathToEnumerable = ExcelTemplatePath.FromRawExpression(expression)
                                                    .SplitForEnumerableExpansion()
                                                    .pathToEnumerable
                                                    .WithoutArrayAccess();
                        if (!enumerableCellsGroups.ContainsKey(cleanPathToEnumerable))
                        {
                            enumerableCellsGroups[cleanPathToEnumerable] = new List <ICell>();
                        }
                        enumerableCellsGroups[cleanPathToEnumerable].Add(cell);
                    }
                }
            }

            var enumerablesLengths = new Dictionary <ExcelTemplatePath, int>();

            foreach (var enumerableCells in enumerableCellsGroups)
            {
                var cleanPathToEnumerable = enumerableCells.Key;

                var childEnumerableType = ObjectPropertiesExtractor.ExtractChildObjectTypeFromPath(typeof(TModel), cleanPathToEnumerable);
                if (!TypeCheckingHelper.IsIList(childEnumerableType))
                {
                    throw new InvalidOperationException($"Only ILists are supported as collections, but tried to use '{childEnumerableType}'. (path: {cleanPathToEnumerable.RawPath})");
                }

                var primaryParts = enumerableCells.Value.Where(x => ExcelTemplatePath.FromRawExpression(x.StringValue).HasPrimaryKeyArrayAccess).ToList();
                if (primaryParts.Count == 0)
                {
                    primaryParts = enumerableCells.Value.Take(1).ToList();
                }

                var measurer = parserCollection.GetEnumerableMeasurer();
                enumerablesLengths[cleanPathToEnumerable] = measurer.GetLength(tableParser, typeof(TModel), primaryParts);
            }

            return(enumerablesLengths);
        }
 public void ValueDescriptionCorrectnessTest(string expression, bool isCorrect)
 {
     TemplateDescriptionHelper.IsCorrectValueDescription(expression).Should().Be(isCorrect);
 }