private Tuple <SchemaIndexingInfo, FieldIndexingInfo> CreateFromExpression(Expression <Func <T, object> > expression, Action <FieldIndexingInfo> fieldTransformator)
        {
            var rootInfo = Clone(_schemaIndexingInfo);
            var path     = GetExpressionPath(expression);

            FieldIndexingInfo field = null;

            foreach (var segment in path)
            {
                var info = field == null ? rootInfo : field.RelatedSchemaIndexing = new SchemaIndexingInfo();
                if (info.Fields == null)
                {
                    info.Fields = new Collection <FieldIndexingInfo>();
                }

                field = info.Fields.SingleOrDefault(f => f.Id == segment.Item1) ?? new FieldIndexingInfo
                {
                    Id = segment.Item1
                };

                if (!info.Fields.Contains(field))
                {
                    info.Fields.Add(field);
                }

                fieldTransformator(field);
            }

            return(new Tuple <SchemaIndexingInfo, FieldIndexingInfo>(rootInfo, field));
        }
        private void ApplyPictureparkSchemaIndexingAttribute(JsonProperty property, FieldIndexingInfo field)
        {
            // TODO: Is ApplyPictureparkSchemaIndexingAttribute needed?
            var attribute = (PictureparkSchemaIndexingAttribute)property.AttributeProvider
                            .GetAttributes(typeof(PictureparkSchemaIndexingAttribute), true)
                            .SingleOrDefault();

            if (attribute != null)
            {
                var relatedSchemaIndexing = Clone(attribute.SchemaIndexingInfo);
                if (relatedSchemaIndexing.Fields != null && relatedSchemaIndexing.Fields.Any())
                {
                    field.RelatedSchemaIndexing = relatedSchemaIndexing;
                }
            }
        }
        private ICollection <FieldIndexingInfo> GenerateFieldIndexingInfos(Type type, int levels, Func <Type, JsonProperty, bool> propertySelector)
        {
            var fields = new Collection <FieldIndexingInfo>();

            if (_contractResolver.ResolveContract(type) is JsonObjectContract contract)
            {
                foreach (var property in contract.Properties)
                {
                    if (propertySelector?.Invoke(type, property) != false)
                    {
                        var searchAttribute = property.AttributeProvider
                                              .GetAttributes(true)
                                              .OfType <PictureparkSearchAttribute>()
                                              .SingleOrDefault();

                        var field = new FieldIndexingInfo
                        {
                            Id           = property.PropertyName,
                            SimpleSearch = searchAttribute?.SimpleSearch ?? false,
                            Index        = searchAttribute?.Index ?? false,
                            Boost        = searchAttribute?.Boost ?? 0.0,
                        };
                        fields.Add(field);

                        ApplyPictureparkSchemaIndexingAttribute(property, field);

                        if (levels > 0)
                        {
                            var propertyType = property.PropertyType.GenericTypeArguments.Any()
                                ? property.PropertyType.GenericTypeArguments.First()
                                : property.PropertyType;

                            var subFields = GenerateFieldIndexingInfos(propertyType, levels - 1, propertySelector);
                            if (subFields != null && subFields.Any())
                            {
                                field.RelatedSchemaIndexing = new SchemaIndexingInfo
                                {
                                    Fields = subFields
                                };
                            }
                        }
                    }
                }
            }

            return(fields);
        }