Esempio n. 1
0
        private ClrQuery ParseJson(Context context, ISchemaEntity?schema, Query <IJsonValue> query,
                                   ResolvedComponents components)
        {
            var queryModel = BuildQueryModel(context, schema, components);

            return(queryModel.Convert(query));
        }
Esempio n. 2
0
        private static IJsonValue?ConvertComponents(IJsonValue?value, ValueConverter[] converters,
                                                    ResolvedComponents components)
        {
            if (value is JsonArray array)
            {
                JsonArray?result = null;

                for (int i = 0, j = 0; i < array.Count; i++, j++)
                {
                    var newValue = ConvertComponent(array[i], converters, components);

                    if (newValue == null)
                    {
                        result ??= new JsonArray(array);
                        result.RemoveAt(j);
                        j--;
                    }
                    else if (!ReferenceEquals(newValue, array[i]))
                    {
                        result ??= new JsonArray(array);
                        result[j] = newValue;
                    }
                }

                return(result ?? array);
            }

            return(null);
        }
Esempio n. 3
0
        public static JsonSchema BuildJsonSchemaFlat(this Schema schema, PartitionResolver partitionResolver,
                                                     ResolvedComponents components,
                                                     JsonTypeFactory?factory = null,
                                                     bool withHidden         = false,
                                                     bool withComponents     = false)
        {
            Guard.NotNull(partitionResolver);
            Guard.NotNull(components);

            factory ??= DefaultFactory;

            var jsonSchema = JsonTypeBuilder.Object();

            foreach (var field in schema.Fields.ForApi(withHidden))
            {
                var property =
                    JsonTypeVisitor.BuildProperty(
                        field, components, schema,
                        factory,
                        withHidden,
                        withComponents);

                // Property is null for UI fields.
                if (property != null)
                {
                    property.SetRequired(false);
                    property.SetDescription(field);

                    jsonSchema.Properties.Add(field.Name, property);
                }
            }

            return(jsonSchema);
        }
Esempio n. 4
0
        public static FieldConverter ForValues(ResolvedComponents components, params ValueConverter[] converters)
        {
            return((data, field) =>
            {
                ContentFieldData?newData = null;

                foreach (var(key, value) in data)
                {
                    var newValue = ConvertByType(field, value, null, converters, components);

                    if (newValue == null)
                    {
                        newData ??= new ContentFieldData(data);
                        newData.Remove(key);
                    }
                    else if (!ReferenceEquals(newValue, value))
                    {
                        newData ??= new ContentFieldData(data);
                        newData[key] = newValue;
                    }
                }

                return newData ?? data;
            });
        }
Esempio n. 5
0
        private ClrQuery ParseJson(Context context, ISchemaEntity?schema, string json,
                                   ResolvedComponents components)
        {
            var queryModel = BuildQueryModel(context, schema, components);

            return(queryModel.Parse(json, jsonSerializer));
        }
        private static JsonSchema BuildJsonSchema(Schema schema, IAppEntity app,
                                                  ResolvedComponents components, bool withHiddenFields)
        {
            var dataSchema = schema.BuildJsonSchema(app.PartitionResolver(), components, null, withHiddenFields);

            return(ContentJsonSchemaBuilder.BuildSchema(dataSchema, false, true));
        }
        private ClrQuery ParseJson(Context context, ISchemaEntity?schema, Query <IJsonValue> query,
                                   ResolvedComponents components)
        {
            var jsonSchema = BuildJsonSchema(context, schema, components);

            return(jsonSchema.Convert(query));
        }
Esempio n. 8
0
        private ClrQuery ParseOData(Context context, ISchemaEntity?schema, string odata,
                                    ResolvedComponents components)
        {
            try
            {
                var model = BuildEdmModel(context, schema, components);

                return(model.ParseQuery(odata).ToQuery());
            }
            catch (ValidationException)
            {
                throw;
            }
            catch (NotSupportedException)
            {
                throw new ValidationException(T.Get("common.odataNotSupported", new { odata }));
            }
            catch (ODataException ex)
            {
                var message = ex.Message;

                throw new ValidationException(T.Get("common.odataFailure", new { odata, message }), ex);
            }
            catch (Exception)
            {
                throw new ValidationException(T.Get("common.odataNotSupported", new { odata }));
            }
        }
Esempio n. 9
0
        private static IJsonValue ConvertNested <T>(FieldCollection <T> fields, JsonObject source, IArrayField?parent, ValueConverter[] converters,
                                                    ResolvedComponents components) where T : IField
        {
            JsonObject?result = null;

            foreach (var(key, value) in source)
            {
                var newValue = value;

                if (fields.ByName.TryGetValue(key, out var field))
                {
                    newValue = ConvertByType(field, value, parent, converters, components);
                }
                else if (key != Component.Discriminator)
                {
                    newValue = null;
                }

                if (newValue == null)
                {
                    result ??= new JsonObject(source);
                    result.Remove(key);
                }
                else if (!ReferenceEquals(newValue, value))
                {
                    result ??= new JsonObject(source);
                    result[key] = newValue;
                }
            }

            return(result ?? source);
        }
Esempio n. 10
0
        public static JsonSchema BuildJsonSchema(this Schema schema, PartitionResolver partitionResolver,
                                                 ResolvedComponents components,
                                                 JsonTypeFactory?factory = null,
                                                 bool withHidden         = false,
                                                 bool withComponents     = false)
        {
            Guard.NotNull(partitionResolver);
            Guard.NotNull(components);

            factory ??= DefaultFactory;

            var jsonSchema = JsonTypeBuilder.Object();

            foreach (var field in schema.Fields.ForApi(withHidden))
            {
                var typeName = $"{schema.TypeName()}{field.Name.ToPascalCase()}PropertyDto";

                // Create a reference to give it a nice name in code generation.
                var(reference, actual) = factory(typeName);

                if (actual != null)
                {
                    var partitioning = partitionResolver(field.Partitioning);

                    foreach (var partitionKey in partitioning.AllKeys)
                    {
                        var property =
                            JsonTypeVisitor.BuildProperty(
                                field, components, schema,
                                factory,
                                withHidden,
                                withComponents);

                        // Property is null for UI fields.
                        if (property != null)
                        {
                            var isOptional = partitioning.IsOptional(partitionKey);

                            var name = partitioning.GetName(partitionKey);

                            // Required if property is required and language/partitioning is not optional.
                            property.SetRequired(field.RawProperties.IsRequired && !isOptional);
                            property.SetDescription(name);

                            actual.Properties.Add(partitionKey, property);
                        }
                    }
                }

                var propertyReference =
                    JsonTypeBuilder.ReferenceProperty(reference)
                    .SetDescription(field)
                    .SetRequired(field.RawProperties.IsRequired);

                jsonSchema.Properties.Add(field.Name, propertyReference);
            }

            return(jsonSchema);
        }
Esempio n. 11
0
        public static JsonSchemaProperty?BuildProperty(IField field, ResolvedComponents components, Schema schema,
                                                       JsonTypeFactory factory,
                                                       bool withHidden,
                                                       bool withComponents)
        {
            var args = new Args(components, schema, factory, withHidden, withComponents);

            return(field.Accept(Instance, args));
        }
Esempio n. 12
0
        private static IJsonValue?ConvertArrayItem(IArrayField field, IJsonValue?value, ValueConverter[] converters,
                                                   ResolvedComponents components)
        {
            if (value is JsonObject obj)
            {
                return(ConvertNested(field.FieldCollection, obj, field, converters, components));
            }

            return(null);
        }
Esempio n. 13
0
        public static FilterSchema BuildDataSchema(this Schema schema, PartitionResolver partitionResolver,
                                                   ResolvedComponents components)
        {
            Guard.NotNull(partitionResolver);
            Guard.NotNull(components);

            var fields = new List <FilterField>();

            var schemaName = schema.DisplayName();

            foreach (var field in schema.Fields.ForApi(true))
            {
                var fieldSchema = FilterVisitor.BuildProperty(field, components);

                if (fieldSchema == null)
                {
                    continue;
                }

                var partitioning    = partitionResolver(field.Partitioning);
                var partitionFields = new List <FilterField>();

                foreach (var partitionKey in partitioning.AllKeys)
                {
                    var partitionDescription = FieldPartitionDescription(field, partitioning.GetName(partitionKey) ?? partitionKey);

                    var partitionField = new FilterField(
                        fieldSchema,
                        partitionKey,
                        partitionDescription,
                        true);

                    partitionFields.Add(partitionField);
                }

                var filterable = new FilterField(
                    new FilterSchema(FilterSchemaType.Object)
                {
                    Fields = partitionFields.ToReadonlyList()
                },
                    field.Name,
                    FieldDescription(schemaName, field));

                fields.Add(filterable);
            }

            var dataSchema = new FilterSchema(FilterSchemaType.Object)
            {
                Fields = fields.ToReadonlyList()
            };

            return(dataSchema);
        }
Esempio n. 14
0
        public ValidationContext(
            IJsonSerializer jsonSerializer,
            NamedId <DomainId> appId,
            NamedId <DomainId> schemaId,
            Schema schema,
            ResolvedComponents components,
            DomainId contentId)
            : base(appId, schemaId, schema)
        {
            JsonSerializer = jsonSerializer;

            Components = components;
            ContentId  = contentId;
        }
Esempio n. 15
0
        private QueryModel BuildQueryModel(Context context, ISchemaEntity?schema,
                                           ResolvedComponents components)
        {
            var cacheKey = BuildJsonCacheKey(context.App, schema, context.IsFrontendClient);

            var result = cache.GetOrCreate(cacheKey, entry =>
            {
                entry.AbsoluteExpirationRelativeToNow = CacheTime;

                return(ContentQueryModel.Build(schema?.SchemaDef, context.App.PartitionResolver(), components));
            });

            return(result);
        }
Esempio n. 16
0
        private IEdmModel BuildEdmModel(Context context, ISchemaEntity?schema,
                                        ResolvedComponents components)
        {
            var cacheKey = BuildEmdCacheKey(context.App, schema, context.IsFrontendClient);

            var result = cache.GetOrCreate <IEdmModel>(cacheKey, entry =>
            {
                entry.AbsoluteExpirationRelativeToNow = CacheTime;

                return(BuildQueryModel(context, schema, components).ConvertToEdm("Contents", schema?.SchemaDef.Name ?? "Generic"));
            });

            return(result);
        }
Esempio n. 17
0
        private IEnumerable <FieldConverter> GenerateConverters(Context context, ResolvedComponents components, ValueConverter?cleanReferences)
        {
            if (!context.IsFrontendClient)
            {
                yield return(excludedHiddenField);

                yield return(FieldConverters.ForValues(components, ValueConverters.ExcludeHidden));
            }

            yield return(excludedChangedField);

            yield return(FieldConverters.ForValues(components, ValueConverters.ExcludeChangedTypes(jsonSerializer)));

            if (cleanReferences != null)
            {
                yield return(FieldConverters.ForValues(components, cleanReferences));
            }

            yield return(FieldConverters.ResolveInvariant(context.App.Languages));

            yield return(FieldConverters.ResolveLanguages(context.App.Languages));

            if (!context.IsFrontendClient)
            {
                if (context.ShouldResolveLanguages())
                {
                    yield return(FieldConverters.ResolveFallbackLanguages(context.App.Languages));
                }

                var languages = context.Languages();

                if (languages.Any())
                {
                    yield return(FieldConverters.FilterLanguages(context.App.Languages, languages));
                }

                var assetUrls = context.AssetUrls().ToList();

                if (assetUrls.Count > 0)
                {
                    var appId = context.App.NamedId();

                    var resolveAssetUrls = ValueConverters.ResolveAssetUrls(appId, assetUrls, urlGenerator);

                    yield return(FieldConverters.ForValues(components, resolveAssetUrls));
                }
            }
        }
Esempio n. 18
0
        private void ResolveAssetsUrls(ISchemaEntity schema, ResolvedComponents components,
                                       IGrouping <DomainId, ContentEntity> contents, ILookup <DomainId, IEnrichedAssetEntity> assets)
        {
            foreach (var field in schema.SchemaDef.ResolvingAssets())
            {
                foreach (var content in contents)
                {
                    content.ReferenceData ??= new ContentData();

                    var fieldReference = content.ReferenceData.GetOrAdd(field.Name, _ => new ContentFieldData()) !;

                    if (content.Data.TryGetValue(field.Name, out var fieldData) && fieldData != null)
                    {
                        foreach (var(partitionKey, partitionValue) in fieldData)
                        {
                            var referencedAsset =
                                field.GetReferencedIds(partitionValue, components)
                                .Select(x => assets[x])
                                .SelectMany(x => x)
                                .FirstOrDefault();

                            if (referencedAsset != null)
                            {
                                IJsonValue array;

                                if (IsImage(referencedAsset))
                                {
                                    var url = urlGenerator.AssetContent(
                                        referencedAsset.AppId,
                                        referencedAsset.Id.ToString());

                                    array = JsonValue.Array(url, referencedAsset.FileName);
                                }
                                else
                                {
                                    array = JsonValue.Array(referencedAsset.FileName);
                                }

                                requestCache.AddDependency(referencedAsset.UniqueId, referencedAsset.Version);

                                fieldReference.AddLocalized(partitionKey, array);
                            }
                        }
                    }
                }
            }
        }
Esempio n. 19
0
        public ContentConversionTests()
        {
            schema =
                new Schema("my-schema")
                .AddComponent(1, "component", Partitioning.Invariant)
                .AddComponents(2, "components", Partitioning.Invariant)
                .AddAssets(3, "assets1", Partitioning.Invariant)
                .AddAssets(4, "assets2", Partitioning.Invariant)
                .AddReferences(5, "references", Partitioning.Invariant)
                .AddArray(6, "array", Partitioning.Invariant, a => a
                          .AddAssets(31, "nested"));

            components = new ResolvedComponents(new Dictionary <DomainId, Schema>
            {
                [DomainId.Empty] = schema
            });
        }
Esempio n. 20
0
        private static IJsonValue?ConvertByType <T>(T field, IJsonValue?value, IArrayField?parent, ValueConverter[] converters,
                                                    ResolvedComponents components) where T : IField
        {
            switch (field)
            {
            case IArrayField arrayField:
                return(ConvertArray(arrayField, value, converters, components));

            case IField <ComponentFieldProperties> :
                return(ConvertComponent(value, converters, components));

            case IField <ComponentsFieldProperties> :
                return(ConvertComponents(value, converters, components));

            default:
                return(ConvertValue(field, value, parent, converters));
            }
        }
        private IEdmModel BuildEdmModel(Context context, ISchemaEntity?schema,
                                        ResolvedComponents components)
        {
            if (schema == null)
            {
                return(genericEdmModel);
            }

            var cacheKey = BuildEmdCacheKey(context.App, schema, context.IsFrontendClient);

            var result = cache.GetOrCreate <IEdmModel>(cacheKey, entry =>
            {
                entry.AbsoluteExpirationRelativeToNow = CacheTime;

                return(BuildEdmModel(schema.SchemaDef, context.App, components, context.IsFrontendClient));
            });

            return(result);
        }
Esempio n. 22
0
        private static IJsonValue?ConvertComponent(IJsonValue?value, ValueConverter[] converters,
                                                   ResolvedComponents components)
        {
            if (value is JsonObject obj && obj.TryGetValue <JsonString>(Component.Discriminator, out var type))
            {
                var id = DomainId.Create(type.Value);

                if (components.TryGetValue(id, out var schema))
                {
                    return(ConvertNested(schema.FieldCollection, obj, null, converters, components));
                }
                else
                {
                    return(obj);
                }
            }

            return(null);
        }
Esempio n. 23
0
        private (DomainId, RootField <ComponentFieldProperties>, ResolvedComponents) Field(ComponentFieldProperties properties, bool isRequired = false)
        {
            var schema =
                new Schema("my-component")
                .AddNumber(1, "componentField", Partitioning.Invariant,
                           new NumberFieldProperties {
                IsRequired = isRequired
            });

            var field = Fields.Component(1, "myComponent", Partitioning.Invariant, properties);

            var components = new ResolvedComponents(new Dictionary <DomainId, Schema>
            {
                [schemaId1] = schema,
                [schemaId2] = schema,
            });

            return(schemaId1, field, components);
        }
        public static EdmComplexType BuildEdmType(this Schema schema, bool withHidden, PartitionResolver partitionResolver, EdmTypeFactory factory,
                                                  ResolvedComponents components)
        {
            Guard.NotNull(factory, nameof(factory));
            Guard.NotNull(partitionResolver, nameof(partitionResolver));

            var(edmType, _) = factory("Data");

            foreach (var field in schema.FieldsByName.Values)
            {
                if (!field.IsForApi(withHidden))
                {
                    continue;
                }

                var fieldEdmType = EdmTypeVisitor.BuildType(field, factory, components);

                if (fieldEdmType == null)
                {
                    continue;
                }

                var(partitionType, created) = factory($"Data.{field.Name.ToPascalCase()}");

                if (created)
                {
                    var partitioning = partitionResolver(field.Partitioning);

                    foreach (var partitionKey in partitioning.AllKeys)
                    {
                        partitionType.AddStructuralProperty(partitionKey.EscapeEdmField(), fieldEdmType);
                    }
                }

                edmType.AddStructuralProperty(field.Name.EscapeEdmField(), new EdmComplexTypeReference(partitionType, false));
            }

            return(edmType);
        }
        private static EdmModel BuildEdmModel(Schema schema, IAppEntity app,
                                              ResolvedComponents components, bool withHiddenFields)
        {
            var model = new EdmModel();

            var pascalAppName    = app.Name.ToPascalCase();
            var pascalSchemaName = schema.Name.ToPascalCase();

            var typeFactory = new EdmTypeFactory(name =>
            {
                var finalName = pascalSchemaName;

                if (!string.IsNullOrWhiteSpace(name))
                {
                    finalName += ".";
                    finalName += name;
                }

                var result = model.SchemaElements.OfType <EdmComplexType>().FirstOrDefault(x => x.Name == finalName);

                if (result != null)
                {
                    return(result, false);
                }

                result = new EdmComplexType(pascalAppName, finalName);

                model.AddElement(result);

                return(result, true);
            });

            var schemaType = schema.BuildEdmType(withHiddenFields, app.PartitionResolver(), typeFactory, components);

            return(BuildEdmModel(app.Name.ToPascalCase(), schema.Name, model, schemaType));
        }
Esempio n. 26
0
 private static void AddAssetIds(HashSet <DomainId> ids, ISchemaEntity schema, ResolvedComponents components, IEnumerable <ContentEntity> contents)
 {
     foreach (var content in contents)
     {
         content.Data.AddReferencedIds(schema.SchemaDef.ResolvingAssets(), ids, components, 1);
     }
 }
Esempio n. 27
0
 public sealed record Args(ResolvedComponents Components, Schema Schema,
                           JsonTypeFactory Factory,
                           bool WithHidden,
                           bool WithComponents,
                           int Level = 0);
Esempio n. 28
0
        public OperationsBuilder Schema(Schema schema, PartitionResolver partitionResolver, ResolvedComponents components, bool flat)
        {
            var typeName = schema.TypeName();

            var dataSchema = RegisterReference($"{typeName}DataDto", _ =>
            {
                return(schema.BuildJsonSchemaDynamic(partitionResolver, components, CreateReference, false, true));
            });

            var flatDataSchema = RegisterReference($"{typeName}FlatDataDto", _ =>
            {
                return(schema.BuildJsonSchemaFlat(partitionResolver, components, CreateReference, false, true));
            });

            var contentSchema = RegisterReference($"{typeName}ContentDto", _ =>
            {
                return(ContentJsonSchemaBuilder.BuildSchema(flat ? flatDataSchema : dataSchema, true));
            });

            var contentsSchema = RegisterReference($"{typeName}ContentResultDto", _ =>
            {
                return(BuildResult(contentSchema));
            });

            var path = $"/content/{AppName}/{schema.Name}";

            var builder = new OperationsBuilder
            {
                ContentSchema     = contentSchema,
                ContentsSchema    = contentsSchema,
                DataSchema        = dataSchema,
                Path              = path,
                Parent            = this,
                SchemaDisplayName = schema.DisplayName(),
                SchemaName        = schema.Name,
                SchemaTypeName    = typeName
            };

            builder.AddTag("API endpoints for [schema] content items.");

            return(builder);
        }
Esempio n. 29
0
        public static (Schema Schema, ResolvedComponents) MixedSchema(SchemaType type = SchemaType.Default)
        {
            var componentId1 = DomainId.NewGuid();
            var componentId2 = DomainId.NewGuid();
            var componentIds = ReadonlyList.Create(componentId1, componentId2);

            var component1 = new Schema("component1")
                             .Publish()
                             .AddString(1, "unique1", Partitioning.Invariant)
                             .AddString(2, "shared1", Partitioning.Invariant)
                             .AddBoolean(3, "shared2", Partitioning.Invariant);

            var component2 = new Schema("component2")
                             .Publish()
                             .AddNumber(1, "unique1", Partitioning.Invariant)
                             .AddNumber(2, "shared1", Partitioning.Invariant)
                             .AddBoolean(3, "shared2", Partitioning.Invariant);

            var resolvedComponents = new ResolvedComponents(new Dictionary <DomainId, Schema>
            {
                [componentId1] = component1,
                [componentId2] = component2,
            });

            var schema = new Schema("user", type: type)
                         .Publish()
                         .AddArray(101, "root-array", Partitioning.Language, f => f
                                   .AddAssets(201, "nested-assets",
                                              new AssetsFieldProperties())
                                   .AddBoolean(202, "nested-boolean",
                                               new BooleanFieldProperties())
                                   .AddDateTime(203, "nested-datetime",
                                                new DateTimeFieldProperties {
                Editor = DateTimeFieldEditor.DateTime
            })
                                   .AddDateTime(204, "nested-date",
                                                new DateTimeFieldProperties {
                Editor = DateTimeFieldEditor.Date
            })
                                   .AddGeolocation(205, "nested-geolocation",
                                                   new GeolocationFieldProperties())
                                   .AddJson(206, "nested-json",
                                            new JsonFieldProperties())
                                   .AddJson(207, "nested-json2",
                                            new JsonFieldProperties())
                                   .AddNumber(208, "nested-number",
                                              new NumberFieldProperties())
                                   .AddReferences(209, "nested-references",
                                                  new ReferencesFieldProperties())
                                   .AddString(210, "nested-string",
                                              new StringFieldProperties())
                                   .AddTags(211, "nested-tags",
                                            new TagsFieldProperties())
                                   .AddUI(212, "nested-ui",
                                          new UIFieldProperties()))
                         .AddAssets(102, "root-assets", Partitioning.Invariant,
                                    new AssetsFieldProperties())
                         .AddBoolean(103, "root-boolean", Partitioning.Invariant,
                                     new BooleanFieldProperties())
                         .AddDateTime(104, "root-datetime", Partitioning.Invariant,
                                      new DateTimeFieldProperties {
                Editor = DateTimeFieldEditor.DateTime
            })
                         .AddDateTime(105, "root-date", Partitioning.Invariant,
                                      new DateTimeFieldProperties {
                Editor = DateTimeFieldEditor.Date
            })
                         .AddGeolocation(106, "root-geolocation", Partitioning.Invariant,
                                         new GeolocationFieldProperties())
                         .AddJson(107, "root-json", Partitioning.Invariant,
                                  new JsonFieldProperties())
                         .AddNumber(108, "root-number", Partitioning.Invariant,
                                    new NumberFieldProperties {
                MinValue = 1, MaxValue = 10
            })
                         .AddReferences(109, "root-references", Partitioning.Invariant,
                                        new ReferencesFieldProperties())
                         .AddString(110, "root-string1", Partitioning.Invariant,
                                    new StringFieldProperties {
                Label = "My String1", IsRequired = true, AllowedValues = ReadonlyList.Create("a", "b")
            })
                         .AddString(111, "root-string2", Partitioning.Invariant,
                                    new StringFieldProperties {
                Hints = "My String1"
            })
                         .AddTags(112, "root-tags", Partitioning.Language,
                                  new TagsFieldProperties())
                         .AddUI(113, "root-ui", Partitioning.Language,
                                new UIFieldProperties())
                         .AddComponent(114, "root-component", Partitioning.Language,
                                       new ComponentFieldProperties {
                SchemaIds = componentIds
            })
                         .AddComponents(115, "root-components", Partitioning.Language,
                                        new ComponentsFieldProperties {
                SchemaIds = componentIds
            })
                         .Update(new SchemaProperties {
                Hints = "The User"
            })
                         .HideField(104)
                         .HideField(211, 101)
                         .DisableField(109)
                         .DisableField(212, 101)
                         .LockField(105);

            return(schema, resolvedComponents);
        }
Esempio n. 30
0
        public static QueryModel Build(Schema?schema, PartitionResolver partitionResolver, ResolvedComponents components)
        {
            var fields = new List <FilterField>
            {
                new FilterField(FilterSchema.String, "id")
                {
                    Description = FieldDescriptions.EntityId
                },
                new FilterField(FilterSchema.Boolean, "isDeleted")
                {
                    Description = FieldDescriptions.EntityIsDeleted
                },
                new FilterField(FilterSchema.DateTime, "created")
                {
                    Description = FieldDescriptions.EntityCreated
                },
                new FilterField(SharedSchemas.User, "createdBy")
                {
                    Description = FieldDescriptions.EntityCreatedBy
                },
                new FilterField(FilterSchema.DateTime, "lastModified")
                {
                    Description = FieldDescriptions.EntityLastModified
                },
                new FilterField(SharedSchemas.User, "lastModifiedBy")
                {
                    Description = FieldDescriptions.EntityLastModifiedBy
                },
                new FilterField(FilterSchema.Number, "version")
                {
                    Description = FieldDescriptions.EntityVersion
                },
                new FilterField(SharedSchemas.Status, "status")
                {
                    Description = FieldDescriptions.ContentStatus,
                },
                new FilterField(SharedSchemas.Status, "newStatus", IsNullable: true)
                {
                    Description = FieldDescriptions.ContentNewStatus
                }
            };

            if (schema != null)
            {
                var dataSchema = schema.BuildDataSchema(partitionResolver, components);

                fields.Add(new FilterField(dataSchema, "data")
                {
                    Description = FieldDescriptions.ContentData
                });
            }

            var filterSchema = new FilterSchema(FilterSchemaType.Object)
            {
                Fields = fields.ToReadonlyList()
            };

            return(new QueryModel {
                Schema = filterSchema
            });
        }