From 56a0706fad04276fc476eede1e84e8a350a7b5a0 Mon Sep 17 00:00:00 2001 From: Sebastian Stehle Date: Tue, 13 Sep 2016 22:17:00 +0200 Subject: [PATCH] Temp --- .../Configurations/InfrastructureModule.cs | 7 +- src/PinkParrot/Configurations/ReadModule.cs | 2 +- src/PinkParrot/Configurations/Serializers.cs | 15 +++- .../Modules/Api/Schemas/CreateFieldDto.cs | 25 ++++++ .../Modules/Api/Schemas/CreateSchemaDto.cs | 22 +++++ .../{SchemasDto.cs => ListSchemaDto.cs} | 2 +- .../Api/Schemas/SchemaFieldsController.cs | 10 +-- .../Modules/Api/Schemas/SchemasController.cs | 10 +-- .../Modules/Api/Schemas/UpdateFieldDto.cs | 19 ++++ .../PinkParrot.Core/Schema/ModelSchema.cs | 4 +- .../Schema/ModelFieldAdded.cs | 6 +- .../Schema/ModelFieldDeleted.cs | 2 +- .../Schema/ModelFieldDisabled.cs | 2 +- .../Schema/ModelFieldEnabled.cs | 2 +- .../Schema/ModelFieldHidden.cs | 2 +- .../Schema/ModelFieldShown.cs | 2 +- .../Schema/ModelFieldUpdated.cs | 4 +- .../Schema/ModelSchemaCreated.cs | 4 +- .../Schema/ModelSchemaUpdated.cs | 2 +- .../PinkParrot.Events/TenantEvent.cs | 2 +- .../CQRS/Commands/CommandContext.cs | 18 +--- .../CQRS/Commands/CommandHandler.cs | 88 +++++++++++++++++++ .../CQRS/Commands/CommandingExtensions.cs | 2 +- .../CQRS/Commands/InMemoryCommandBus.cs | 15 +--- .../CQRS/DomainObject.cs | 15 +--- .../Schema/Commands/AddModelField.cs | 6 +- .../Schema/Commands/DeleteModelField.cs | 2 +- .../Schema/Commands/DisableModelField.cs | 2 +- .../Schema/Commands/EnableModelField.cs | 2 +- .../Schema/Commands/HideModelField.cs | 2 +- .../Schema/Commands/ShowModelField.cs | 2 +- .../Schema/Commands/UpdateModelField.cs | 2 +- .../Schema/ModelSchemaCommandHandler.cs | 71 ++++++++------- .../Schema/ModelSchemaDomainObject.cs | 60 ++++--------- 34 files changed, 271 insertions(+), 160 deletions(-) create mode 100644 src/PinkParrot/Modules/Api/Schemas/CreateFieldDto.cs create mode 100644 src/PinkParrot/Modules/Api/Schemas/CreateSchemaDto.cs rename src/PinkParrot/Modules/Api/Schemas/{SchemasDto.cs => ListSchemaDto.cs} (95%) create mode 100644 src/PinkParrot/Modules/Api/Schemas/UpdateFieldDto.cs create mode 100644 src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Commands/CommandHandler.cs diff --git a/src/PinkParrot/Configurations/InfrastructureModule.cs b/src/PinkParrot/Configurations/InfrastructureModule.cs index c5a62eff8..302b60649 100644 --- a/src/PinkParrot/Configurations/InfrastructureModule.cs +++ b/src/PinkParrot/Configurations/InfrastructureModule.cs @@ -15,11 +15,12 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.Extensions.DependencyInjection; using MongoDB.Driver; +using PinkParrot.Core.Schema; using PinkParrot.Infrastructure.CQRS.Autofac; using PinkParrot.Infrastructure.CQRS.Commands; using PinkParrot.Infrastructure.CQRS.EventStore; using PinkParrot.Pipeline; -using PinkParrot.Read.Services.Implementations; +using PinkParrot.Read.Repositories.Implementations.Mongo; namespace PinkParrot.Configurations { @@ -84,6 +85,10 @@ namespace PinkParrot.Configurations builder.RegisterType() .AsSelf() .SingleInstance(); + + builder.RegisterType() + .AsSelf() + .SingleInstance(); } } diff --git a/src/PinkParrot/Configurations/ReadModule.cs b/src/PinkParrot/Configurations/ReadModule.cs index 1bbdd2f02..208545cc9 100644 --- a/src/PinkParrot/Configurations/ReadModule.cs +++ b/src/PinkParrot/Configurations/ReadModule.cs @@ -9,7 +9,7 @@ using Autofac; using PinkParrot.Infrastructure.CQRS.Events; using PinkParrot.Read.Repositories; -using PinkParrot.Read.Repositories.Implementations; +using PinkParrot.Read.Repositories.Implementations.Mongo; using PinkParrot.Read.Services; using PinkParrot.Read.Services.Implementations; diff --git a/src/PinkParrot/Configurations/Serializers.cs b/src/PinkParrot/Configurations/Serializers.cs index f68b12759..319c79019 100644 --- a/src/PinkParrot/Configurations/Serializers.cs +++ b/src/PinkParrot/Configurations/Serializers.cs @@ -11,7 +11,8 @@ using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using PinkParrot.Core.Schema; -using PinkParrot.Core.Schema.Json; +using PinkParrot.Events.Schema; +using PinkParrot.Infrastructure; using PinkParrot.Infrastructure.CQRS.EventStore; using PinkParrot.Infrastructure.Json; @@ -21,7 +22,7 @@ namespace PinkParrot.Configurations { private static JsonSerializerSettings ConfigureJson(JsonSerializerSettings settings) { - settings.Binder = new TypeNameSerializationBinder().Map(typeof(ModelSchema).GetTypeInfo().Assembly); + settings.Binder = new TypeNameSerializationBinder(); settings.ContractResolver = new CamelCasePropertyNamesContractResolver(); settings.Converters.Add(new PropertiesBagConverter()); settings.NullValueHandling = NullValueHandling.Ignore; @@ -37,10 +38,18 @@ namespace PinkParrot.Configurations return ConfigureJson(new JsonSerializerSettings()); } + private static JsonSerializer CreateSerializer(JsonSerializerSettings settings) + { + return JsonSerializer.Create(settings); + } + public static void AddEventFormatter(this IServiceCollection services) { + TypeNameRegistry.Map(typeof(ModelSchema).GetTypeInfo().Assembly); + TypeNameRegistry.Map(typeof(ModelSchemaCreated).GetTypeInfo().Assembly); + services.AddSingleton(t => CreateSettings()); - services.AddSingleton(); + services.AddSingleton(t => CreateSerializer(t.GetRequiredService())); services.AddSingleton(); } diff --git a/src/PinkParrot/Modules/Api/Schemas/CreateFieldDto.cs b/src/PinkParrot/Modules/Api/Schemas/CreateFieldDto.cs new file mode 100644 index 000000000..179df5a93 --- /dev/null +++ b/src/PinkParrot/Modules/Api/Schemas/CreateFieldDto.cs @@ -0,0 +1,25 @@ +// ========================================================================== +// CreateFieldDto.cs +// PinkParrot Headless CMS +// ========================================================================== +// Copyright (c) PinkParrot Group +// All rights reserved. +// ========================================================================== + +using System.ComponentModel.DataAnnotations; +using Newtonsoft.Json.Linq; + +namespace PinkParrot.Modules.Api.Schemas +{ + public class CreateFieldDto + { + [Required] + public string Name { get; set; } + + [Required] + public string Type { get; set; } + + [Required] + public JToken Properties { get; set; } + } +} diff --git a/src/PinkParrot/Modules/Api/Schemas/CreateSchemaDto.cs b/src/PinkParrot/Modules/Api/Schemas/CreateSchemaDto.cs new file mode 100644 index 000000000..5a4f1a4a0 --- /dev/null +++ b/src/PinkParrot/Modules/Api/Schemas/CreateSchemaDto.cs @@ -0,0 +1,22 @@ +// ========================================================================== +// CreateFieldDto.cs +// PinkParrot Headless CMS +// ========================================================================== +// Copyright (c) PinkParrot Group +// All rights reserved. +// ========================================================================== + +using System.ComponentModel.DataAnnotations; +using PinkParrot.Core.Schema; + +namespace PinkParrot.Modules.Api.Schemas +{ + public class CreateSchemaDto + { + [Required] + public string Name { get; set; } + + [Required] + public ModelFieldProperties Properties { get; set; } + } +} diff --git a/src/PinkParrot/Modules/Api/Schemas/SchemasDto.cs b/src/PinkParrot/Modules/Api/Schemas/ListSchemaDto.cs similarity index 95% rename from src/PinkParrot/Modules/Api/Schemas/SchemasDto.cs rename to src/PinkParrot/Modules/Api/Schemas/ListSchemaDto.cs index 7ae7475a8..1495ba5c8 100644 --- a/src/PinkParrot/Modules/Api/Schemas/SchemasDto.cs +++ b/src/PinkParrot/Modules/Api/Schemas/ListSchemaDto.cs @@ -11,7 +11,7 @@ using System.ComponentModel.DataAnnotations; namespace PinkParrot.Modules.Api.Schemas { - public class SchemasDto + public class ListSchemaDto { [Required] public Guid Id { get; set; } diff --git a/src/PinkParrot/Modules/Api/Schemas/SchemaFieldsController.cs b/src/PinkParrot/Modules/Api/Schemas/SchemaFieldsController.cs index a6026e2be..a9f4729f7 100644 --- a/src/PinkParrot/Modules/Api/Schemas/SchemaFieldsController.cs +++ b/src/PinkParrot/Modules/Api/Schemas/SchemaFieldsController.cs @@ -8,8 +8,8 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; -using PinkParrot.Core.Schema; using PinkParrot.Infrastructure.CQRS.Commands; +using PinkParrot.Infrastructure.Reflection; using PinkParrot.Write.Schema.Commands; namespace PinkParrot.Modules.Api.Schemas @@ -23,18 +23,18 @@ namespace PinkParrot.Modules.Api.Schemas [HttpPost] [Route("api/schemas/{name}/fields/")] - public Task Add(string name, [FromBody] ModelFieldProperties field) + public Task Add(string name, [FromBody] CreateFieldDto model) { - var command = new AddModelField { Properties = field }; + var command = SimpleMapper.Map(model, new AddModelField()); return CommandBus.PublishAsync(command); } [HttpPut] [Route("api/schemas/{name}/fields/{fieldId:long}/")] - public Task Update(string name, long fieldId, [FromBody] ModelFieldProperties properties) + public Task Update(string name, long fieldId, [FromBody] UpdateFieldDto model) { - var command = new UpdateModelField { FieldId = fieldId, Properties = properties }; + var command = new UpdateModelField { FieldId = fieldId, Properties = model.Properties }; return CommandBus.PublishAsync(command); } diff --git a/src/PinkParrot/Modules/Api/Schemas/SchemasController.cs b/src/PinkParrot/Modules/Api/Schemas/SchemasController.cs index 953a6692c..e7814bab2 100644 --- a/src/PinkParrot/Modules/Api/Schemas/SchemasController.cs +++ b/src/PinkParrot/Modules/Api/Schemas/SchemasController.cs @@ -12,9 +12,9 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using PinkParrot.Core.Schema; -using PinkParrot.Core.Schema.Json; using PinkParrot.Infrastructure.CQRS.Commands; using PinkParrot.Infrastructure.Reflection; +using PinkParrot.Read.Models; using PinkParrot.Read.Repositories; using PinkParrot.Write.Schema.Commands; @@ -32,11 +32,11 @@ namespace PinkParrot.Modules.Api.Schemas [HttpGet] [Route("api/schemas/")] - public async Task> Query() + public async Task> Query() { var schemas = await modelSchemaRepository.QueryAllAsync(TenantId); - return schemas.Select(s => SimpleMapper.Map(s, new SchemasDto())).ToList(); + return schemas.Select(s => SimpleMapper.Map(s, new ListSchemaDto())).ToList(); } [HttpGet] @@ -55,9 +55,9 @@ namespace PinkParrot.Modules.Api.Schemas [HttpPost] [Route("api/schemas/")] - public async Task Create([FromBody] ModelSchemaProperties schema) + public async Task Create([FromBody] CreateSchemaDto model) { - var command = new CreateModelSchema { AggregateId = Guid.NewGuid(), Properties = schema }; + var command = SimpleMapper.Map(model, new CreateModelSchema { AggregateId = Guid.NewGuid() }); await CommandBus.PublishAsync(command); diff --git a/src/PinkParrot/Modules/Api/Schemas/UpdateFieldDto.cs b/src/PinkParrot/Modules/Api/Schemas/UpdateFieldDto.cs new file mode 100644 index 000000000..d558c0e95 --- /dev/null +++ b/src/PinkParrot/Modules/Api/Schemas/UpdateFieldDto.cs @@ -0,0 +1,19 @@ +// ========================================================================== +// UpdateFieldDto.cs +// PinkParrot Headless CMS +// ========================================================================== +// Copyright (c) PinkParrot Group +// All rights reserved. +// ========================================================================== + +using System.ComponentModel.DataAnnotations; +using Newtonsoft.Json.Linq; + +namespace PinkParrot.Modules.Api.Schemas +{ + public class UpdateFieldDto + { + [Required] + public JToken Properties { get; set; } + } +} diff --git a/src/pinkparrot_core/PinkParrot.Core/Schema/ModelSchema.cs b/src/pinkparrot_core/PinkParrot.Core/Schema/ModelSchema.cs index 88949d608..0679b3022 100644 --- a/src/pinkparrot_core/PinkParrot.Core/Schema/ModelSchema.cs +++ b/src/pinkparrot_core/PinkParrot.Core/Schema/ModelSchema.cs @@ -54,13 +54,13 @@ namespace PinkParrot.Core.Schema public static ModelSchema Create(string name, ModelSchemaProperties newProperties) { - Guard.NotNull(newProperties, nameof(newProperties)); + newProperties = newProperties ?? new ModelSchemaProperties(null, null); if (!name.IsSlug()) { var error = new ValidationError("Name must be a valid slug", "Name"); - throw new ValidationException($"Cannot rename the schema '{name}'", error); + throw new ValidationException($"Cannot create a new schema", error); } return new ModelSchema(name, newProperties, ImmutableDictionary.Empty); diff --git a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldAdded.cs b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldAdded.cs index eb17dd1b9..7709bb3ba 100644 --- a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldAdded.cs +++ b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldAdded.cs @@ -14,10 +14,10 @@ namespace PinkParrot.Events.Schema [TypeName("ModelFieldAddedEvent")] public class ModelFieldAdded : TenantEvent { - public long FieldId; + public long FieldId { get; set; } - public string Name; + public string Name { get; set; } - public IModelFieldProperties Properties; + public IModelFieldProperties Properties { get; set; } } } diff --git a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldDeleted.cs b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldDeleted.cs index 1d0ece1b4..59da03c86 100644 --- a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldDeleted.cs +++ b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldDeleted.cs @@ -13,6 +13,6 @@ namespace PinkParrot.Events.Schema [TypeName("ModelFieldDeletedEvent")] public class ModelFieldDeleted : TenantEvent { - public long FieldId; + public long FieldId { get; set; } } } diff --git a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldDisabled.cs b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldDisabled.cs index 039c407da..090829e7e 100644 --- a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldDisabled.cs +++ b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldDisabled.cs @@ -13,6 +13,6 @@ namespace PinkParrot.Events.Schema [TypeName("ModelFieldDisabledEvent")] public class ModelFieldDisabled : TenantEvent { - public long FieldId; + public long FieldId { get; set; } } } diff --git a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldEnabled.cs b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldEnabled.cs index 41429afd1..36d8a96fe 100644 --- a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldEnabled.cs +++ b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldEnabled.cs @@ -13,6 +13,6 @@ namespace PinkParrot.Events.Schema [TypeName("ModelFieldEnabledEvent")] public class ModelFieldEnabled : TenantEvent { - public long FieldId; + public long FieldId { get; set; } } } diff --git a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldHidden.cs b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldHidden.cs index eebe99787..2e4a558d2 100644 --- a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldHidden.cs +++ b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldHidden.cs @@ -13,6 +13,6 @@ namespace PinkParrot.Events.Schema [TypeName("ModelFieldHiddenEvent")] public class ModelFieldHidden : TenantEvent { - public long FieldId; + public long FieldId { get; set; } } } diff --git a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldShown.cs b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldShown.cs index b3c6f5008..fba7d467a 100644 --- a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldShown.cs +++ b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldShown.cs @@ -13,6 +13,6 @@ namespace PinkParrot.Events.Schema [TypeName("ModelFieldShownEvent")] public class ModelFieldShown : TenantEvent { - public long FieldId; + public long FieldId { get; set; } } } diff --git a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldUpdated.cs b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldUpdated.cs index 8615fd9e9..518293ce0 100644 --- a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldUpdated.cs +++ b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldUpdated.cs @@ -14,8 +14,8 @@ namespace PinkParrot.Events.Schema [TypeName("ModelFieldUpdatedEvent")] public class ModelFieldUpdated : TenantEvent { - public long FieldId; + public long FieldId { get; set; } - public IModelFieldProperties Properties; + public IModelFieldProperties Properties { get; set; } } } diff --git a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaCreated.cs b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaCreated.cs index 784bf372a..88b1c329f 100644 --- a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaCreated.cs +++ b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaCreated.cs @@ -14,8 +14,8 @@ namespace PinkParrot.Events.Schema [TypeName("ModelSchemaCreatedEvent")] public class ModelSchemaCreated : TenantEvent { - public string Name; + public string Name { get; set; } - public ModelSchemaProperties Properties; + public ModelSchemaProperties Properties { get; set; } } } diff --git a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaUpdated.cs b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaUpdated.cs index 6d081f6d0..b82717fbc 100644 --- a/src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaUpdated.cs +++ b/src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaUpdated.cs @@ -14,6 +14,6 @@ namespace PinkParrot.Events.Schema [TypeName("ModelSchemaUpdated")] public class ModelSchemaUpdated : TenantEvent { - public ModelSchemaProperties Properties; + public ModelSchemaProperties Properties { get; set; } } } diff --git a/src/pinkparrot_events/PinkParrot.Events/TenantEvent.cs b/src/pinkparrot_events/PinkParrot.Events/TenantEvent.cs index 60a1fef05..4debe0f8f 100644 --- a/src/pinkparrot_events/PinkParrot.Events/TenantEvent.cs +++ b/src/pinkparrot_events/PinkParrot.Events/TenantEvent.cs @@ -13,6 +13,6 @@ namespace PinkParrot.Events { public class TenantEvent : IEvent { - public Guid TenantId; + public Guid TenantId { get; set; } } } diff --git a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Commands/CommandContext.cs b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Commands/CommandContext.cs index 7c8a19b75..94be9adec 100644 --- a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Commands/CommandContext.cs +++ b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Commands/CommandContext.cs @@ -12,22 +12,10 @@ namespace PinkParrot.Infrastructure.CQRS.Commands { public sealed class CommandContext { - private readonly IDomainObjectFactory factory; - private readonly IDomainObjectRepository repository; private readonly ICommand command; private Exception exception; private bool isSucceeded; - public IDomainObjectRepository Repository - { - get { return repository; } - } - - public IDomainObjectFactory Factory - { - get { return factory; } - } - public ICommand Command { get { return command; } @@ -48,15 +36,11 @@ namespace PinkParrot.Infrastructure.CQRS.Commands get { return exception; } } - public CommandContext(IDomainObjectFactory factory, IDomainObjectRepository repository, ICommand command) + public CommandContext(ICommand command) { Guard.NotNull(command, nameof(command)); - Guard.NotNull(factory, nameof(factory)); - Guard.NotNull(repository, nameof(repository)); this.command = command; - this.factory = factory; - this.repository = repository; } public void MarkSucceeded() diff --git a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Commands/CommandHandler.cs b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Commands/CommandHandler.cs new file mode 100644 index 000000000..d3f2db45b --- /dev/null +++ b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Commands/CommandHandler.cs @@ -0,0 +1,88 @@ +// ========================================================================== +// CommandHandler.cs +// PinkParrot Headless CMS +// ========================================================================== +// Copyright (c) PinkParrot Group +// All rights reserved. +// ========================================================================== + +using System; +using System.Threading.Tasks; + +namespace PinkParrot.Infrastructure.CQRS.Commands +{ + public abstract class CommandHandler : ICommandHandler where T : class, IAggregate + { + private readonly IDomainObjectRepository domainObjectRepository; + private readonly IDomainObjectFactory domainObjectFactory; + + protected IDomainObjectRepository Repository + { + get { return domainObjectRepository; } + } + + protected IDomainObjectFactory Factory + { + get { return domainObjectFactory; } + } + + protected CommandHandler(IDomainObjectFactory domainObjectFactory, IDomainObjectRepository domainObjectRepository) + { + Guard.NotNull(domainObjectFactory, nameof(domainObjectFactory)); + Guard.NotNull(domainObjectRepository, nameof(domainObjectRepository)); + + this.domainObjectFactory = domainObjectFactory; + this.domainObjectRepository = domainObjectRepository; + } + + protected async Task CreateAsync(IAggregateCommand command, Func creator) + { + Guard.NotNull(creator, nameof(creator)); + Guard.NotNull(command, nameof(command)); + + var domainObject = domainObjectFactory.CreateNew(command.AggregateId); + + await creator(domainObject); + + await domainObjectRepository.SaveAsync(domainObject, command.AggregateId); + } + + protected Task CreateAsync(IAggregateCommand command, Action creator) + { + Guard.NotNull(creator, nameof(creator)); + Guard.NotNull(command, nameof(command)); + + var domainObject = domainObjectFactory.CreateNew(command.AggregateId); + + creator(domainObject); + + return domainObjectRepository.SaveAsync(domainObject, command.AggregateId); + } + + protected async Task UpdateAsync(IAggregateCommand command, Func updater) + { + Guard.NotNull(updater, nameof(updater)); + Guard.NotNull(command, nameof(command)); + + var domainObject = await domainObjectRepository.GetByIdAsync(command.AggregateId); + + await updater(domainObject); + + await domainObjectRepository.SaveAsync(domainObject, Guid.NewGuid()); + } + + protected async Task UpdateAsync(IAggregateCommand command, Action updater) + { + Guard.NotNull(updater, nameof(updater)); + Guard.NotNull(command, nameof(command)); + + var domainObject = await domainObjectRepository.GetByIdAsync(command.AggregateId); + + updater(domainObject); + + await domainObjectRepository.SaveAsync(domainObject, Guid.NewGuid()); + } + + public abstract Task HandleAsync(CommandContext context); + } +} diff --git a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Commands/CommandingExtensions.cs b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Commands/CommandingExtensions.cs index c6d4f5f02..735ad42a8 100644 --- a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Commands/CommandingExtensions.cs +++ b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Commands/CommandingExtensions.cs @@ -12,7 +12,7 @@ namespace PinkParrot.Infrastructure.CQRS.Commands { public static class CommandingExtensions { - public static T CreateNew(this IDomainObjectFactory factory, Guid id) where T : DomainObject + public static T CreateNew(this IDomainObjectFactory factory, Guid id) where T : IAggregate { return (T)factory.CreateNew(typeof(T), id); } diff --git a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Commands/InMemoryCommandBus.cs b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Commands/InMemoryCommandBus.cs index c2007365f..fb66a2690 100644 --- a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Commands/InMemoryCommandBus.cs +++ b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Commands/InMemoryCommandBus.cs @@ -14,29 +14,20 @@ namespace PinkParrot.Infrastructure.CQRS.Commands { public sealed class InMemoryCommandBus : ICommandBus { - private readonly IDomainObjectFactory factory; - private readonly IDomainObjectRepository repository; private readonly IEnumerable handlers; - public InMemoryCommandBus( - IDomainObjectRepository repository, - IDomainObjectFactory factory, - IEnumerable handlers) + public InMemoryCommandBus(IEnumerable handlers) { - Guard.NotNull(factory, nameof(factory)); Guard.NotNull(handlers, nameof(handlers)); - Guard.NotNull(repository, nameof(repository)); - - this.factory = factory; + this.handlers = handlers; - this.repository = repository; } public async Task PublishAsync(ICommand command) { Guard.NotNull(command, nameof(command)); - var context = new CommandContext(factory, repository, command); + var context = new CommandContext(command); foreach (var handler in handlers) { diff --git a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/DomainObject.cs b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/DomainObject.cs index 7f1421cc9..51777f4ef 100644 --- a/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/DomainObject.cs +++ b/src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/DomainObject.cs @@ -40,7 +40,7 @@ namespace PinkParrot.Infrastructure.CQRS protected abstract void ApplyEvent(Envelope @event); - protected void RaiseEvent(Envelope envelope, bool disableApply = false) where TEvent : class, IEvent + protected void RaiseEvent(Envelope envelope) where TEvent : class, IEvent { Guard.NotNull(envelope, nameof(envelope)); @@ -48,19 +48,12 @@ namespace PinkParrot.Infrastructure.CQRS uncomittedEvents.Add(envelopeToAdd); - if (!disableApply) - { - ApplyEvent(envelopeToAdd); - } - else - { - version++; - } + ApplyEvent(envelopeToAdd); } - protected void RaiseEvent(IEvent @event, bool disableApply = false) + protected void RaiseEvent(IEvent @event) { - RaiseEvent(EnvelopeFactory.ForEvent(@event, this), disableApply); + RaiseEvent(EnvelopeFactory.ForEvent(@event, this)); } void IAggregate.ApplyEvent(Envelope @event) diff --git a/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/AddModelField.cs b/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/AddModelField.cs index 41d2be3e7..b62a66ca4 100644 --- a/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/AddModelField.cs +++ b/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/AddModelField.cs @@ -12,10 +12,10 @@ namespace PinkParrot.Write.Schema.Commands { public class AddModelField : TenantCommand { - public string Name; + public string Name { get; set; } - public string Type; + public string Type { get; set; } - public JToken Properties; + public JToken Properties { get; set; } } } \ No newline at end of file diff --git a/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/DeleteModelField.cs b/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/DeleteModelField.cs index 5a9d0b0d2..f8ec9ad64 100644 --- a/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/DeleteModelField.cs +++ b/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/DeleteModelField.cs @@ -10,6 +10,6 @@ namespace PinkParrot.Write.Schema.Commands { public class DeleteModelField : TenantCommand { - public long FieldId; + public long FieldId { get; set; } } } \ No newline at end of file diff --git a/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/DisableModelField.cs b/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/DisableModelField.cs index 08a4aef63..d931649a9 100644 --- a/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/DisableModelField.cs +++ b/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/DisableModelField.cs @@ -10,6 +10,6 @@ namespace PinkParrot.Write.Schema.Commands { public class DisableModelField : TenantCommand { - public long FieldId; + public long FieldId { get; set; } } } diff --git a/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/EnableModelField.cs b/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/EnableModelField.cs index 5554f8f9d..feeba187e 100644 --- a/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/EnableModelField.cs +++ b/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/EnableModelField.cs @@ -10,6 +10,6 @@ namespace PinkParrot.Write.Schema.Commands { public class EnableModelField : TenantCommand { - public long FieldId; + public long FieldId { get; set; } } } diff --git a/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/HideModelField.cs b/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/HideModelField.cs index 929d1d7bb..a8b24e445 100644 --- a/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/HideModelField.cs +++ b/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/HideModelField.cs @@ -10,6 +10,6 @@ namespace PinkParrot.Write.Schema.Commands { public class HideModelField : TenantCommand { - public long FieldId; + public long FieldId { get; set; } } } diff --git a/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/ShowModelField.cs b/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/ShowModelField.cs index d9754a999..8668851a2 100644 --- a/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/ShowModelField.cs +++ b/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/ShowModelField.cs @@ -10,6 +10,6 @@ namespace PinkParrot.Write.Schema.Commands { public class ShowModelField : TenantCommand { - public long FieldId; + public long FieldId { get; set; } } } diff --git a/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/UpdateModelField.cs b/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/UpdateModelField.cs index 4c08fa47b..a1f88bdd3 100644 --- a/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/UpdateModelField.cs +++ b/src/pinkparrot_write/PinkParrot.Write/Schema/Commands/UpdateModelField.cs @@ -12,7 +12,7 @@ namespace PinkParrot.Write.Schema.Commands { public class UpdateModelField : TenantCommand { - public long FieldId; + public long FieldId { get; set; } public JToken Properties { get; set; } } diff --git a/src/pinkparrot_write/PinkParrot.Write/Schema/ModelSchemaCommandHandler.cs b/src/pinkparrot_write/PinkParrot.Write/Schema/ModelSchemaCommandHandler.cs index d47225b41..be9a3a751 100644 --- a/src/pinkparrot_write/PinkParrot.Write/Schema/ModelSchemaCommandHandler.cs +++ b/src/pinkparrot_write/PinkParrot.Write/Schema/ModelSchemaCommandHandler.cs @@ -9,6 +9,7 @@ using System; using System.Threading.Tasks; using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using PinkParrot.Core.Schema; using PinkParrot.Infrastructure; using PinkParrot.Infrastructure.CQRS.Commands; @@ -17,77 +18,79 @@ using PinkParrot.Write.Schema.Commands; namespace PinkParrot.Write.Schema { - public class ModelSchemaCommandHandler : ICommandHandler + public class ModelSchemaCommandHandler : CommandHandler { private readonly ModelFieldRegistry registry; private readonly JsonSerializer serializer; - public ModelSchemaCommandHandler(ModelFieldRegistry registry, JsonSerializer serializer) + public ModelSchemaCommandHandler( + ModelFieldRegistry registry, + IDomainObjectFactory domainObjectFactory, + IDomainObjectRepository domainObjectRepository, + JsonSerializer serializer) + : base(domainObjectFactory, domainObjectRepository) { this.registry = registry; + this.serializer = serializer; } - public Task HandleAsync(CommandContext context) + public override Task HandleAsync(CommandContext context) { - return context.IsHandled ? Task.FromResult(false) : this.DispatchActionAsync(context.Command, context); + return context.IsHandled ? Task.FromResult(false) : this.DispatchActionAsync(context.Command); } - public Task On(CreateModelSchema command, CommandContext context) + public Task On(CreateModelSchema command) { - var schema = context.Factory.CreateNew(command.AggregateId); - - schema.Create(command.TenantId, command.Name, command.Properties); - - return context.Repository.SaveAsync(schema, command.AggregateId); + return CreateAsync(command, s => s.Create(command.TenantId, command.Name, command.Properties)); } - public Task On(DeleteModelSchema command, CommandContext context) + public Task On(DeleteModelSchema command) { - return UpdateAsync(command, context, s => s.Delete()); + return UpdateAsync(command, s => s.Delete()); } - public Task On(DeleteModelField command, CommandContext context) + public Task On(DeleteModelField command) { - return UpdateAsync(command, context, s => s.DeleteField(command.FieldId)); + return UpdateAsync(command, s => s.DeleteField(command.FieldId)); } - public Task On(DisableModelField command, CommandContext context) + public Task On(DisableModelField command) { - return UpdateAsync(command, context, s => s.DisableField(command.FieldId)); + return UpdateAsync(command, s => s.DisableField(command.FieldId)); } - public Task On(EnableModelField command, CommandContext context) + public Task On(EnableModelField command) { - return UpdateAsync(command, context, s => s.EnableField(command.FieldId)); + return UpdateAsync(command, s => s.EnableField(command.FieldId)); } - public Task On(HideModelField command, CommandContext context) + public Task On(HideModelField command) { - return UpdateAsync(command, context, s => s.HideField(command.FieldId)); + return UpdateAsync(command, s => s.HideField(command.FieldId)); } - public Task On(ShowModelField command, CommandContext context) + public Task On(ShowModelField command) { - return UpdateAsync(command, context, s => s.ShowField(command.FieldId)); + return UpdateAsync(command, s => s.ShowField(command.FieldId)); } - public Task On(UpdateModelSchema command, CommandContext context) + public Task On(UpdateModelSchema command) { - return UpdateAsync(command, context, s => s.Update(command.Properties)); + return UpdateAsync(command, s => s.Update(command.Properties)); } - public Task On(AddModelField command, CommandContext context) + public Task On(AddModelField command) { var propertiesType = registry.FindByTypeName(command.Type).PropertiesType; - var propertiesValue = (IModelFieldProperties)command.Properties.ToObject(propertiesType, serializer); + var propertiesValue = CreateProperties(command.Properties, propertiesType); - return UpdateAsync(command, context, s => s.AddField(command.Name, propertiesValue)); + return UpdateAsync(command, s => s.AddField(command.Name, propertiesValue)); } - public Task On(UpdateModelField command, CommandContext context) + public Task On(UpdateModelField command) { - return UpdateAsync(command, context, s => + return UpdateAsync(command, s => { var field = s.Schema.Fields.GetOrDefault(command.FieldId); @@ -97,19 +100,15 @@ namespace PinkParrot.Write.Schema } var propertiesType = registry.FindByPropertiesType(field.RawProperties.GetType()).PropertiesType; - var propertiesValue = (IModelFieldProperties)command.Properties.ToObject(propertiesType, serializer); + var propertiesValue = CreateProperties(command.Properties, propertiesType); s.UpdateField(command.FieldId, propertiesValue); }); } - private static async Task UpdateAsync(IAggregateCommand command, CommandContext context, Action updater) + private IModelFieldProperties CreateProperties(JToken token, Type type) { - var schema = await context.Repository.GetByIdAsync(command.AggregateId); - - updater(schema); - - await context.Repository.SaveAsync(schema, Guid.NewGuid()); + return (IModelFieldProperties)token.ToObject(type, serializer); } } } diff --git a/src/pinkparrot_write/PinkParrot.Write/Schema/ModelSchemaDomainObject.cs b/src/pinkparrot_write/PinkParrot.Write/Schema/ModelSchemaDomainObject.cs index 7297c3365..6c5c9be6a 100644 --- a/src/pinkparrot_write/PinkParrot.Write/Schema/ModelSchemaDomainObject.cs +++ b/src/pinkparrot_write/PinkParrot.Write/Schema/ModelSchemaDomainObject.cs @@ -104,95 +104,71 @@ namespace PinkParrot.Write.Schema public void AddField(string name, IModelFieldProperties properties) { VerifyCreatedAndNotDeleted(); - - var id = ++totalFields; - - schema = schema.AddOrUpdateField(registry.CreateField(id, name, properties)); - - RaiseEvent(new ModelFieldAdded { FieldId = id, Properties = properties }, true); + + RaiseEvent(new ModelFieldAdded { FieldId = ++totalFields, Name = name, Properties = properties }); } public void Create(Guid newTenantId, string name, ModelSchemaProperties properties) { VerifyNotCreated(); - - tenantId = newTenantId; - - schema = ModelSchema.Create(name, properties); - - RaiseEvent(new ModelSchemaCreated { Properties = properties }, true); + + RaiseEvent(new ModelSchemaCreated { TenantId = newTenantId, Name = name, Properties = properties }); } public void Update(ModelSchemaProperties properties) { VerifyCreatedAndNotDeleted(); - - schema = schema.Update(properties); - - RaiseEvent(new ModelSchemaUpdated { Properties = properties }, true); + + RaiseEvent(new ModelSchemaUpdated { Properties = properties }); } public void UpdateField(long fieldId, IModelFieldProperties properties) { VerifyCreatedAndNotDeleted(); - schema = schema.UpdateField(fieldId, properties); - - RaiseEvent(new ModelFieldUpdated { FieldId = fieldId, Properties = properties }, true); + RaiseEvent(new ModelFieldUpdated { FieldId = fieldId, Properties = properties }); } public void HideField(long fieldId) { VerifyCreatedAndNotDeleted(); - - schema = schema.HideField(fieldId); - - RaiseEvent(new ModelFieldHidden { FieldId = fieldId }, true); + + RaiseEvent(new ModelFieldHidden { FieldId = fieldId }); } public void ShowField(long fieldId) { VerifyCreatedAndNotDeleted(); - - schema = schema.ShowField(fieldId); - - RaiseEvent(new ModelFieldShown { FieldId = fieldId }, true); + + RaiseEvent(new ModelFieldShown { FieldId = fieldId }); } public void DisableField(long fieldId) { VerifyCreatedAndNotDeleted(); - schema = schema.DisableField(fieldId); - - RaiseEvent(new ModelFieldDisabled { FieldId = fieldId }, true); + RaiseEvent(new ModelFieldDisabled { FieldId = fieldId }); } public void EnableField(long fieldId) { VerifyCreatedAndNotDeleted(); - - schema = schema.EnableField(fieldId); - - RaiseEvent(new ModelFieldEnabled { FieldId = fieldId }, true); + + RaiseEvent(new ModelFieldEnabled { FieldId = fieldId }); } public void DeleteField(long fieldId) { VerifyCreatedAndNotDeleted(); - - schema = schema.DeleteField(fieldId); - - RaiseEvent(new ModelFieldDeleted { FieldId = fieldId }, true); + + RaiseEvent(new ModelFieldDeleted { FieldId = fieldId }); } public void Delete() { VerifyCreatedAndNotDeleted(); - - isDeleted = true; - - RaiseEvent(new ModelSchemaDeleted(), true); + + RaiseEvent(new ModelSchemaDeleted()); } private void VerifyNotCreated()