Browse Source

Some progress

pull/1/head
Sebastian Stehle 9 years ago
parent
commit
8405695374
  1. 9
      PinkParrot.sln
  2. 74
      src/PinkParrot/Modules/Api/Schemas/SchemaFieldsController.cs
  3. 37
      src/PinkParrot/Modules/Api/Schemas/SchemasController.cs
  4. 42
      src/PinkParrot/Startup.cs
  5. 8
      src/PinkParrot/project.json
  6. 5
      src/PinkParrot/web.config
  7. 8
      src/pinkparrot_core/PinkParrot.Core/Schema/ModelField.cs
  8. 12
      src/pinkparrot_core/PinkParrot.Core/Schema/ModelSchema.cs
  9. 2
      src/pinkparrot_core/PinkParrot.Core/Schema/ModelSchemaMetadata.cs
  10. 4
      src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldAdded.cs
  11. 4
      src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldDeleted.cs
  12. 4
      src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldDisabled.cs
  13. 4
      src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldEnabled.cs
  14. 4
      src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldHidden.cs
  15. 4
      src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldShown.cs
  16. 3
      src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldUpdated.cs
  17. 4
      src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaCreated.cs
  18. 4
      src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaDeleted.cs
  19. 3
      src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaUpdated.cs
  20. 18
      src/pinkparrot_events/PinkParrot.Events/TenantEvent.cs
  21. 3
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure.Tests/DispatchingTests.cs
  22. 8
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure.Tests/PropertiesBagTests.cs
  23. 33
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Autofac/AutofacDomainObjectFactory.cs
  24. 16
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/DomainObject.cs
  25. 20
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/EnvelopeExtensions.cs
  26. 11
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/GetEventStore/GetEventStoreDomainObjectRepository.cs
  27. 2
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/IAggregate.cs
  28. 1
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/ActionContextDispatcherFactory.cs
  29. 1
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/ActionDispatcherFactory.cs
  30. 1
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/FuncContextDispatcherFactory.cs
  31. 1
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/FuncDispatcherFactory.cs
  32. 15
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure/ICommandContext.cs
  33. 12
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure/ValidationException.cs
  34. 7
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure/project.json
  35. 16
      src/pinkparrot_read/PinkParrot.Read/Models/ModelSchemaRM.cs
  36. 19
      src/pinkparrot_read/PinkParrot.Read/PinkParrot.Read.xproj
  37. 19
      src/pinkparrot_read/PinkParrot.Read/Repositories/IModelSchemaRepository.cs
  38. 42
      src/pinkparrot_read/PinkParrot.Read/Repositories/MongoDb/MongoDbModelSchemaRepository.cs
  39. 33
      src/pinkparrot_read/PinkParrot.Read/Repositories/MongoDb/Utils/BaseRepository.cs
  40. 27
      src/pinkparrot_read/PinkParrot.Read/project.json
  41. 18
      src/pinkparrot_write/PinkParrot.Write/Schema/ISchemaIdProvider.cs
  42. 4
      src/pinkparrot_write/PinkParrot.Write/Schema/ModelSchemaDomainObject.cs
  43. 70
      src/pinkparrot_write/PinkParrot.Write/Schema/ModelSchemaNameMap.cs

9
PinkParrot.sln

@ -32,6 +32,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "pinkparrot_write", "pinkpar
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "PinkParrot.Write", "src\pinkparrot_write\PinkParrot.Write\PinkParrot.Write.xproj", "{A85201C6-6AF8-4B63-8365-08F741050438}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "PinkParrot.Read", "src\pinkparrot_read\PinkParrot.Read\PinkParrot.Read.xproj", "{A92B4734-2587-4F6F-97A3-741BE48709A5}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "pinkparrot_read", "pinkparrot_read", "{2CDAF493-B88E-48BD-9634-B5128C106199}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -66,6 +70,10 @@ Global
{A85201C6-6AF8-4B63-8365-08F741050438}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A85201C6-6AF8-4B63-8365-08F741050438}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A85201C6-6AF8-4B63-8365-08F741050438}.Release|Any CPU.Build.0 = Release|Any CPU
{A92B4734-2587-4F6F-97A3-741BE48709A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A92B4734-2587-4F6F-97A3-741BE48709A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A92B4734-2587-4F6F-97A3-741BE48709A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A92B4734-2587-4F6F-97A3-741BE48709A5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -78,5 +86,6 @@ Global
{BD1C30A8-8FFA-4A92-A9BD-B67B1CDDD84C} = {8CF53B92-5EB1-461D-98F8-70DA9B603FBF}
{25F66C64-058A-4D44-BC0C-F12A054F9A91} = {6AE39761-FD74-45CD-99CF-73D3D2E5D064}
{A85201C6-6AF8-4B63-8365-08F741050438} = {4AED438F-684F-4FAE-B016-21CF2EAEA79F}
{A92B4734-2587-4F6F-97A3-741BE48709A5} = {2CDAF493-B88E-48BD-9634-B5128C106199}
EndGlobalSection
EndGlobal

74
src/PinkParrot/Modules/Api/Schemas/SchemaFieldsController.cs

@ -0,0 +1,74 @@
// ==========================================================================
// SchemaFieldsController.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using PinkParrot.Infrastructure.CQRS.Commands;
using PinkParrot.Write.Schema.Commands;
namespace PinkParrot.Modules.Api.Schemas
{
public class SchemasFieldsController : Controller
{
private readonly ICommandBus commandBus;
public SchemasFieldsController(ICommandBus commandBus)
{
this.commandBus = commandBus;
}
[HttpPost]
[Route("schemas/{name}/fields/")]
public Task Add(AddModelField command)
{
return commandBus.PublishAsync(command);
}
[HttpPut]
[Route("schemas/{name}/fields/{fieldId:long}/")]
public Task Update(UpdateModelField command)
{
return commandBus.PublishAsync(command);
}
[HttpPut]
[Route("schemas/{name}/fields/{fieldId:long}/hide/")]
public Task Hide(HideModelField command)
{
return commandBus.PublishAsync(command);
}
[HttpPut]
[Route("schemas/{name}/fields/{fieldId:long}/show/")]
public Task Show(ShowModelField command)
{
return commandBus.PublishAsync(command);
}
[HttpPut]
[Route("schemas/{name}/fields/{fieldId:long}/enable/")]
public Task Enable(EnableModelField command)
{
return commandBus.PublishAsync(command);
}
[HttpPut]
[Route("schemas/{name}/fields/{fieldId:long}/disable/")]
public Task Enable(DisableModelField command)
{
return commandBus.PublishAsync(command);
}
[HttpDelete]
[Route("schemas/{name}/fields/{fieldId:long}/")]
public Task Delete(DeleteModelField command)
{
return commandBus.PublishAsync(command);
}
}
}

37
src/PinkParrot/Modules/Api/Schemas/SchemasController.cs

@ -1,26 +1,55 @@
using System.Threading.Tasks;
// ==========================================================================
// SchemasController.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using PinkParrot.Infrastructure.CQRS.Commands;
using PinkParrot.Read.Models;
using PinkParrot.Write.Schema.Commands;
namespace PinkParrot.Modules.Api.Schemas
{
public class SchemasController : Controller
{
private readonly ICommandBus commandBus;
public SchemasController(ICommandBus commandBus)
{
this.commandBus = commandBus;
}
[HttpGet]
[Route("schemas/")]
public Task<List<ModelSchemaRM>> Query()
{
return null;
}
[HttpPost]
[Route("schemas/")]
public async Task Create()
public Task Create(CreateModelSchema command)
{
return commandBus.PublishAsync(command);
}
[HttpPut]
[Route("schemas/{name}/")]
public async Task Update()
public Task Update(UpdateModelSchema command)
{
return commandBus.PublishAsync(command);
}
[HttpDelete]
[Route("schemas/{name}/")]
public async Task Delete()
public Task Delete()
{
return commandBus.PublishAsync(new DeleteModelSchema());
}
}
}

42
src/PinkParrot/Startup.cs

@ -6,27 +6,59 @@
// All rights reserved.
// ==========================================================================
using System;
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using PinkParrot.Infrastructure.CQRS.Autofac;
using PinkParrot.Infrastructure.CQRS.Commands;
// ReSharper disable AccessToModifiedClosure
namespace PinkParrot
{
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
public IServiceProvider ConfigureServices(IServiceCollection services)
{
}
services.AddMvc();
services.AddRouting();
services.AddSwaggerGen();
IContainer container = null;
var containerBuilder = new ContainerBuilder();
containerBuilder.Populate(services);
containerBuilder.Register(c => container)
.As<IContainer>()
.SingleInstance();
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
containerBuilder.RegisterType<AutofacDomainObjectFactory>()
.As<IDomainObjectFactory>()
.SingleInstance();
containerBuilder.RegisterType<InMemoryCommandBus>()
.As<ICommandBus>()
.SingleInstance();
container = containerBuilder.Build();
return new AutofacServiceProvider(container);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole();
app.UseMvc();
app.UseStaticFiles();
app.UseSwagger();
app.UseSwaggerUi();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();

8
src/PinkParrot/project.json

@ -1,5 +1,7 @@
{
"dependencies": {
"Autofac": "4.1.0",
"Autofac.Extensions.DependencyInjection": "4.0.0",
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
"Microsoft.AspNetCore.Mvc": "1.0.0",
"Microsoft.AspNetCore.Razor.Tools": {
@ -19,10 +21,14 @@
"version": "1.0.0",
"type": "platform"
},
"MongoDB.Driver": "2.3.0-rc1",
"PinkParrot.Core": "1.0.0-*",
"PinkParrot.Events": "1.0.0-*",
"PinkParrot.Infrastructure": "1.0.0-*",
"PinkParrot.Write": "1.0.0-*"
"PinkParrot.Read": "1.0.0-*",
"PinkParrot.Write": "1.0.0-*",
"Swashbuckle.SwaggerGen": "6.0.0-beta901",
"Swashbuckle.SwaggerUi": "6.0.0-beta901"
},
"tools": {

5
src/PinkParrot/web.config

@ -1,10 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!--
Configure your application settings in appsettings.json. Learn more at http://go.microsoft.com/fwlink/?LinkId=786380
-->
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified"/>

8
src/pinkparrot_core/PinkParrot.Core/Schema/ModelField.cs

@ -134,7 +134,7 @@ namespace PinkParrot.Core.Schema
{
if (isHidden)
{
throw new DomainValidationException($"The field '{name} is already hidden.");
throw new ValidationException($"The field '{name} is already hidden.");
}
var clone = Clone();
@ -148,7 +148,7 @@ namespace PinkParrot.Core.Schema
{
if (!isHidden)
{
throw new DomainValidationException($"The field '{name} is already visible.");
throw new ValidationException($"The field '{name} is already visible.");
}
var clone = Clone();
@ -162,7 +162,7 @@ namespace PinkParrot.Core.Schema
{
if (isDisabled)
{
throw new DomainValidationException($"The field '{name} is already disabled.");
throw new ValidationException($"The field '{name} is already disabled.");
}
var clone = Clone();
@ -176,7 +176,7 @@ namespace PinkParrot.Core.Schema
{
if (!isDisabled)
{
throw new DomainValidationException($"The field '{name} is already enabled.");
throw new ValidationException($"The field '{name} is already enabled.");
}
var clone = Clone();

12
src/pinkparrot_core/PinkParrot.Core/Schema/ModelSchema.cs

@ -37,7 +37,7 @@ namespace PinkParrot.Core.Schema
{
if (!name.IsSlug())
{
throw new DomainValidationException("Cannot create the schema.", $"'{name}' is not a valid slug.");
throw new ValidationException("Cannot create the schema.", $"'{name}' is not a valid slug.");
}
return new ModelSchema(new ModelSchemaMetadata(name), ImmutableDictionary<long, ModelField>.Empty);
@ -79,7 +79,7 @@ namespace PinkParrot.Core.Schema
if (errors.Any())
{
throw new DomainValidationException($"Cannot update field with id '{fieldId}', becase the settings are invalid.", errors);
throw new ValidationException($"Cannot update field with id '{fieldId}', becase the settings are invalid.", errors);
}
return newField;
@ -112,7 +112,7 @@ namespace PinkParrot.Core.Schema
if (fields.Values.Any(f => f.Name == field.Name && f.Id != field.Id))
{
throw new DomainValidationException($"A field with name '{field.Name}' already exists.");
throw new ValidationException($"A field with name '{field.Name}' already exists.");
}
return new ModelSchema(metadata, fields.SetItem(field.Id, field));
@ -122,7 +122,7 @@ namespace PinkParrot.Core.Schema
{
if (!fields.ContainsKey(fieldId))
{
throw new DomainValidationException($"A field with id {fieldId} does not exist.");
throw new ValidationException($"A field with id {fieldId} does not exist.");
}
return new ModelSchema(metadata, fields.Remove(fieldId));
@ -134,7 +134,7 @@ namespace PinkParrot.Core.Schema
if (!fields.TryGetValue(fieldId, out field))
{
throw new DomainValidationException($"Cannot update field with id '{fieldId}'.", "Field does not exist.");
throw new ValidationException($"Cannot update field with id '{fieldId}'.", "Field does not exist.");
}
var newField = updater(field);
@ -168,7 +168,7 @@ namespace PinkParrot.Core.Schema
if (errors.Any())
{
throw new DomainValidationException("The data is not valid.", errors);
throw new ValidationException("The data is not valid.", errors);
}
}
}

2
src/pinkparrot_core/PinkParrot.Core/Schema/ModelSchemaMetadata.cs

@ -54,7 +54,7 @@ namespace PinkParrot.Core.Schema
{
if (!newName.IsSlug())
{
throw new DomainValidationException("Cannot update the schema.", $"'{newName}' is not a valid slug.");
throw new ValidationException("Cannot update the schema.", $"'{newName}' is not a valid slug.");
}
clone.name = newName;

4
src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldAdded.cs

@ -6,11 +6,9 @@
// All rights reserved.
// ==========================================================================
using PinkParrot.Infrastructure.CQRS.Events;
namespace PinkParrot.Events.Schema
{
public class ModelFieldAdded : IEvent
public class ModelFieldAdded : TenantEvent
{
public long FieldId;

4
src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldDeleted.cs

@ -6,11 +6,9 @@
// All rights reserved.
// ==========================================================================
using PinkParrot.Infrastructure.CQRS.Events;
namespace PinkParrot.Events.Schema
{
public class ModelFieldDeleted : IEvent
public class ModelFieldDeleted : TenantEvent
{
public long FieldId;
}

4
src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldDisabled.cs

@ -6,11 +6,9 @@
// All rights reserved.
// ==========================================================================
using PinkParrot.Infrastructure.CQRS.Events;
namespace PinkParrot.Events.Schema
{
public class ModelFieldDisabled : IEvent
public class ModelFieldDisabled : TenantEvent
{
public long FieldId;
}

4
src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldEnabled.cs

@ -6,11 +6,9 @@
// All rights reserved.
// ==========================================================================
using PinkParrot.Infrastructure.CQRS.Events;
namespace PinkParrot.Events.Schema
{
public class ModelFieldEnabled : IEvent
public class ModelFieldEnabled : TenantEvent
{
public long FieldId;
}

4
src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldHidden.cs

@ -6,11 +6,9 @@
// All rights reserved.
// ==========================================================================
using PinkParrot.Infrastructure.CQRS.Events;
namespace PinkParrot.Events.Schema
{
public class ModelFieldHidden : IEvent
public class ModelFieldHidden : TenantEvent
{
public long FieldId;
}

4
src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldShown.cs

@ -6,11 +6,9 @@
// All rights reserved.
// ==========================================================================
using PinkParrot.Infrastructure.CQRS.Events;
namespace PinkParrot.Events.Schema
{
public class ModelFieldShown : IEvent
public class ModelFieldShown : TenantEvent
{
public long FieldId;
}

3
src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldUpdated.cs

@ -7,11 +7,10 @@
// ==========================================================================
using PinkParrot.Infrastructure;
using PinkParrot.Infrastructure.CQRS.Events;
namespace PinkParrot.Events.Schema
{
public class ModelFieldUpdated : IEvent
public class ModelFieldUpdated : TenantEvent
{
public long FieldId;

4
src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaCreated.cs

@ -6,11 +6,9 @@
// All rights reserved.
// ==========================================================================
using PinkParrot.Infrastructure.CQRS.Events;
namespace PinkParrot.Events.Schema
{
public class ModelSchemaCreated : IEvent
public class ModelSchemaCreated : TenantEvent
{
public string Name;
}

4
src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaDeleted.cs

@ -6,11 +6,9 @@
// All rights reserved.
// ==========================================================================
using PinkParrot.Infrastructure.CQRS.Events;
namespace PinkParrot.Events.Schema
{
public class ModelSchemaDeleted : IEvent
public class ModelSchemaDeleted : TenantEvent
{
}
}

3
src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaUpdated.cs

@ -7,11 +7,10 @@
// ==========================================================================
using PinkParrot.Infrastructure;
using PinkParrot.Infrastructure.CQRS.Events;
namespace PinkParrot.Events.Schema
{
public class ModelSchemaUpdated : IEvent
public class ModelSchemaUpdated : TenantEvent
{
public string NewName;

18
src/pinkparrot_events/PinkParrot.Events/TenantEvent.cs

@ -0,0 +1,18 @@
// ==========================================================================
// TenantEvent.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using System;
using PinkParrot.Infrastructure.CQRS.Events;
namespace PinkParrot.Events
{
public class TenantEvent : IEvent
{
public Guid TenantId;
}
}

3
src/pinkparrot_infrastructure/PinkParrot.Infrastructure.Tests/DispatchingTests.cs

@ -10,6 +10,9 @@ 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
namespace PinkParrot.Infrastructure
{

8
src/pinkparrot_infrastructure/PinkParrot.Infrastructure.Tests/PropertiesBagTests.cs

@ -295,6 +295,14 @@ namespace PinkParrot.Infrastructure
AssertBoolean(false);
}
[Fact]
public void Should_provide_value_as_string()
{
bag.Set("Key", "Foo");
AssertString("Foo");
}
[Fact]
public void Should_throw_when_converting_instant_to_number()
{

33
src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Autofac/AutofacDomainObjectFactory.cs

@ -0,0 +1,33 @@
// ==========================================================================
// AutofacDomainObjectFactory.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using System;
using Autofac;
using PinkParrot.Infrastructure.CQRS.Commands;
namespace PinkParrot.Infrastructure.CQRS.Autofac
{
public sealed class AutofacDomainObjectFactory : IDomainObjectFactory
{
private readonly IContainer container;
public AutofacDomainObjectFactory(IContainer container)
{
Guard.NotNull(container, nameof(container));
this.container = container;
}
public IAggregate CreateNew(Type type, Guid id)
{
return (IAggregate)container.Resolve(type,
new NamedParameter("id", id),
new NamedParameter("version", 0));
}
}
}

16
src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/DomainObject.cs

@ -38,17 +38,19 @@ namespace PinkParrot.Infrastructure.CQRS
this.version = version;
}
protected abstract void ApplyEvent(IEvent @event);
protected abstract void ApplyEvent(Envelope<IEvent> @event);
protected void RaiseEvent<TEvent>(Envelope<TEvent> envelope, bool disableApply = false) where TEvent : class, IEvent
{
Guard.NotNull(envelope, nameof(envelope));
uncomittedEvents.Add(envelope.To<IEvent>());
var envelopeToAdd = envelope.To<IEvent>();
uncomittedEvents.Add(envelopeToAdd);
if (!disableApply)
{
ApplyEvent(envelope.Payload);
ApplyEvent(envelopeToAdd);
}
}
@ -56,15 +58,17 @@ namespace PinkParrot.Infrastructure.CQRS
{
Guard.NotNull(@event, nameof(@event));
uncomittedEvents.Add(EnvelopeFactory.ForEvent(@event, id));
var envelopeToAdd = EnvelopeFactory.ForEvent(@event, id);
uncomittedEvents.Add(envelopeToAdd);
if (!disableApply)
{
ApplyEvent(@event);
ApplyEvent(envelopeToAdd);
}
}
void IAggregate.ApplyEvent(IEvent @event)
void IAggregate.ApplyEvent(Envelope<IEvent> @event)
{
ApplyEvent(@event); version++;
}

20
src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/EnvelopeExtensions.cs

@ -14,9 +14,9 @@ namespace PinkParrot.Infrastructure.CQRS
{
public static class EnvelopeExtensions
{
public static int EventNumber<T>(this Envelope<T> envelope) where T : class
public static int EventNumber(this EnvelopeHeaders headers)
{
return envelope.Headers[CommonHeaders.EventNumber].ToInt32(CultureInfo.InvariantCulture);
return headers[CommonHeaders.EventNumber].ToInt32(CultureInfo.InvariantCulture);
}
public static Envelope<T> SetEventNumber<T>(this Envelope<T> envelope, int value) where T : class
@ -26,9 +26,9 @@ namespace PinkParrot.Infrastructure.CQRS
return envelope;
}
public static Guid CommitId<T>(this Envelope<T> envelope) where T : class
public static Guid CommitId(this EnvelopeHeaders headers)
{
return envelope.Headers[CommonHeaders.CommitId].ToGuid(CultureInfo.InvariantCulture);
return headers[CommonHeaders.CommitId].ToGuid(CultureInfo.InvariantCulture);
}
public static Envelope<T> SetCommitId<T>(this Envelope<T> envelope, Guid value) where T : class
@ -38,9 +38,9 @@ namespace PinkParrot.Infrastructure.CQRS
return envelope;
}
public static Guid AggregateId<T>(this Envelope<T> envelope) where T : class
public static Guid AggregateId(this EnvelopeHeaders headers)
{
return envelope.Headers[CommonHeaders.AggregateId].ToGuid(CultureInfo.InvariantCulture);
return headers[CommonHeaders.AggregateId].ToGuid(CultureInfo.InvariantCulture);
}
public static Envelope<T> SetAggregateId<T>(this Envelope<T> envelope, Guid value) where T : class
@ -50,9 +50,9 @@ namespace PinkParrot.Infrastructure.CQRS
return envelope;
}
public static Guid EventId<T>(this Envelope<T> envelope) where T : class
public static Guid EventId(this EnvelopeHeaders headers)
{
return envelope.Headers[CommonHeaders.EventId].ToGuid(CultureInfo.InvariantCulture);
return headers[CommonHeaders.EventId].ToGuid(CultureInfo.InvariantCulture);
}
public static Envelope<T> SetEventId<T>(this Envelope<T> envelope, Guid value) where T : class
@ -62,9 +62,9 @@ namespace PinkParrot.Infrastructure.CQRS
return envelope;
}
public static Instant Timestamp<T>(this Envelope<T> envelope) where T : class
public static Instant Timestamp(this EnvelopeHeaders headers)
{
return envelope.Headers[CommonHeaders.Timestamp].ToInstant(CultureInfo.InvariantCulture);
return headers[CommonHeaders.Timestamp].ToInstant(CultureInfo.InvariantCulture);
}
public static Envelope<T> SetTimestamp<T>(this Envelope<T> envelope, Instant value) where T : class

11
src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/GetEventStore/GetEventStoreDomainObjectRepository.cs

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace PinkParrot.Infrastructure.CQRS.GetEventStore
{
public class GetEventStoreDomainObjectRepository
{
}
}

2
src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/IAggregate.cs

@ -18,7 +18,7 @@ namespace PinkParrot.Infrastructure.CQRS
int Version { get; }
void ApplyEvent(IEvent @event);
void ApplyEvent(Envelope<IEvent> @event);
void ClearUncommittedEvents();

1
src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/ActionContextDispatcherFactory.cs

@ -27,6 +27,7 @@ namespace PinkParrot.Infrastructure.Dispatching
return new Tuple<Type, Action<TTarget, object, TContext>>(inputType, (Action<TTarget, object, TContext>)handler);
}
// ReSharper disable once UnusedMember.Local
private static Action<TTarget, object, TContext> Factory<TTarget, TIn, TContext>(MethodInfo methodInfo)
{
var type = typeof(Action<TTarget, TIn, TContext>);

1
src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/ActionDispatcherFactory.cs

@ -27,6 +27,7 @@ namespace PinkParrot.Infrastructure.Dispatching
return new Tuple<Type, Action<T, object>>(inputType, (Action<T, object>)handler);
}
// ReSharper disable once UnusedMember.Local
private static Action<TTarget, object> Factory<TTarget, TIn>(MethodInfo methodInfo)
{
var type = typeof(Action<TTarget, TIn>);

1
src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/FuncContextDispatcherFactory.cs

@ -27,6 +27,7 @@ namespace PinkParrot.Infrastructure.Dispatching
return new Tuple<Type, Func<TTarget, object, TContext, TOut>>(inputType, (Func<TTarget, object, TContext, TOut>)handler);
}
// ReSharper disable once UnusedMember.Local
private static Func<TTarget, object, TContext, TOut> Factory<TTarget, TIn, TContext, TOut>(MethodInfo methodInfo)
{
var type = typeof(Func<TTarget, TIn, TContext, TOut>);

1
src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/FuncDispatcherFactory.cs

@ -27,6 +27,7 @@ namespace PinkParrot.Infrastructure.Dispatching
return new Tuple<Type, Func<TTarget, object, TReturn>>(inputType, (Func<TTarget, object, TReturn>)handler);
}
// ReSharper disable once UnusedMember.Local
private static Func<TTarget, object, TReturn> Factory<TTarget, TIn, TReturn>(MethodInfo methodInfo)
{
var type = typeof(Func<TTarget, TIn, TReturn>);

15
src/pinkparrot_infrastructure/PinkParrot.Infrastructure/ICommandContext.cs

@ -1,15 +0,0 @@
using System;
namespace PinkParrot.Infrastructure.CQRS.Commands
{
public interface ICommandContext
{
ICommand Command { get; }
Exception Exception { get; }
IDomainObjectFactory Factory { get; }
bool IsFailed { get; }
bool IsHandled { get; }
bool IsSucceeded { get; }
IDomainObjectRepository Repository { get; }
}
}

12
src/pinkparrot_infrastructure/PinkParrot.Infrastructure/DomainValidationException.cs → src/pinkparrot_infrastructure/PinkParrot.Infrastructure/ValidationException.cs

@ -1,5 +1,5 @@
// ==========================================================================
// DomainValidationException.cs
// ValidationException.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
@ -12,7 +12,7 @@ using System.Linq;
namespace PinkParrot.Infrastructure
{
public class DomainValidationException : Exception
public class ValidationException : Exception
{
private readonly IReadOnlyList<string> errors;
@ -21,25 +21,25 @@ namespace PinkParrot.Infrastructure
get { return errors; }
}
public DomainValidationException(string message, params string[] errors)
public ValidationException(string message, params string[] errors)
: base(message)
{
this.errors = errors != null ? errors.ToList() : new List<string>();
}
public DomainValidationException(string message, IReadOnlyList<string> errors)
public ValidationException(string message, IReadOnlyList<string> errors)
: base(message)
{
this.errors = errors ?? new List<string>();
}
public DomainValidationException(string message, Exception inner, params string[] errors)
public ValidationException(string message, Exception inner, params string[] errors)
: base(message, inner)
{
this.errors = errors != null ? errors.ToList() : new List<string>();
}
public DomainValidationException(string message, Exception inner, IReadOnlyList<string> errors)
public ValidationException(string message, Exception inner, IReadOnlyList<string> errors)
: base(message, inner)
{
this.errors = errors ?? new List<string>();

7
src/pinkparrot_infrastructure/PinkParrot.Infrastructure/project.json

@ -1,11 +1,12 @@
{
"version": "1.0.0-*",
"dependencies": {
"NodaTime": "2.0.0-alpha20160729",
"Autofac": "4.1.0",
"NETStandard.Library": "1.6.0",
"System.Reflection.TypeExtensions": "4.1.0",
"Newtonsoft.Json": "9.0.1",
"NodaTime": "2.0.0-alpha20160729",
"System.Linq": "4.1.0",
"Newtonsoft.Json": "9.0.1"
"System.Reflection.TypeExtensions": "4.1.0"
},
"frameworks": {
"netcoreapp1.0": {

16
src/pinkparrot_read/PinkParrot.Read/Models/ModelSchemaRM.cs

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace PinkParrot.Read.Models
{
public sealed class ModelSchemaRM
{
public string Id { get; set; }
public string Name { get; set; }
public Guid SchemaId { get; set; }
}
}

19
src/pinkparrot_read/PinkParrot.Read/PinkParrot.Read.xproj

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0.25420" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.25420</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>a92b4734-2587-4f6f-97a3-741be48709a5</ProjectGuid>
<RootNamespace>PinkParrot.Read</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

19
src/pinkparrot_read/PinkParrot.Read/Repositories/IModelSchemaRepository.cs

@ -0,0 +1,19 @@
// ==========================================================================
// IModelSchemaRepository.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using System.Collections.Generic;
using System.Threading.Tasks;
using PinkParrot.Read.Models;
namespace PinkParrot.Read.Repositories
{
public interface IModelSchemaRepository
{
Task<List<ModelSchemaRM>> QueryAllAsync();
}
}

42
src/pinkparrot_read/PinkParrot.Read/Repositories/MongoDb/MongoDbModelSchemaRepository.cs

@ -0,0 +1,42 @@
// ==========================================================================
// MongoDbModelSchemaRepository.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
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;
namespace PinkParrot.Read.Repositories.MongoDb
{
public sealed class MongoDbModelSchemaRepository : BaseRepository<ModelSchemaRM>, IModelSchemaRepository
{
public MongoDbModelSchemaRepository(IMongoDatabase database)
: base(database, "ModelSchemas")
{
CreateIndicesAsync().Wait();
}
private async Task CreateIndicesAsync()
{
await Collection.Indexes.CreateOneAsync(IndexKeys.Ascending(x => x.SchemaId));
}
public IQueryable<ModelSchemaRM> QuerySchemas()
{
return Collection.AsQueryable();
}
public Task<List<ModelSchemaRM>> QueryAllAsync()
{
return Collection.Find(s => true).ToListAsync();
}
}
}

33
src/pinkparrot_read/PinkParrot.Read/Repositories/MongoDb/Utils/BaseRepository.cs

@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MongoDB.Driver;
using PinkParrot.Infrastructure;
namespace PinkParrot.Read.Repositories.MongoDb.Utils
{
public abstract class BaseRepository<T>
{
private readonly IMongoCollection<T> collection;
private readonly IndexKeysDefinitionBuilder<T> indexKeys = new IndexKeysDefinitionBuilder<T>();
protected IMongoCollection<T> Collection
{
get { return collection; }
}
protected IndexKeysDefinitionBuilder<T> IndexKeys
{
get { return indexKeys; }
}
protected BaseRepository(IMongoDatabase database, string collectioName)
{
Guard.NotNull(database, nameof(database));
Guard.NotNullOrEmpty(collectioName, nameof(collectioName));
collection = database.GetCollection<T>(collectioName);
}
}
}

27
src/pinkparrot_read/PinkParrot.Read/project.json

@ -0,0 +1,27 @@
{
"version": "1.0.0-*",
"dependencies": {
"MongoDB.Driver": "2.3.0-rc1",
"NETStandard.Library": "1.6.0",
"NodaTime": "2.0.0-alpha20160729",
"PinkParrot.Core": "1.0.0-*",
"PinkParrot.Events": "1.0.0-*",
"PinkParrot.Infrastructure": "1.0.0-*"
},
"frameworks": {
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0"
}
}
}
},
"tooling": {
"defaultNamespace": "PinkParrot.Read"
}
}

18
src/pinkparrot_write/PinkParrot.Write/Schema/ISchemaIdProvider.cs

@ -0,0 +1,18 @@
// ==========================================================================
// ISchemaIdProvider.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using System;
using System.Threading.Tasks;
namespace PinkParrot.Write.Schema
{
public interface ISchemaIdProvider
{
Task<Guid> FindSchemaId(string name);
}
}

4
src/pinkparrot_write/PinkParrot.Write/Schema/ModelSchemaDomainObject.cs

@ -199,9 +199,9 @@ namespace PinkParrot.Write.Schema
}
}
protected override void ApplyEvent(IEvent @event)
protected override void ApplyEvent(Envelope<IEvent> @event)
{
this.DispatchAction(@event);
this.DispatchAction(@event.Payload);
}
}
}

70
src/pinkparrot_write/PinkParrot.Write/Schema/ModelSchemaNameMap.cs

@ -0,0 +1,70 @@
// ==========================================================================
// 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<string, Guid> schemaIdsByName = new Dictionary<string, Guid>();
private readonly Dictionary<Guid, string> schemaNamesByIds = new Dictionary<Guid, string>();
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<IEvent> @event)
{
ApplyEvent(@event);
}
protected override void ApplyEvent(Envelope<IEvent> @event)
{
this.DispatchAction(@event.Payload, @event.Headers);
}
}
}
Loading…
Cancel
Save