// ========================================================================== // Squidex Headless CMS // ========================================================================== // Copyright (c) Squidex UG (haftungsbeschränkt) // All rights reserved. Licensed under the MIT license. // ========================================================================== using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Squidex.Domain.Apps.Entities.Assets; using Squidex.Infrastructure; namespace Squidex.Domain.Apps.Entities.Contents.Queries { public class QueryExecutionContext : Dictionary { private readonly ConcurrentDictionary cachedContents = new ConcurrentDictionary(); private readonly ConcurrentDictionary cachedAssets = new ConcurrentDictionary(); private readonly IContentQueryService contentQuery; private readonly IAssetQueryService assetQuery; private readonly Context context; public Context Context { get { return context; } } public QueryExecutionContext(Context context, IAssetQueryService assetQuery, IContentQueryService contentQuery) { Guard.NotNull(assetQuery, nameof(assetQuery)); Guard.NotNull(contentQuery, nameof(contentQuery)); Guard.NotNull(context, nameof(context)); this.assetQuery = assetQuery; this.contentQuery = contentQuery; this.context = context; } public virtual async Task FindAssetAsync(Guid id) { var asset = cachedAssets.GetOrDefault(id); if (asset == null) { asset = await assetQuery.FindAssetAsync(context, id); if (asset != null) { cachedAssets[asset.Id] = asset; } } return asset; } public virtual async Task FindContentAsync(Guid schemaId, Guid id) { var content = cachedContents.GetOrDefault(id); if (content == null) { content = await contentQuery.FindContentAsync(context, schemaId.ToString(), id); if (content != null) { cachedContents[content.Id] = content; } } return content; } public virtual async Task> QueryAssetsAsync(string odata) { var q = Q.Empty.WithODataQuery(odata); var assets = await assetQuery.QueryAsync(context, null, q); foreach (var asset in assets) { cachedAssets[asset.Id] = asset; } return assets; } public virtual async Task> QueryContentsAsync(string schemaIdOrName, string odata) { var q = Q.Empty.WithODataQuery(odata); var result = await contentQuery.QueryAsync(context, schemaIdOrName, q); foreach (var content in result) { cachedContents[content.Id] = content; } return result; } public virtual async Task> GetReferencedAssetsAsync(ICollection ids) { Guard.NotNull(ids, nameof(ids)); var notLoadedAssets = new HashSet(ids.Where(id => !cachedAssets.ContainsKey(id))); if (notLoadedAssets.Count > 0) { var assets = await assetQuery.QueryAsync(context, null, Q.Empty.WithIds(notLoadedAssets)); foreach (var asset in assets) { cachedAssets[asset.Id] = asset; } } return ids.Select(cachedAssets.GetOrDefault).NotNull().ToList(); } public virtual async Task> GetReferencedContentsAsync(ICollection ids) { Guard.NotNull(ids, nameof(ids)); var notLoadedContents = ids.Where(id => !cachedContents.ContainsKey(id)).ToList(); if (notLoadedContents.Count > 0) { var result = await contentQuery.QueryAsync(context, notLoadedContents); foreach (var content in result) { cachedContents[content.Id] = content; } } return ids.Select(cachedContents.GetOrDefault).NotNull().ToList(); } public Task> QueryReferencingContentsAsync(string schemaIdOrName, string odata, Guid reference) { var q = Q.Empty.WithODataQuery(odata).WithReference(reference); return contentQuery.QueryAsync(context, schemaIdOrName, q); } } }