mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-31 04:04:21 -04:00
110 lines
3.2 KiB
C#
110 lines
3.2 KiB
C#
// Kyoo - A portable and vast media library solution.
|
|
// Copyright (c) Kyoo.
|
|
//
|
|
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
|
//
|
|
// Kyoo is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// any later version.
|
|
//
|
|
// Kyoo is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel.DataAnnotations;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using Kyoo.Abstractions.Models.Attributes;
|
|
|
|
namespace Kyoo.Abstractions.Models.Utils;
|
|
|
|
public class Include
|
|
{
|
|
/// <summary>
|
|
/// The aditional fields to include in the result.
|
|
/// </summary>
|
|
public ICollection<Metadata> Metadatas { get; set; } = ArraySegment<Metadata>.Empty;
|
|
|
|
public abstract record Metadata(string Name);
|
|
|
|
public record SingleRelation(string Name, Type type, string RelationIdName) : Metadata(Name);
|
|
|
|
public record CustomRelation(string Name, Type type, string Sql, string? On, Type Declaring)
|
|
: Metadata(Name);
|
|
|
|
public record ProjectedRelation(string Name, string Sql) : Metadata(Name);
|
|
}
|
|
|
|
/// <summary>
|
|
/// The aditional fields to include in the result.
|
|
/// </summary>
|
|
/// <typeparam name="T">The type related to the new fields</typeparam>
|
|
public class Include<T> : Include
|
|
{
|
|
/// <summary>
|
|
/// The aditional fields names to include in the result.
|
|
/// </summary>
|
|
public ICollection<string> Fields => Metadatas.Select(x => x.Name).ToList();
|
|
|
|
public Include() { }
|
|
|
|
public Include(params string[] fields)
|
|
{
|
|
Type[] types = typeof(T).GetCustomAttribute<OneOfAttribute>()?.Types ?? new[] { typeof(T) };
|
|
Metadatas = fields
|
|
.SelectMany(key =>
|
|
{
|
|
var relations = types
|
|
.Select(x =>
|
|
x.GetProperty(
|
|
key,
|
|
BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance
|
|
)!
|
|
)
|
|
.Select(prop =>
|
|
(prop, attr: prop?.GetCustomAttribute<LoadableRelationAttribute>()!)
|
|
)
|
|
.Where(x => x.prop != null && x.attr != null)
|
|
.ToList();
|
|
if (!relations.Any())
|
|
throw new ValidationException($"No loadable relation with the name {key}.");
|
|
return relations
|
|
.Select(x =>
|
|
{
|
|
(PropertyInfo prop, LoadableRelationAttribute attr) = x;
|
|
|
|
if (attr.RelationID != null)
|
|
return new SingleRelation(prop.Name, prop.PropertyType, attr.RelationID)
|
|
as Metadata;
|
|
if (attr.Sql != null)
|
|
return new CustomRelation(
|
|
prop.Name,
|
|
prop.PropertyType,
|
|
attr.Sql,
|
|
attr.On,
|
|
prop.DeclaringType!
|
|
);
|
|
if (attr.Projected != null)
|
|
return new ProjectedRelation(prop.Name, attr.Projected);
|
|
throw new NotImplementedException();
|
|
})
|
|
.Distinct();
|
|
})
|
|
.ToArray();
|
|
}
|
|
|
|
public static Include<T> From(string? fields)
|
|
{
|
|
if (string.IsNullOrEmpty(fields))
|
|
return new Include<T>();
|
|
return new Include<T>(fields.Split(','));
|
|
}
|
|
}
|