diff --git a/src/PinkParrot/Startup.cs b/src/PinkParrot/Startup.cs index 56b7fa74e..d1fc8c79e 100644 --- a/src/PinkParrot/Startup.cs +++ b/src/PinkParrot/Startup.cs @@ -16,6 +16,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using PinkParrot.Infrastructure.CQRS.Autofac; using PinkParrot.Infrastructure.CQRS.Commands; + // ReSharper disable AccessToModifiedClosure namespace PinkParrot diff --git a/src/pinkparrot_core/PinkParrot.Core/Schema/ModelField.cs b/src/pinkparrot_core/PinkParrot.Core/Schema/ModelField.cs index c13f9fe79..d5e11b2e6 100644 --- a/src/pinkparrot_core/PinkParrot.Core/Schema/ModelField.cs +++ b/src/pinkparrot_core/PinkParrot.Core/Schema/ModelField.cs @@ -6,6 +6,7 @@ // All rights reserved. // ========================================================================== +using System; using System.Collections.Generic; using System.Threading.Tasks; using PinkParrot.Infrastructure; @@ -18,10 +19,6 @@ namespace PinkParrot.Core.Schema public abstract class ModelField { private readonly long id; - private string name; - private string hint; - private string displayName; - private bool isRequired; private bool isDisabled; private bool isHidden; @@ -30,25 +27,15 @@ namespace PinkParrot.Core.Schema get { return id; } } - public string Name - { - get { return name; } - } + public abstract ModelFieldProperties RawProperties { get; } - public string Hint - { - get { return hint; } - } + public abstract string Name { get; } - public string DisplayName - { - get { return displayName; } - } + public abstract string Label { get; } - public bool IsRequired - { - get { return isRequired; } - } + public abstract string Hints { get; } + + public abstract bool IsRequired { get; } public bool IsHidden { @@ -60,61 +47,22 @@ namespace PinkParrot.Core.Schema get { return isDisabled; } } - protected ModelField(long id, string name) + protected ModelField(long id) { Guard.GreaterThan(id, 0, nameof(id)); - Guard.ValidSlug(name, nameof(name)); this.id = id; - - this.name = name; } - public ModelField Configure(dynamic settings, ICollection errors) - { - var clone = Clone(); - - if (settings.Contains("Name")) - { - clone.name = settings.Name; - - if (!clone.name.IsSlug()) - { - errors.Add("Field name must be a slug"); - } - } - - if (settings.Contains("hint")) - { - clone.hint = settings.Hint?.Trim(); - } - - if (settings.Contains("displayName")) - { - clone.displayName = settings.DisplayName?.Trim(); - } - - if (settings.Contains("IsRequired")) - { - clone.isRequired = settings.IsRequired; - } - - clone.ConfigureCore(settings, errors); - - return clone; - } - - protected virtual void ConfigureCore(dynamic settings, ICollection errors) - { - } + public abstract ModelField Configure(ModelFieldProperties newProperties, IList errors); public Task ValidateAsync(PropertyValue property, ICollection errors) { Guard.NotNull(property, nameof(property)); - if (isRequired && property.RawValue == null) + if (IsRequired && property.RawValue == null) { - errors.Add(" is required"); + errors.Add("Field is required"); } if (property.RawValue == null) @@ -134,54 +82,47 @@ namespace PinkParrot.Core.Schema { if (isHidden) { - throw new ValidationException($"The field '{name} is already hidden."); + throw new DomainException($"The field '{Name} is already hidden."); } - var clone = Clone(); - - clone.isHidden = true; - - return Clone(); + return Update(clone => clone.isHidden = true); } public ModelField Show() { if (!isHidden) { - throw new ValidationException($"The field '{name} is already visible."); + throw new DomainException($"The field '{Name} is already visible."); } - var clone = Clone(); - - clone.isHidden = false; - - return Clone(); + return Update(clone => clone.isHidden = false); } public ModelField Disable() { if (isDisabled) { - throw new ValidationException($"The field '{name} is already disabled."); + throw new DomainException($"The field '{Name} is already disabled."); } - var clone = Clone(); - - clone.isDisabled = true; - - return clone; + return Update(clone => clone.isDisabled = true); } public ModelField Enable() { if (!isDisabled) { - throw new ValidationException($"The field '{name} is already enabled."); + throw new DomainException($"The field '{Name} is already enabled."); } + + return Update(clone => clone.isDisabled = false); + } - var clone = Clone(); + protected T Update(Action updater) where T : ModelField + { + var clone = (T)Clone(); - clone.isDisabled = false; + updater(clone); return clone; } diff --git a/src/pinkparrot_core/PinkParrot.Core/Schema/ModelFieldFactory.cs b/src/pinkparrot_core/PinkParrot.Core/Schema/ModelFieldFactory.cs index e6cad2f5c..7f3b47fdd 100644 --- a/src/pinkparrot_core/PinkParrot.Core/Schema/ModelFieldFactory.cs +++ b/src/pinkparrot_core/PinkParrot.Core/Schema/ModelFieldFactory.cs @@ -6,13 +6,40 @@ // All rights reserved. // ========================================================================== +using System; +using System.Collections.Generic; +using PinkParrot.Infrastructure; + namespace PinkParrot.Core.Schema { public class ModelFieldFactory { - public virtual ModelField CreateField(long id, string type, string fieldName) + private readonly Dictionary> factories = new Dictionary>(); + + public ModelFieldFactory() + { + AddFactory(id => new NumberField(id)); + } + + public void AddFactory(Func factory) where T : ModelFieldProperties + { + Guard.NotNull(factory, nameof(factory)); + + factories[typeof(T)] = factory; + } + + public virtual ModelField CreateField(long id, ModelFieldProperties properties) { - return new NumberField(id, fieldName); + 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); } } } diff --git a/src/pinkparrot_core/PinkParrot.Core/Schema/ModelFieldProperties.cs b/src/pinkparrot_core/PinkParrot.Core/Schema/ModelFieldProperties.cs new file mode 100644 index 000000000..52399f804 --- /dev/null +++ b/src/pinkparrot_core/PinkParrot.Core/Schema/ModelFieldProperties.cs @@ -0,0 +1,39 @@ +// ========================================================================== +// ModelFieldProperties.cs +// PinkParrot Headless CMS +// ========================================================================== +// Copyright (c) PinkParrot Group +// All rights reserved. +// ========================================================================== + +using System.Collections.Generic; +using PinkParrot.Infrastructure; + +namespace PinkParrot.Core.Schema +{ + public abstract class ModelFieldProperties : NamedElementProperties + { + public bool IsRequired { get; } + + protected ModelFieldProperties( + bool isRequired, + string name, + string label, + string hints) + : base(name, label, hints) + { + IsRequired = isRequired; + } + + public override void Validate(IList errors) + { + base.Validate(errors); + + ValidateCore(errors); + } + + protected virtual void ValidateCore(IList errors) + { + } + } +} \ No newline at end of file diff --git a/src/pinkparrot_core/PinkParrot.Core/Schema/ModelField_Generic.cs b/src/pinkparrot_core/PinkParrot.Core/Schema/ModelField_Generic.cs new file mode 100644 index 000000000..8a4079892 --- /dev/null +++ b/src/pinkparrot_core/PinkParrot.Core/Schema/ModelField_Generic.cs @@ -0,0 +1,71 @@ +// ========================================================================== +// ModelField_Generic.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 abstract class ModelField : ModelField where T : ModelFieldProperties + { + private T properties; + + public override ModelFieldProperties RawProperties + { + get { return properties; } + } + + public override string Name + { + get { return properties.Name; } + } + + public override string Label + { + get { return properties.Label; } + } + + public override string Hints + { + get { return properties.Hints; } + } + + public override bool IsRequired + { + get { return properties.IsRequired; } + } + + public T Properties + { + get { return properties; } + } + + protected ModelField(long id) + : base(id) + { + } + + public override ModelField Configure(ModelFieldProperties newProperties, IList errors) + { + Guard.NotNull(newProperties, nameof(newProperties)); + Guard.NotNull(errors, nameof(errors)); + + var typedProperties = newProperties as T; + + if (typedProperties == null) + { + throw new ArgumentException($"Properties must be of type '{typeof(T)}", nameof(newProperties)); + } + + newProperties.Validate(errors); + + return Update>(clone => clone.properties = typedProperties); + } + } +} diff --git a/src/pinkparrot_core/PinkParrot.Core/Schema/ModelSchema.cs b/src/pinkparrot_core/PinkParrot.Core/Schema/ModelSchema.cs index cbacfc349..ae9493345 100644 --- a/src/pinkparrot_core/PinkParrot.Core/Schema/ModelSchema.cs +++ b/src/pinkparrot_core/PinkParrot.Core/Schema/ModelSchema.cs @@ -17,30 +17,34 @@ namespace PinkParrot.Core.Schema { public sealed class ModelSchema { - private readonly ModelSchemaMetadata metadata; + private readonly ModelSchemaProperties properties; private readonly ImmutableDictionary fields; private readonly Dictionary fieldsByName; - public ModelSchema(ModelSchemaMetadata metadata, ImmutableDictionary fields) + public ModelSchema(ModelSchemaProperties properties, ImmutableDictionary fields) { Guard.NotNull(fields, nameof(fields)); - Guard.NotNull(metadata, nameof(metadata)); + Guard.NotNull(properties, nameof(properties)); this.fields = fields; - this.metadata = metadata; + this.properties = properties; fieldsByName = fields.Values.ToDictionary(x => x.Name, StringComparer.OrdinalIgnoreCase); } - public static ModelSchema Create(string name) + public static ModelSchema Create(ModelSchemaProperties metadata) { - if (!name.IsSlug()) + var errors = new List(); + + metadata.Validate(errors); + + if (errors.Any()) { - throw new ValidationException("Cannot create the schema.", $"'{name}' is not a valid slug."); + throw new ValidationException("Failed to create a new model schema.", errors); } - return new ModelSchema(new ModelSchemaMetadata(name), ImmutableDictionary.Empty); + return new ModelSchema(metadata, ImmutableDictionary.Empty); } public IReadOnlyDictionary Fields @@ -48,34 +52,34 @@ namespace PinkParrot.Core.Schema get { return fields; } } - public ModelSchemaMetadata Metadata + public ModelSchemaProperties Properties { - get { return metadata; } + get { return properties; } } - public ModelSchema Update(ModelSchemaMetadata newMetadata) + public ModelSchema Update(ModelSchemaProperties newMetadata) { Guard.NotNull(newMetadata, nameof(newMetadata)); return new ModelSchema(newMetadata, fields); } - public ModelSchema AddField(long id, string type, string fieldName, ModelFieldFactory factory) + public ModelSchema AddField(long id, ModelFieldProperties properties, ModelFieldFactory factory) { - var field = factory.CreateField(id, type, fieldName); + var field = factory.CreateField(id, properties); return SetField(field); } - public ModelSchema SetField(long fieldId, PropertiesBag settings) + public ModelSchema SetField(long fieldId, ModelFieldProperties properties) { - Guard.NotNull(settings, nameof(settings)); + Guard.NotNull(properties, nameof(properties)); return UpdateField(fieldId, field => { - var errors = new List(); + var errors = new List(); - var newField = field.Configure(settings, errors); + var newField = field.Configure(properties, errors); if (errors.Any()) { @@ -115,7 +119,7 @@ namespace PinkParrot.Core.Schema throw new ValidationException($"A field with name '{field.Name}' already exists."); } - return new ModelSchema(metadata, fields.SetItem(field.Id, field)); + return new ModelSchema(properties, fields.SetItem(field.Id, field)); } public ModelSchema DeleteField(long fieldId) @@ -125,7 +129,7 @@ namespace PinkParrot.Core.Schema throw new ValidationException($"A field with id {fieldId} does not exist."); } - return new ModelSchema(metadata, fields.Remove(fieldId)); + return new ModelSchema(properties, fields.Remove(fieldId)); } private ModelSchema UpdateField(long fieldId, Func updater) @@ -134,7 +138,8 @@ namespace PinkParrot.Core.Schema if (!fields.TryGetValue(fieldId, out field)) { - throw new ValidationException($"Cannot update field with id '{fieldId}'.", "Field does not exist."); + throw new ValidationException($"Cannot update field with id '{fieldId}'.", + new ValidationError("Field does not exist.", "fieldId")); } var newField = updater(field); @@ -146,10 +151,12 @@ namespace PinkParrot.Core.Schema { Guard.NotNull(data, nameof(data)); - var errors = new List(); + var errors = new List(); foreach (var kvp in data.Properties) { + var fieldErrors = new List(); + ModelField field; if (fieldsByName.TryGetValue(kvp.Key, out field)) @@ -157,13 +164,13 @@ namespace PinkParrot.Core.Schema var newErrors = new List(); await field.ValidateAsync(kvp.Value, newErrors); - - errors.AddRange(newErrors.Select(e => e.Replace("", "'" + field.Name + "'"))); } else { - errors.Add($"'{kvp.Key}' is not a known field"); + fieldErrors.Add($"'{kvp.Key}' is not a known field"); } + + errors.AddRange(fieldErrors.Select(x => new ValidationError(x, kvp.Key))); } if (errors.Any()) diff --git a/src/pinkparrot_core/PinkParrot.Core/Schema/ModelSchemaMetadata.cs b/src/pinkparrot_core/PinkParrot.Core/Schema/ModelSchemaMetadata.cs deleted file mode 100644 index a767d7320..000000000 --- a/src/pinkparrot_core/PinkParrot.Core/Schema/ModelSchemaMetadata.cs +++ /dev/null @@ -1,81 +0,0 @@ -// ========================================================================== -// ModelSchemaMetadata.cs -// PinkParrot Headless CMS -// ========================================================================== -// Copyright (c) PinkParrot Group -// All rights reserved. -// ========================================================================== - -using PinkParrot.Infrastructure; - -namespace PinkParrot.Core.Schema -{ - public sealed class ModelSchemaMetadata - { - private string name; - private string displayName; - private string hint; - private string itemTitle; - - public string Name - { - get { return name; } - } - - public string DisplayName - { - get { return displayName; } - } - - public string Hint - { - get { return hint; } - } - - public string ItemTitle - { - get { return itemTitle; } - } - - public ModelSchemaMetadata(string name) - { - Guard.ValidSlug(name, nameof(name)); - - this.name = name; - } - - public ModelSchemaMetadata Configure(string newName, PropertiesBag properties) - { - Guard.NotNull(properties, nameof(properties)); - - var clone = (ModelSchemaMetadata) MemberwiseClone(); - - if (newName != null) - { - if (!newName.IsSlug()) - { - throw new ValidationException("Cannot update the schema.", $"'{newName}' is not a valid slug."); - } - - clone.name = newName; - } - - if (properties.Contains("Hint")) - { - clone.hint = properties["Hint"].ToString()?.Trim(); - } - - if (properties.Contains("DisplayName")) - { - clone.displayName = properties["DisplayName"].ToString()?.Trim(); - } - - if (properties.Contains("ItemTitle")) - { - clone.itemTitle = properties["ItemTitle"].ToString()?.Trim(); - } - - return clone; - } - } -} \ No newline at end of file diff --git a/src/pinkparrot_core/PinkParrot.Core/Schema/ModelSchemaProperties.cs b/src/pinkparrot_core/PinkParrot.Core/Schema/ModelSchemaProperties.cs new file mode 100644 index 000000000..6965596f1 --- /dev/null +++ b/src/pinkparrot_core/PinkParrot.Core/Schema/ModelSchemaProperties.cs @@ -0,0 +1,20 @@ +// ========================================================================== +// ModelSchemaMetadata.cs +// PinkParrot Headless CMS +// ========================================================================== +// Copyright (c) PinkParrot Group +// All rights reserved. +// ========================================================================== +namespace PinkParrot.Core.Schema +{ + public sealed class ModelSchemaProperties : NamedElementProperties + { + public ModelSchemaProperties( + string name, + string label, + string hints) + : base(name, label, hints) + { + } + } +} \ No newline at end of file diff --git a/src/pinkparrot_core/PinkParrot.Core/Schema/NamedElementProperties.cs b/src/pinkparrot_core/PinkParrot.Core/Schema/NamedElementProperties.cs new file mode 100644 index 000000000..2d0a00d73 --- /dev/null +++ b/src/pinkparrot_core/PinkParrot.Core/Schema/NamedElementProperties.cs @@ -0,0 +1,59 @@ +// ========================================================================== +// NamedElementProperties.cs +// PinkParrot Headless CMS +// ========================================================================== +// Copyright (c) PinkParrot Group +// All rights reserved. +// ========================================================================== + +using System.Collections.Generic; +using PinkParrot.Infrastructure; + +namespace PinkParrot.Core.Schema +{ + public abstract class NamedElementProperties + { + private readonly string name; + private readonly string label; + private readonly string hints; + + public string Name + { + get { return name; } + } + + public string Label + { + get { return string.IsNullOrWhiteSpace(label) ? name : label; } + } + + public string Hints + { + get { return hints; } + } + + protected NamedElementProperties( + string name, + string label, + string hints) + { + this.name = name; + this.label = label; + this.hints = hints; + } + + public virtual void Validate(IList errors) + { + Guard.NotNull(errors, nameof(errors)); + + if (string.IsNullOrWhiteSpace(Name)) + { + errors.Add(new ValidationError("Name cannot be empty.", "Name")); + } + else if (!Name.IsSlug()) + { + errors.Add(new ValidationError("Name must be a valid slug.", "Name")); + } + } + } +} \ No newline at end of file diff --git a/src/pinkparrot_core/PinkParrot.Core/Schema/NumberField.cs b/src/pinkparrot_core/PinkParrot.Core/Schema/NumberField.cs index 60e0ff146..4ae37df87 100644 --- a/src/pinkparrot_core/PinkParrot.Core/Schema/NumberField.cs +++ b/src/pinkparrot_core/PinkParrot.Core/Schema/NumberField.cs @@ -15,35 +15,21 @@ using PinkParrot.Infrastructure.Tasks; namespace PinkParrot.Core.Schema { - public sealed class NumberField : ModelField + public sealed class NumberField : ModelField { - private double? maxValue; - private double? minValue; - public double? MaxValue { - get { return maxValue; } + get { return Properties.MaxValue; } } public double? MinValue { - get { return minValue; } - } - - public NumberField(long id, string name) - : base(id, name) - { + get { return Properties.MinValue; } } - protected override void ConfigureCore(dynamic settings, ICollection errors) + public NumberField(long id) + : base(id) { - maxValue = settings.MaxValue; - minValue = settings.MinValue; - - if (maxValue.HasValue && minValue.HasValue && minValue.Value > maxValue.Value) - { - errors.Add("MinValue cannot be larger than max value"); - } } protected override Task ValidateCoreAsync(PropertyValue property, ICollection errors) @@ -54,17 +40,17 @@ namespace PinkParrot.Core.Schema if (MinValue.HasValue && value < MinValue.Value) { - errors.Add($" must be greater than {MinValue}"); + errors.Add($"Must be greater than {MinValue}"); } if (MaxValue.HasValue && value > MaxValue.Value) { - errors.Add($" must be less than {MaxValue}"); + errors.Add($"Must be less than {MaxValue}"); } } catch (InvalidCastException) { - errors.Add(" is not a valid number"); + errors.Add("Value is not a valid number"); } return TaskHelper.Done; diff --git a/src/pinkparrot_core/PinkParrot.Core/Schema/NumberFieldProperties.cs b/src/pinkparrot_core/PinkParrot.Core/Schema/NumberFieldProperties.cs new file mode 100644 index 000000000..1b415515a --- /dev/null +++ b/src/pinkparrot_core/PinkParrot.Core/Schema/NumberFieldProperties.cs @@ -0,0 +1,42 @@ +// ========================================================================== +// NumberFieldProperties.cs +// PinkParrot Headless CMS +// ========================================================================== +// Copyright (c) PinkParrot Group +// All rights reserved. +// ========================================================================== + +using System.Collections.Generic; +using PinkParrot.Infrastructure; + +namespace PinkParrot.Core.Schema +{ + [TypeName("Number")] + public sealed class NumberFieldProperties : ModelFieldProperties + { + public double? MaxValue { get; } + + public double? MinValue { get; } + + public NumberFieldProperties( + bool isRequired, + string name, + string label, + string hints, + double? minValue, + double? maxValue) + : base(isRequired, name, label, hints) + { + MinValue = minValue; + MaxValue = maxValue; + } + + protected override void ValidateCore(IList errors) + { + if (MaxValue.HasValue && MinValue.HasValue && MinValue.Value > MaxValue.Value) + { + errors.Add(new ValidationError("MinValue cannot be larger than max value", "MinValue", "MaxValue")); + } + } + } +} diff --git a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldAdded.cs b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldAdded.cs index f74488f4f..52435fe2f 100644 --- a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldAdded.cs +++ b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldAdded.cs @@ -6,14 +6,14 @@ // All rights reserved. // ========================================================================== +using PinkParrot.Core.Schema; + namespace PinkParrot.Events.Schema { public class ModelFieldAdded : TenantEvent { public long FieldId; - public string FieldType; - - public string FieldName; + public ModelFieldProperties Properties; } } diff --git a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldDeleted.cs b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldDeleted.cs index c131b4ff5..5f9dbec71 100644 --- a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldDeleted.cs +++ b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldDeleted.cs @@ -5,7 +5,6 @@ // Copyright (c) PinkParrot Group // All rights reserved. // ========================================================================== - namespace PinkParrot.Events.Schema { public class ModelFieldDeleted : TenantEvent diff --git a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldDisabled.cs b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldDisabled.cs index b48984d21..e47b8084a 100644 --- a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldDisabled.cs +++ b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldDisabled.cs @@ -5,7 +5,6 @@ // Copyright (c) PinkParrot Group // All rights reserved. // ========================================================================== - namespace PinkParrot.Events.Schema { public class ModelFieldDisabled : TenantEvent diff --git a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldEnabled.cs b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldEnabled.cs index 37bb0d1c2..327d70637 100644 --- a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldEnabled.cs +++ b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldEnabled.cs @@ -5,7 +5,6 @@ // Copyright (c) PinkParrot Group // All rights reserved. // ========================================================================== - namespace PinkParrot.Events.Schema { public class ModelFieldEnabled : TenantEvent diff --git a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldHidden.cs b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldHidden.cs index 671257b63..284ccf369 100644 --- a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldHidden.cs +++ b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldHidden.cs @@ -5,7 +5,6 @@ // Copyright (c) PinkParrot Group // All rights reserved. // ========================================================================== - namespace PinkParrot.Events.Schema { public class ModelFieldHidden : TenantEvent diff --git a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldShown.cs b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldShown.cs index 06a0851ac..f2a6b7310 100644 --- a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldShown.cs +++ b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldShown.cs @@ -5,7 +5,6 @@ // Copyright (c) PinkParrot Group // All rights reserved. // ========================================================================== - namespace PinkParrot.Events.Schema { public class ModelFieldShown : TenantEvent diff --git a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldUpdated.cs b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldUpdated.cs index 881346f9d..135f5230e 100644 --- a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldUpdated.cs +++ b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldUpdated.cs @@ -6,7 +6,7 @@ // All rights reserved. // ========================================================================== -using PinkParrot.Infrastructure; +using PinkParrot.Core.Schema; namespace PinkParrot.Events.Schema { @@ -14,6 +14,6 @@ namespace PinkParrot.Events.Schema { public long FieldId; - public PropertiesBag Settings { get; set; } + public ModelFieldProperties Properties; } } diff --git a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaCreated.cs b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaCreated.cs index 013659478..b2f5b268c 100644 --- a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaCreated.cs +++ b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaCreated.cs @@ -6,10 +6,12 @@ // All rights reserved. // ========================================================================== +using PinkParrot.Core.Schema; + namespace PinkParrot.Events.Schema { public class ModelSchemaCreated : TenantEvent { - public string Name; + public ModelSchemaProperties Properties; } } diff --git a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaDeleted.cs b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaDeleted.cs index 78938048a..16f577d09 100644 --- a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaDeleted.cs +++ b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaDeleted.cs @@ -5,7 +5,6 @@ // Copyright (c) PinkParrot Group // All rights reserved. // ========================================================================== - namespace PinkParrot.Events.Schema { public class ModelSchemaDeleted : TenantEvent diff --git a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaUpdated.cs b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaUpdated.cs index 638028bd7..d9f2b98f1 100644 --- a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaUpdated.cs +++ b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaUpdated.cs @@ -6,14 +6,12 @@ // All rights reserved. // ========================================================================== -using PinkParrot.Infrastructure; +using PinkParrot.Core.Schema; namespace PinkParrot.Events.Schema { public class ModelSchemaUpdated : TenantEvent { - public string NewName; - - public PropertiesBag Settings { get; set; } + public ModelSchemaProperties Properties; } } diff --git a/src/pinkparrot_events/PinkParrot.Events/project.json b/src/pinkparrot_events/PinkParrot.Events/project.json index e676a1907..8421dc721 100644 --- a/src/pinkparrot_events/PinkParrot.Events/project.json +++ b/src/pinkparrot_events/PinkParrot.Events/project.json @@ -4,6 +4,7 @@ "dependencies": { "NETStandard.Library": "1.6.0", "NodaTime": "2.0.0-alpha20160729", + "PinkParrot.Core": "1.0.0-*", "PinkParrot.Infrastructure": "1.0.0-*" }, diff --git a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure.Tests/CollectionExtensionsTests.cs b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure.Tests/CollectionExtensionsTests.cs index e6f0a62e0..03f863e53 100644 --- a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure.Tests/CollectionExtensionsTests.cs +++ b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure.Tests/CollectionExtensionsTests.cs @@ -1,5 +1,5 @@ // ========================================================================== -// CollectionExtensionsTest.cs +// CollectionExtensionsTests.cs // PinkParrot Headless CMS // ========================================================================== // Copyright (c) PinkParrot Group diff --git a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure.Tests/DispatchingTests.cs b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure.Tests/DispatchingTests.cs index 37619d378..66a8a34aa 100644 --- a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure.Tests/DispatchingTests.cs +++ b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure.Tests/DispatchingTests.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using PinkParrot.Infrastructure.Dispatching; using PinkParrot.Infrastructure.Tasks; using Xunit; + // ReSharper disable UnusedMethodReturnValue.Local // ReSharper disable UnusedParameter.Local // ReSharper disable UnusedMember.Local diff --git a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure.Tests/EnumExtensionsTests.cs b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure.Tests/EnumExtensionsTests.cs index 735ef5b94..daf9977fe 100644 --- a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure.Tests/EnumExtensionsTests.cs +++ b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure.Tests/EnumExtensionsTests.cs @@ -1,5 +1,5 @@ // ========================================================================== -// EnumExtensionsTest.cs +// EnumExtensionsTests.cs // PinkParrot Headless CMS // ========================================================================== // Copyright (c) PinkParrot Group diff --git a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Commands/CommandContext.cs b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Commands/CommandContext.cs index 1689921b1..ef68d81b8 100644 --- a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Commands/CommandContext.cs +++ b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Commands/CommandContext.cs @@ -1,9 +1,9 @@ // ========================================================================== -// CommandContext.cs -// Green Parrot Framework +// CommandContext.cs +// PinkParrot Headless CMS // ========================================================================== -// Copyright (c) Sebastian Stehle -// All rights reserved. +// Copyright (c) PinkParrot Group +// All rights reserved. // ========================================================================== using System; diff --git a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Commands/ICommand.cs b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Commands/ICommand.cs index 465954f13..cc4d6f5da 100644 --- a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Commands/ICommand.cs +++ b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Commands/ICommand.cs @@ -5,7 +5,6 @@ // Copyright (c) PinkParrot Group // All rights reserved. // ========================================================================== - namespace PinkParrot.Infrastructure.CQRS.Commands { public interface ICommand diff --git a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Events/IEventConsumer.cs b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Events/IEventConsumer.cs index f7a243d13..80b0736fa 100644 --- a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Events/IEventConsumer.cs +++ b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Events/IEventConsumer.cs @@ -5,7 +5,6 @@ // Copyright (c) PinkParrot Group // All rights reserved. // ========================================================================== - namespace PinkParrot.Infrastructure.CQRS.Events { public interface IEventConsumer diff --git a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/GetEventStore/GetEventStoreDomainObjectRepository.cs b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/GetEventStore/GetEventStoreDomainObjectRepository.cs index dc2d69950..9f25e4942 100644 --- a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/GetEventStore/GetEventStoreDomainObjectRepository.cs +++ b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/GetEventStore/GetEventStoreDomainObjectRepository.cs @@ -1,8 +1,10 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - +// ========================================================================== +// GetEventStoreDomainObjectRepository.cs +// PinkParrot Headless CMS +// ========================================================================== +// Copyright (c) PinkParrot Group +// All rights reserved. +// ========================================================================== namespace PinkParrot.Infrastructure.CQRS.GetEventStore { public class GetEventStoreDomainObjectRepository diff --git a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/ActionContextDispatcher.cs b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/ActionContextDispatcher.cs index a01cc87be..64b8cf08f 100644 --- a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/ActionContextDispatcher.cs +++ b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/ActionContextDispatcher.cs @@ -1,5 +1,5 @@ // ========================================================================== -// ActionDispatcher.cs +// ActionContextDispatcher.cs // PinkParrot Headless CMS // ========================================================================== // Copyright (c) PinkParrot Group @@ -25,7 +25,7 @@ namespace PinkParrot.Infrastructure.Dispatching .Where(Helper.HasRightName) .Where(Helper.HasRightParameters) .Select(ActionContextDispatcherFactory.CreateActionHandler) - .ToDictionary(h => h.Item1, h => h.Item2); + .ToDictionary>, Type, Action>(h => h.Item1, h => h.Item2); } public static bool Dispatch(TTarget target, TIn input, TContext context) diff --git a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/ActionContextDispatcherFactory.cs b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/ActionContextDispatcherFactory.cs index 800e343fe..4052d55b1 100644 --- a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/ActionContextDispatcherFactory.cs +++ b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/ActionContextDispatcherFactory.cs @@ -1,5 +1,5 @@ // ========================================================================== -// ActionHandlerFactory.cs +// ActionContextDispatcherFactory.cs // PinkParrot Headless CMS // ========================================================================== // Copyright (c) PinkParrot Group diff --git a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/ActionDispatcher.cs b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/ActionDispatcher.cs index d0b1ede37..ee20958f3 100644 --- a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/ActionDispatcher.cs +++ b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/ActionDispatcher.cs @@ -25,7 +25,7 @@ namespace PinkParrot.Infrastructure.Dispatching .Where(Helper.HasRightName) .Where(Helper.HasRightParameters) .Select(ActionDispatcherFactory.CreateActionHandler) - .ToDictionary(h => h.Item1, h => h.Item2); + .ToDictionary>, Type, Action>(h => h.Item1, h => h.Item2); } public static bool Dispatch(TTarget target, TIn item) diff --git a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/ActionDispatcherFactory.cs b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/ActionDispatcherFactory.cs index c42fb1550..1adb8118a 100644 --- a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/ActionDispatcherFactory.cs +++ b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/ActionDispatcherFactory.cs @@ -1,5 +1,5 @@ // ========================================================================== -// ActionHandlerFactory.cs +// ActionDispatcherFactory.cs // PinkParrot Headless CMS // ========================================================================== // Copyright (c) PinkParrot Group diff --git a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/FuncContextDispatcher.cs b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/FuncContextDispatcher.cs index e166d71da..c05e2225f 100644 --- a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/FuncContextDispatcher.cs +++ b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/FuncContextDispatcher.cs @@ -1,5 +1,5 @@ // ========================================================================== -// FuncDispatcher.cs +// FuncContextDispatcher.cs // PinkParrot Headless CMS // ========================================================================== // Copyright (c) PinkParrot Group @@ -26,7 +26,7 @@ namespace PinkParrot.Infrastructure.Dispatching .Where(Helper.HasRightParameters) .Where(Helper.HasRightReturnType) .Select(FuncContextDispatcherFactory.CreateFuncHandler) - .ToDictionary(h => h.Item1, h => h.Item2); + .ToDictionary>, Type, Func>(h => h.Item1, h => h.Item2); } public static TOut Dispatch(TTarget target, TIn item, TContext context) diff --git a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/FuncContextDispatcherFactory.cs b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/FuncContextDispatcherFactory.cs index 448afec09..7a4ea8a69 100644 --- a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/FuncContextDispatcherFactory.cs +++ b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/FuncContextDispatcherFactory.cs @@ -1,5 +1,5 @@ // ========================================================================== -// HandlerFactory.cs +// FuncContextDispatcherFactory.cs // PinkParrot Headless CMS // ========================================================================== // Copyright (c) PinkParrot Group diff --git a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/FuncDispatcher.cs b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/FuncDispatcher.cs index 488197286..ba7254c21 100644 --- a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/FuncDispatcher.cs +++ b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/FuncDispatcher.cs @@ -26,7 +26,7 @@ namespace PinkParrot.Infrastructure.Dispatching .Where(Helper.HasRightParameters) .Where(Helper.HasRightReturnType) .Select(FuncDispatcherFactory.CreateFuncHandler) - .ToDictionary(h => h.Item1, h => h.Item2); + .ToDictionary>, Type, Func>(h => h.Item1, h => h.Item2); } public static TOut Dispatch(TTarget target, TIn item) diff --git a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/FuncDispatcherFactory.cs b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/FuncDispatcherFactory.cs index ea7cbdba1..a2cc41e49 100644 --- a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/FuncDispatcherFactory.cs +++ b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/FuncDispatcherFactory.cs @@ -1,5 +1,5 @@ // ========================================================================== -// HandlerFactory.cs +// FuncDispatcherFactory.cs // PinkParrot Headless CMS // ========================================================================== // Copyright (c) PinkParrot Group diff --git a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/DomainException.cs b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/DomainException.cs new file mode 100644 index 000000000..81d14b5b4 --- /dev/null +++ b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/DomainException.cs @@ -0,0 +1,25 @@ +// ========================================================================== +// DomainException.cs +// PinkParrot Headless CMS +// ========================================================================== +// Copyright (c) PinkParrot Group +// All rights reserved. +// ========================================================================== + +using System; + +namespace PinkParrot.Infrastructure +{ + public class DomainException : Exception + { + public DomainException(string message) + : base(message) + { + } + + public DomainException(string message, Exception inner) + : base(message, inner) + { + } + } +} diff --git a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Json/JsonPropertiesBagConverter.cs b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Json/PropertiesBagConverter.cs similarity index 98% rename from src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Json/JsonPropertiesBagConverter.cs rename to src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Json/PropertiesBagConverter.cs index af3b5a364..1e1a452e8 100644 --- a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Json/JsonPropertiesBagConverter.cs +++ b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Json/PropertiesBagConverter.cs @@ -1,5 +1,5 @@ // ========================================================================== -// JsonPropertiesBagConverter.cs +// PropertiesBagConverter.cs // PinkParrot Headless CMS // ========================================================================== // Copyright (c) PinkParrot Group diff --git a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Json/TypeNameSerializationBinder.cs b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Json/TypeNameSerializationBinder.cs new file mode 100644 index 000000000..f475fa6f1 --- /dev/null +++ b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Json/TypeNameSerializationBinder.cs @@ -0,0 +1,71 @@ +// ========================================================================== +// TypeNameSerializationBinder.cs +// PinkParrot Headless CMS +// ========================================================================== +// Copyright (c) PinkParrot Group +// All rights reserved. +// ========================================================================== + +using System; +using System.Collections.Generic; +using System.Reflection; +using Newtonsoft.Json.Serialization; + +namespace PinkParrot.Infrastructure.Json +{ + public class TypeNameSerializationBinder : DefaultSerializationBinder + { + private readonly Dictionary namesByType = new Dictionary(); + private readonly Dictionary typesByName = new Dictionary(StringComparer.OrdinalIgnoreCase); + + public TypeNameSerializationBinder Map(Type type, string name) + { + Guard.NotNull(type, nameof(type)); + Guard.NotNull(name, nameof(name)); + + namesByType.Add(type, name); + typesByName.Add(name, type); + + return this; + } + + public TypeNameSerializationBinder Map(Assembly assembly) + { + foreach (var type in assembly.GetTypes()) + { + var typeNameAttribute = type.GetTypeInfo().GetCustomAttribute(); + + if (!string.IsNullOrWhiteSpace(typeNameAttribute?.TypeName)) + { + Map(type, typeNameAttribute.TypeName); + } + } + + return this; + } + + public override Type BindToType(string assemblyName, string typeName) + { + var type = typesByName.GetOrDefault(typeName); + + return type ?? base.BindToType(assemblyName, typeName); + } + + public override void BindToName(Type serializedType, out string assemblyName, out string typeName) + { + assemblyName = null; + + var name = namesByType.GetOrDefault(serializedType); + + if (name != null) + { + typeName = name; + } + else + { + base.BindToName(serializedType, out assemblyName, out typeName); + } + } + } +} + diff --git a/src/pinkparrot_write/PinkParrot.Write/Schema/ISchemaIdProvider.cs b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/TypeNameAttribute.cs similarity index 52% rename from src/pinkparrot_write/PinkParrot.Write/Schema/ISchemaIdProvider.cs rename to src/pinkparrot_infrastructure/PinkParrot.Infrastructure/TypeNameAttribute.cs index 9fbe52e39..a3cee0193 100644 --- a/src/pinkparrot_write/PinkParrot.Write/Schema/ISchemaIdProvider.cs +++ b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/TypeNameAttribute.cs @@ -1,5 +1,5 @@ // ========================================================================== -// ISchemaIdProvider.cs +// TypeNameAttribute.cs // PinkParrot Headless CMS // ========================================================================== // Copyright (c) PinkParrot Group @@ -7,12 +7,17 @@ // ========================================================================== using System; -using System.Threading.Tasks; -namespace PinkParrot.Write.Schema +namespace PinkParrot.Infrastructure { - public interface ISchemaIdProvider + [AttributeUsage(AttributeTargets.Class, Inherited = false)] + public class TypeNameAttribute : Attribute { - Task FindSchemaId(string name); + public string TypeName { get; } + + public TypeNameAttribute(string typeName) + { + TypeName = typeName; + } } -} +} \ No newline at end of file diff --git a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/ValidationError.cs b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/ValidationError.cs new file mode 100644 index 000000000..a08bd829c --- /dev/null +++ b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/ValidationError.cs @@ -0,0 +1,38 @@ +// ========================================================================== +// ValidationError.cs +// PinkParrot Headless CMS +// ========================================================================== +// Copyright (c) PinkParrot Group +// All rights reserved. +// ========================================================================== + +using System.Collections.Generic; + +namespace PinkParrot.Infrastructure +{ + public sealed class ValidationError + { + private static readonly string[] FalbackProperties = new string[0]; + private readonly string message; + private readonly string[] propertyNames; + + public string Message + { + get { return message; } + } + + public IEnumerable PropertyNames + { + get { return propertyNames; } + } + + public ValidationError(string message, params string[] propertyNames) + { + Guard.NotNullOrEmpty(message, nameof(message)); + + this.message = message; + + this.propertyNames = propertyNames ?? FalbackProperties; + } + } +} \ No newline at end of file diff --git a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/ValidationException.cs b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/ValidationException.cs index eb32706b8..ca28712d6 100644 --- a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/ValidationException.cs +++ b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/ValidationException.cs @@ -14,35 +14,36 @@ namespace PinkParrot.Infrastructure { public class ValidationException : Exception { - private readonly IReadOnlyList errors; + private static readonly List FallbackErrors = new List(); + private readonly IReadOnlyList errors; - public IReadOnlyList Errors + public IReadOnlyList Errors { get { return errors; } } - public ValidationException(string message, params string[] errors) + public ValidationException(string message, params ValidationError[] errors) : base(message) { - this.errors = errors != null ? errors.ToList() : new List(); + this.errors = errors != null ? errors.ToList() : FallbackErrors; } - public ValidationException(string message, IReadOnlyList errors) + public ValidationException(string message, IReadOnlyList errors) : base(message) { - this.errors = errors ?? new List(); + this.errors = errors ?? FallbackErrors; } - public ValidationException(string message, Exception inner, params string[] errors) + public ValidationException(string message, Exception inner, params ValidationError[] errors) : base(message, inner) { - this.errors = errors != null ? errors.ToList() : new List(); + this.errors = errors != null ? errors.ToList() : FallbackErrors; } - public ValidationException(string message, Exception inner, IReadOnlyList errors) + public ValidationException(string message, Exception inner, IReadOnlyList errors) : base(message, inner) { - this.errors = errors ?? new List(); + this.errors = errors ?? FallbackErrors; } } } diff --git a/src/pinkparrot_read/PinkParrot.Read/Models/ModelSchemaRM.cs b/src/pinkparrot_read/PinkParrot.Read/Models/ModelSchemaRM.cs index 3f9d4e730..86b35ddb7 100644 --- a/src/pinkparrot_read/PinkParrot.Read/Models/ModelSchemaRM.cs +++ b/src/pinkparrot_read/PinkParrot.Read/Models/ModelSchemaRM.cs @@ -1,7 +1,12 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +// ========================================================================== +// ModelSchemaRM.cs +// PinkParrot Headless CMS +// ========================================================================== +// Copyright (c) PinkParrot Group +// All rights reserved. +// ========================================================================== + +using System; namespace PinkParrot.Read.Models { diff --git a/src/pinkparrot_read/PinkParrot.Read/Repositories/MongoDb/MongoDbModelSchemaRepository.cs b/src/pinkparrot_read/PinkParrot.Read/Repositories/MongoDb/MongoDbModelSchemaRepository.cs index dad9a3c29..a7c824245 100644 --- a/src/pinkparrot_read/PinkParrot.Read/Repositories/MongoDb/MongoDbModelSchemaRepository.cs +++ b/src/pinkparrot_read/PinkParrot.Read/Repositories/MongoDb/MongoDbModelSchemaRepository.cs @@ -9,7 +9,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using MongoDB.Bson; using MongoDB.Driver; using PinkParrot.Read.Models; using PinkParrot.Read.Repositories.MongoDb.Utils; diff --git a/src/pinkparrot_read/PinkParrot.Read/Repositories/MongoDb/Utils/BaseRepository.cs b/src/pinkparrot_read/PinkParrot.Read/Repositories/MongoDb/Utils/BaseRepository.cs index b87fd6248..5c6ed0246 100644 --- a/src/pinkparrot_read/PinkParrot.Read/Repositories/MongoDb/Utils/BaseRepository.cs +++ b/src/pinkparrot_read/PinkParrot.Read/Repositories/MongoDb/Utils/BaseRepository.cs @@ -1,7 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +// ========================================================================== +// BaseRepository.cs +// PinkParrot Headless CMS +// ========================================================================== +// Copyright (c) PinkParrot Group +// All rights reserved. +// ========================================================================== + using MongoDB.Driver; using PinkParrot.Infrastructure; diff --git a/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/AddModelField.cs b/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/AddModelField.cs index dd9b1937c..8ed607163 100644 --- a/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/AddModelField.cs +++ b/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/AddModelField.cs @@ -6,14 +6,13 @@ // All rights reserved. // ========================================================================== +using PinkParrot.Core.Schema; using PinkParrot.Infrastructure.CQRS.Commands; namespace PinkParrot.Write.Schema.Commands { public class AddModelField : AggregateCommand { - public string FieldType; - - public string FieldName; + public ModelFieldProperties Properties; } } \ No newline at end of file diff --git a/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/CreateModelSchema.cs b/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/CreateModelSchema.cs index 6be8f93b7..f3b04cc5a 100644 --- a/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/CreateModelSchema.cs +++ b/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/CreateModelSchema.cs @@ -6,12 +6,13 @@ // All rights reserved. // ========================================================================== +using PinkParrot.Core.Schema; using PinkParrot.Infrastructure.CQRS.Commands; namespace PinkParrot.Write.Schema.Commands { public class CreateModelSchema : AggregateCommand { - public string Name; + public ModelSchemaProperties Properties; } } \ No newline at end of file diff --git a/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/UpdateModelField.cs b/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/UpdateModelField.cs index 387c34335..eab6cd660 100644 --- a/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/UpdateModelField.cs +++ b/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/UpdateModelField.cs @@ -6,7 +6,7 @@ // All rights reserved. // ========================================================================== -using PinkParrot.Infrastructure; +using PinkParrot.Core.Schema; using PinkParrot.Infrastructure.CQRS.Commands; namespace PinkParrot.Write.Schema.Commands @@ -15,6 +15,6 @@ namespace PinkParrot.Write.Schema.Commands { public long FieldId; - public PropertiesBag Settings; + public ModelFieldProperties Properties; } } \ No newline at end of file diff --git a/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/UpdateModelSchema.cs b/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/UpdateModelSchema.cs index 3aada1f07..d6e5464f0 100644 --- a/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/UpdateModelSchema.cs +++ b/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/UpdateModelSchema.cs @@ -6,15 +6,13 @@ // All rights reserved. // ========================================================================== -using PinkParrot.Infrastructure; +using PinkParrot.Core.Schema; using PinkParrot.Infrastructure.CQRS.Commands; namespace PinkParrot.Write.Schema.Commands { public class UpdateModelSchema : AggregateCommand { - public string NewName; - - public PropertiesBag Settings { get; set; } + public ModelSchemaProperties Properties; } } \ No newline at end of file diff --git a/src/pinkparrot_write/PinkParrot.Write/Schema/ModelSchemaDomainObject.cs b/src/pinkparrot_write/PinkParrot.Write/Schema/ModelSchemaDomainObject.cs index 70bb100e1..8afa0bcae 100644 --- a/src/pinkparrot_write/PinkParrot.Write/Schema/ModelSchemaDomainObject.cs +++ b/src/pinkparrot_write/PinkParrot.Write/Schema/ModelSchemaDomainObject.cs @@ -41,19 +41,19 @@ namespace PinkParrot.Write.Schema protected void Apply(ModelFieldAdded @event) { - schema = schema.AddField(@event.FieldId, @event.FieldType, @event.FieldName, fieldFactory); + schema = schema.AddField(@event.FieldId, @event.Properties, fieldFactory); totalFields++; } protected void Apply(ModelSchemaCreated @event) { - schema = ModelSchema.Create(@event.Name); + schema = ModelSchema.Create(@event.Properties); } protected void Apply(ModelFieldUpdated @event) { - schema = schema.SetField(@event.FieldId, @event.Settings); + schema = schema.SetField(@event.FieldId, @event.Properties); } public void Apply(ModelFieldHidden @event) @@ -78,7 +78,7 @@ namespace PinkParrot.Write.Schema protected void Apply(ModelSchemaUpdated @event) { - schema = schema.Update(schema.Metadata.Configure(@event.NewName, @event.Settings)); + schema = schema.Update(@event.Properties); } protected void Apply(ModelFieldDeleted @event) @@ -97,36 +97,36 @@ namespace PinkParrot.Write.Schema var id = ++totalFields; - schema = schema.AddField(id, command.FieldType, command.FieldName, fieldFactory); + schema = schema.AddField(id, command.Properties, fieldFactory); - RaiseEvent(new ModelFieldAdded { FieldId = id, FieldType = command.FieldType, FieldName = command.FieldName }, true); + RaiseEvent(new ModelFieldAdded { FieldId = id, Properties = command.Properties }, true); } public void Create(CreateModelSchema command) { VerifyNotCreated(); - schema = ModelSchema.Create(command.Name); + schema = ModelSchema.Create(command.Properties); - RaiseEvent(new ModelSchemaCreated { Name = command.Name }, true); + RaiseEvent(new ModelSchemaCreated { Properties = command.Properties }, true); } public void Update(UpdateModelSchema command) { VerifyCreatedAndNotDeleted(); - schema = schema.Update(schema.Metadata.Configure(command.NewName, command.Settings)); + schema = schema.Update(command.Properties); - RaiseEvent(new ModelSchemaUpdated { NewName = command.NewName, Settings = command.Settings }, true); + RaiseEvent(new ModelSchemaUpdated { Properties = command.Properties }, true); } public void UpdateField(UpdateModelField command) { VerifyCreatedAndNotDeleted(); - schema = schema.SetField(command.FieldId, command.Settings); + schema = schema.SetField(command.FieldId, command.Properties); - RaiseEvent(new ModelFieldUpdated { FieldId = command.FieldId, Settings = command.Settings }, true); + RaiseEvent(new ModelFieldUpdated { FieldId = command.FieldId, Properties = command.Properties }, true); } public void HideField(HideModelField command) diff --git a/src/pinkparrot_write/PinkParrot.Write/Schema/ModelSchemaNameMap.cs b/src/pinkparrot_write/PinkParrot.Write/Schema/ModelSchemaNameMap.cs deleted file mode 100644 index 92d83cead..000000000 --- a/src/pinkparrot_write/PinkParrot.Write/Schema/ModelSchemaNameMap.cs +++ /dev/null @@ -1,70 +0,0 @@ -// ========================================================================== -// ModelSchemaNameMap.cs -// PinkParrot Headless CMS -// ========================================================================== -// Copyright (c) PinkParrot Group -// All rights reserved. -// ========================================================================== - -using System; -using System.Collections.Generic; -using PinkParrot.Events.Schema; -using PinkParrot.Infrastructure.CQRS; -using PinkParrot.Infrastructure.CQRS.Events; -using PinkParrot.Infrastructure.Dispatching; -// ReSharper disable InvertIf - -namespace PinkParrot.Write.Schema -{ - public class ModelSchemaNameMap : DomainObject - { - private readonly Dictionary schemaIdsByName = new Dictionary(); - private readonly Dictionary schemaNamesByIds = new Dictionary(); - - public ModelSchemaNameMap(Guid id, int version) - : base(id, version) - { - } - - protected void On(ModelSchemaDeleted @event, EnvelopeHeaders headers) - { - var aggregateId = headers.AggregateId(); - - string oldName; - - if (schemaNamesByIds.TryGetValue(aggregateId, out oldName)) - { - schemaIdsByName.Remove(oldName); - schemaNamesByIds.Remove(aggregateId); - } - } - - protected void On(ModelSchemaUpdated @event, EnvelopeHeaders headers) - { - var aggregateId = headers.AggregateId(); - - string oldName; - - if (schemaNamesByIds.TryGetValue(aggregateId, out oldName)) - { - schemaIdsByName.Remove(oldName); - schemaIdsByName[@event.NewName] = aggregateId; - } - } - - protected void On(ModelSchemaCreated @event, EnvelopeHeaders headers) - { - schemaIdsByName[@event.Name] = headers.AggregateId(); - } - - public void Apply(Envelope @event) - { - ApplyEvent(@event); - } - - protected override void ApplyEvent(Envelope @event) - { - this.DispatchAction(@event.Payload, @event.Headers); - } - } -}