mirror of https://github.com/Squidex/squidex.git
47 changed files with 593 additions and 373 deletions
@ -0,0 +1,16 @@ |
|||
// ==========================================================================
|
|||
// IModelFieldProperties.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using PinkParrot.Infrastructure; |
|||
|
|||
namespace PinkParrot.Core.Schema |
|||
{ |
|||
public interface IModelFieldProperties : IValidatable |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
// ==========================================================================
|
|||
// IRegisterModelField.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
|
|||
namespace PinkParrot.Core.Schema |
|||
{ |
|||
public interface IRegisterModelField |
|||
{ |
|||
Type PropertiesType { get; } |
|||
|
|||
ModelField CreateField(long id, string name, IModelFieldProperties properties); |
|||
} |
|||
} |
|||
@ -1,64 +0,0 @@ |
|||
// ==========================================================================
|
|||
// SerializationModel.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Immutable; |
|||
using PinkParrot.Infrastructure; |
|||
|
|||
// ReSharper disable LoopCanBeConvertedToQuery
|
|||
|
|||
namespace PinkParrot.Core.Schema.Json |
|||
{ |
|||
public class SchemaDto |
|||
{ |
|||
private readonly ModelSchemaProperties properties; |
|||
private readonly ImmutableDictionary<long, ModelFieldProperties> fields; |
|||
|
|||
public ImmutableDictionary<long, ModelFieldProperties> Fields |
|||
{ |
|||
get { return fields; } |
|||
} |
|||
|
|||
public ModelSchemaProperties Properties |
|||
{ |
|||
get { return properties; } |
|||
} |
|||
|
|||
public SchemaDto(ModelSchemaProperties properties, ImmutableDictionary<long, ModelFieldProperties> fields) |
|||
{ |
|||
Guard.NotNull(fields, nameof(fields)); |
|||
Guard.NotNull(properties, nameof(properties)); |
|||
|
|||
this.properties = properties; |
|||
|
|||
this.fields = fields; |
|||
} |
|||
|
|||
public static SchemaDto Create(ModelSchema schema) |
|||
{ |
|||
Guard.NotNull(schema, nameof(schema)); |
|||
|
|||
var fields = schema.Fields.ToImmutableDictionary(x => x.Key, x => x.Value.RawProperties); |
|||
|
|||
return new SchemaDto(schema.Properties, fields); |
|||
} |
|||
|
|||
public ModelSchema ToModelSchema(ModelFieldFactory factory) |
|||
{ |
|||
Guard.NotNull(factory, nameof(factory)); |
|||
|
|||
var schema = ModelSchema.Create(properties); |
|||
|
|||
foreach (var field in fields) |
|||
{ |
|||
schema = schema.AddField(field.Key, field.Value, factory); |
|||
} |
|||
|
|||
return schema; |
|||
} |
|||
} |
|||
} |
|||
@ -1,49 +0,0 @@ |
|||
// ==========================================================================
|
|||
// ModelFieldFactory.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using PinkParrot.Infrastructure; |
|||
|
|||
namespace PinkParrot.Core.Schema |
|||
{ |
|||
public class ModelFieldFactory |
|||
{ |
|||
private readonly Dictionary<Type, Func<long, ModelFieldProperties, ModelField>> factories |
|||
= new Dictionary<Type, Func<long, ModelFieldProperties, ModelField>>(); |
|||
|
|||
public ModelFieldFactory() |
|||
{ |
|||
AddFactory<NumberFieldProperties>((id, p) => new NumberField(id, (NumberFieldProperties)p)); |
|||
} |
|||
|
|||
public ModelFieldFactory AddFactory<T>(Func<long, ModelFieldProperties, ModelField> factory) where T : ModelFieldProperties |
|||
{ |
|||
Guard.NotNull(factory, nameof(factory)); |
|||
|
|||
factories[typeof(T)] = factory; |
|||
|
|||
return this; |
|||
} |
|||
|
|||
public virtual ModelField CreateField(long id, ModelFieldProperties properties) |
|||
{ |
|||
Guard.NotNull(properties, nameof(properties)); |
|||
|
|||
var factory = factories.GetOrDefault(properties.GetType()); |
|||
|
|||
if (factory == null) |
|||
{ |
|||
throw new InvalidOperationException("Field type is not supported."); |
|||
} |
|||
|
|||
return factory(id, properties); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,97 @@ |
|||
// ==========================================================================
|
|||
// ModelFieldRegistry.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using PinkParrot.Infrastructure; |
|||
|
|||
namespace PinkParrot.Core.Schema |
|||
{ |
|||
public delegate ModelField FactoryFunction(long id, string name, IModelFieldProperties properties); |
|||
|
|||
public sealed class ModelFieldRegistry |
|||
{ |
|||
private readonly Dictionary<string, IRegisterModelField> fieldsByTypeName = new Dictionary<string, IRegisterModelField>(); |
|||
private readonly Dictionary<Type, IRegisterModelField> fieldsByPropertyType = new Dictionary<Type, IRegisterModelField>(); |
|||
|
|||
private sealed class Registered : IRegisterModelField |
|||
{ |
|||
private readonly FactoryFunction fieldFactory; |
|||
private readonly Type propertiesType; |
|||
private readonly string typeName; |
|||
|
|||
public Type PropertiesType |
|||
{ |
|||
get { return propertiesType; } |
|||
} |
|||
|
|||
public string TypeName |
|||
{ |
|||
get { return typeName; } |
|||
} |
|||
|
|||
public Registered(FactoryFunction fieldFactory, Type propertiesType) |
|||
{ |
|||
typeName = TypeNameRegistry.GetName(propertiesType); |
|||
|
|||
this.fieldFactory = fieldFactory; |
|||
this.propertiesType = propertiesType; |
|||
} |
|||
|
|||
ModelField IRegisterModelField.CreateField(long id, string name, IModelFieldProperties properties) |
|||
{ |
|||
return fieldFactory(id, name, properties); |
|||
} |
|||
} |
|||
|
|||
public void Add<TFieldProperties>(FactoryFunction fieldFactory) |
|||
{ |
|||
Guard.NotNull(fieldFactory, nameof(fieldFactory)); |
|||
|
|||
var registered = new Registered(fieldFactory, typeof(TFieldProperties)); |
|||
|
|||
fieldsByTypeName[registered.TypeName] = registered; |
|||
fieldsByPropertyType[registered.PropertiesType] = registered; |
|||
} |
|||
|
|||
public ModelField CreateField(long id, string name, IModelFieldProperties properties) |
|||
{ |
|||
var registered = fieldsByPropertyType[properties.GetType()]; |
|||
|
|||
return registered.CreateField(id, name, properties); |
|||
} |
|||
|
|||
public IRegisterModelField FindByPropertiesType(Type type) |
|||
{ |
|||
Guard.NotNull(type, nameof(type)); |
|||
|
|||
var registered = fieldsByPropertyType.GetOrDefault(type); |
|||
|
|||
if (registered == null) |
|||
{ |
|||
throw new InvalidOperationException($"The field property '{type}' is not supported."); |
|||
} |
|||
|
|||
return registered; |
|||
} |
|||
|
|||
public IRegisterModelField FindByTypeName(string typeName) |
|||
{ |
|||
Guard.NotNullOrEmpty(typeName, nameof(typeName)); |
|||
|
|||
var registered = fieldsByTypeName.GetOrDefault(typeName); |
|||
|
|||
if (registered == null) |
|||
{ |
|||
throw new DomainException($"A field with type '{typeName} is not known."); |
|||
} |
|||
|
|||
return registered; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,75 @@ |
|||
// ==========================================================================
|
|||
// TypeNameRegistry.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Reflection; |
|||
|
|||
namespace PinkParrot.Infrastructure |
|||
{ |
|||
public class TypeNameRegistry |
|||
{ |
|||
private static readonly Dictionary<Type, string> namesByType = new Dictionary<Type, string>(); |
|||
private static readonly Dictionary<string, Type> typesByName = new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase); |
|||
|
|||
public static void Map(Type type, string name) |
|||
{ |
|||
Guard.NotNull(type, nameof(type)); |
|||
Guard.NotNull(name, nameof(name)); |
|||
|
|||
lock (namesByType) |
|||
{ |
|||
namesByType.Add(type, name); |
|||
|
|||
typesByName.Add(name, type); |
|||
} |
|||
} |
|||
|
|||
public static void Map(Assembly assembly) |
|||
{ |
|||
foreach (var type in assembly.GetTypes()) |
|||
{ |
|||
var typeNameAttribute = type.GetTypeInfo().GetCustomAttribute<TypeNameAttribute>(); |
|||
|
|||
if (!string.IsNullOrWhiteSpace(typeNameAttribute?.TypeName)) |
|||
{ |
|||
Map(type, typeNameAttribute.TypeName); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public static string GetName<T>() |
|||
{ |
|||
return GetName(typeof(T)); |
|||
} |
|||
|
|||
public static string GetName(Type type) |
|||
{ |
|||
var result = namesByType.GetOrDefault(type); |
|||
|
|||
if (result == null) |
|||
{ |
|||
throw new ArgumentException($"There is not name for type '{type}"); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
public static Type GetType(string name) |
|||
{ |
|||
var result = typesByName.GetOrDefault(name); |
|||
|
|||
if (result == null) |
|||
{ |
|||
throw new ArgumentException($"There is not type for name '{name}"); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
// ==========================================================================
|
|||
// ModelFieldDto.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using Newtonsoft.Json; |
|||
using PinkParrot.Core.Schema; |
|||
|
|||
namespace PinkParrot.Read.Models |
|||
{ |
|||
public class ModelFieldDto |
|||
{ |
|||
[JsonProperty] |
|||
public string Name { get; set; } |
|||
|
|||
[JsonProperty] |
|||
public IModelFieldProperties Properties { get; set; } |
|||
|
|||
public static ModelFieldDto Create(ModelField field) |
|||
{ |
|||
return new ModelFieldDto { Name = field.Name, Properties = field.RawProperties }; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,63 @@ |
|||
// ==========================================================================
|
|||
// ModelSchemaDto.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using PinkParrot.Core.Schema; |
|||
using PinkParrot.Infrastructure; |
|||
using Newtonsoft.Json; |
|||
// ReSharper disable UseObjectOrCollectionInitializer
|
|||
// ReSharper disable InvertIf
|
|||
|
|||
namespace PinkParrot.Read.Models |
|||
{ |
|||
public sealed class ModelSchemaDto |
|||
{ |
|||
[JsonProperty] |
|||
public string Name { get; set; } |
|||
|
|||
[JsonProperty] |
|||
public Dictionary<long, ModelFieldDto> Fields { get; set; } |
|||
|
|||
[JsonProperty] |
|||
public ModelSchemaProperties Properties { get; set; } |
|||
|
|||
public static ModelSchemaDto Create(ModelSchema schema) |
|||
{ |
|||
Guard.NotNull(schema, nameof(schema)); |
|||
|
|||
var dto = new ModelSchemaDto { Properties = schema.Properties, Name = schema.Name }; |
|||
|
|||
dto.Fields = |
|||
schema.Fields.ToDictionary( |
|||
kvp => kvp.Key, |
|||
kvp => ModelFieldDto.Create(kvp.Value)); |
|||
|
|||
return dto; |
|||
} |
|||
|
|||
public ModelSchema ToSchema(ModelFieldRegistry registry) |
|||
{ |
|||
Guard.NotNull(registry, nameof(registry)); |
|||
|
|||
var schema = ModelSchema.Create(Name, Properties); |
|||
|
|||
if (Fields != null) |
|||
{ |
|||
foreach (var kvp in Fields) |
|||
{ |
|||
var field = kvp.Value; |
|||
|
|||
schema = schema.AddOrUpdateField(registry.CreateField(kvp.Key, field.Name, field.Properties)); |
|||
} |
|||
} |
|||
|
|||
return schema; |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue