// ========================================================================== // 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 { public class QueryExecutionContext { private readonly ConcurrentDictionary cachedContents = new ConcurrentDictionary(); private readonly ConcurrentDictionary cachedAssets = new ConcurrentDictionary(); private readonly IContentQueryService contentQuery; private readonly IAssetQueryService assetQuery; private readonly QueryContext context; public QueryExecutionContext(QueryContext 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 query) { var assets = await assetQuery.QueryAsync(context, Q.Empty.WithODataQuery(query)); foreach (var asset in assets) { cachedAssets[asset.Id] = asset; } return assets; } public virtual async Task> QueryContentsAsync(string schemaIdOrName, string query) { var result = await contentQuery.QueryAsync(context, schemaIdOrName, Q.Empty.WithODataQuery(query)); 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, Q.Empty.WithIds(notLoadedAssets)); foreach (var asset in assets) { cachedAssets[asset.Id] = asset; } } return ids.Select(cachedAssets.GetOrDefault).Where(x => x != null).ToList(); } public virtual async Task> GetReferencedContentsAsync(Guid schemaId, 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, schemaId.ToString(), Q.Empty.WithIds(notLoadedContents)); foreach (var content in result) { cachedContents[content.Id] = content; } } return ids.Select(cachedContents.GetOrDefault).Where(x => x != null).ToList(); } } }