IEnumerable <Proxy> GenerateReadModelProxy(Type artifact, ArtifactsConfiguration artifactsConfig, BuildTaskConfiguration configuration, Func <object, string> template) { _buildMessages.Trace($"Creating read model proxy for {ClrType.FromType(artifact).TypeString}"); var artifactId = GetArtifactId(artifact, artifactsConfig); var artifactDefinition = GetArtifactDefinition(artifact, artifactsConfig); var handlebarsReadmodel = new HandlebarsReadmodel() { ReadModelName = artifact.Name, ReadModelArtifactId = artifactId.Value.ToString(), ReadModelGeneration = artifactDefinition.Generation.Value.ToString() }; var setableProperties = artifact.GetSettableProperties(); if (setableProperties.Any()) { handlebarsReadmodel.Properties = CreateProxyProperties(setableProperties); } var proxies = new List <Proxy>(); foreach (var path in configuration.ProxiesBasePath) { proxies.Add(CreateProxy(artifact, template(handlebarsReadmodel), configuration, path)); } return(proxies); }
static void ThrowIfDuplicateArtifacts(ArtifactsConfiguration artifacts, IBuildMessages buildMessages) { var idMap = new Dictionary <ArtifactId, ClrType>(); bool foundDuplicate = false; foreach (var artifactDefinitionEntry in artifacts.GetAllArtifactDefinitions()) { if (idMap.ContainsKey(artifactDefinitionEntry.Key)) { foundDuplicate = true; var artifactId = artifactDefinitionEntry.Key; var clrType = idMap[artifactId]; buildMessages.Error($"The artifacts '{clrType.TypeString}' and '{artifactDefinitionEntry.Value.Type.TypeString}' has the same ArtifactId: '{artifactId}'"); } else { idMap.Add(artifactDefinitionEntry.Key, artifactDefinitionEntry.Value.Type); } } if (foundDuplicate) { throw new DuplicateArtifact(); } }
IEnumerable <Proxy> GenerateCommandProxy(Type artifact, ArtifactsConfiguration artifactsConfig, BuildTaskConfiguration configuration, Func <object, string> template) { _buildMessages.Trace($"Creating command proxy for {ClrType.FromType(artifact).TypeString}"); var artifactId = GetArtifactId(artifact, artifactsConfig); var handlebarsCommand = new HandlebarsCommand() { CommandName = artifact.Name, ArtifactId = artifactId.Value.ToString() }; var setableProperties = artifact.GetSettableProperties(); if (setableProperties.Length > 0) { handlebarsCommand.Properties = CreateProxyProperties(setableProperties); } var proxies = new List <Proxy>(); foreach (var path in configuration.ProxiesBasePath) { proxies.Add(CreateProxy(artifact, template(handlebarsCommand), configuration, path)); } return(proxies); }
/// <summary> /// Instantiates an instance of <see cref="ArtifactsConfigurationBuilder"/> /// </summary> /// <param name="artifacts">The discovered types of artifacts in the Bounded Context's assemblies</param> /// <param name="currentArtifactsConfiguration">The current <see cref="ArtifactsConfiguration"/> that will be used as a base for building a valid updated configuration that is returned from Build</param> /// <param name="artifactTypes">A list of <see cref="ArtifactType"/> which represents the different artifact types</param> /// <param name="buildMessages"></param> public ArtifactsConfigurationBuilder(Type[] artifacts, ArtifactsConfiguration currentArtifactsConfiguration, ArtifactTypes artifactTypes, IBuildMessages buildMessages) { _artifacts = artifacts; _buildMessages = buildMessages; _artifactTypes = artifactTypes; _currentArtifactsConfiguration = currentArtifactsConfiguration; }
/// <summary> /// Instantiates an instance of <see cref="ArtifactsConfigurationBuilder"/> /// </summary> /// <param name="artifacts">The discovered types of artifacts in the Bounded Context's assemblies</param> /// <param name="currentArtifactsConfiguration">The current <see cref="ArtifactsConfiguration"/> that will be used as a base for building a valid updated configuration that is returned from Build</param> /// <param name="artifactTypes">A list of <see cref="ArtifactType"/> which represents the different artifact types</param> /// <param name="logger"></param> public ArtifactsConfigurationBuilder(Type[] artifacts, ArtifactsConfiguration currentArtifactsConfiguration, DolittleArtifactTypes artifactTypes, IBuildToolLogger logger) { _artifacts = artifacts; _logger = logger; _artifactTypes = artifactTypes; _currentArtifactsConfiguration = currentArtifactsConfiguration; }
/// <inheritdoc/> public void Save(ArtifactsConfiguration configuration) { var path = GetPath(); var json = _serializer.ToJson(configuration, _serializationOptions); File.WriteAllText(path, json); }
/// <summary> /// Generates all proxies for all relevant artifacts and writes them as files in their corresponding feature structure /// </summary> public void GenerateProxies(ArtifactsConfiguration artifactsConfiguration, ArgumentsParsingResult parsingResults) { var proxies = new List <Proxy>(); GenerateProxies(artifactsConfiguration, parsingResults, _templateLoader.CommandProxyTemplate, "command", GenerateCommandProxy, ref proxies); GenerateProxies(artifactsConfiguration, parsingResults, _templateLoader.QueryProxyTemplate, "query", GenereateQueryProxy, ref proxies); GenerateProxies(artifactsConfiguration, parsingResults, _templateLoader.ReadModelProxyTemplate, "read model", GenerateReadModelProxy, ref proxies); WriteProxiesToFile(proxies.ToArray()); }
/// <summary> /// Generates all proxies for all relevant artifacts and writes them as files in their corresponding feature structure /// </summary> public void GenerateProxies(ArtifactsConfiguration artifactsConfiguration, BuildTaskConfiguration configuration) { var proxies = new List <Proxy>(); GenerateProxies(artifactsConfiguration, configuration, _templateLoader.CommandProxyTemplate, "command", GenerateCommandProxy, ref proxies); GenerateProxies(artifactsConfiguration, configuration, _templateLoader.QueryProxyTemplate, "query", GenereateQueryProxy, ref proxies); GenerateProxies(artifactsConfiguration, configuration, _templateLoader.ReadModelProxyTemplate, "read model", GenerateReadModelProxy, ref proxies); WriteProxiesToFile(proxies.ToArray()); }
/// <summary> /// Validates the <see cref="ArtifactsConfiguration"/> based on the bounded context's topology and the discoved artifact types in the assemblies of the bounded context. /// </summary> /// <param name="configuration">The <see cref="ArtifactsConfiguration"/> being extended.</param> /// <param name="boundedContextTopology"><see cref="BoundedContextTopology"/> to validate against.</param> /// <param name="types">All <see cref="Type">types</see> to validate.</param> /// <param name="buildMessages"><see cref="IBuildMessages"/> for outputting build messages.</param> public static void ValidateArtifacts( this ArtifactsConfiguration configuration, BoundedContextTopology boundedContextTopology, IEnumerable <Type> types, IBuildMessages buildMessages) { ThrowIfDuplicateArtifacts(configuration, buildMessages); WarnIfFeatureMissingFromTopology(configuration, boundedContextTopology, buildMessages); WarnIfArtifactNoLongerInStructure(configuration, types, buildMessages); }
/// <summary> /// Initializes a new instance of the <see cref="ArtifactMapper{T}"/> class. /// </summary> /// <param name="topology"><see cref="Topology"/> configuration.</param> /// <param name="artifacts">The <see cref="ArtifactsConfiguration"/>.</param> /// <param name="artifactTypeMap"><see cref="IArtifactTypeMap"/> for mapping artifacts and types.</param> public ArtifactMapper( Topology topology, ArtifactsConfiguration artifacts, IArtifactTypeMap artifactTypeMap) { _topology = topology; _artifacts = artifacts; _artifactTypeMap = artifactTypeMap; _artifactPaths = new Dictionary <Type, PathString>(); BuildMapOfArtifacts(); }
/// <summary> /// Initializes a new instance of the <see cref="ArtifactMapper{T}"/> class. /// </summary> /// <param name="topology"><see cref="Topology"/> configuration.</param> /// <param name="artifacts">The <see cref="ArtifactsConfiguration"/>.</param> /// <param name="artifactTypeMap"><see cref="IArtifactTypeMap"/> for mapping artifacts and types.</param> public ArtifactMapper( Topology topology, ArtifactsConfiguration artifacts, IArtifactTypeMap artifactTypeMap) { _topology = topology; _artifacts = artifacts; _artifactTypeMap = artifactTypeMap; _artifactsByPath = new Dictionary <string, Type>(); BuildMapOfAllCorrespondingArtifacts(); }
Proxy GenereateQueryProxy(Type artifact, ArtifactsConfiguration artifactsConfig, BuildTaskConfiguration configuration, Func <object, string> template) { _buildMessages.Trace($"Creating query proxy for {ClrType.FromType(artifact).TypeString}"); var handlebarsQuery = new HandlebarsQuery() { ClrType = artifact.FullName, QueryName = artifact.Name }; var setableProperties = artifact.GetSettableProperties(); if (setableProperties.Any()) { handlebarsQuery.Properties = CreateProxyProperties(setableProperties); } return(CreateProxy(artifact, template(handlebarsQuery), configuration)); }
Proxy GenereateQueryProxy(Type artifact, ArtifactsConfiguration artifactsConfig, ArgumentsParsingResult parsingResults, Func <object, string> template) { _logger.Trace($"Creating query proxy for {ClrType.FromType(artifact).TypeString}"); var handlebarsQuery = new HandlebarsQuery() { ClrType = artifact.FullName, QueryName = artifact.Name }; var setableProperties = artifact.GetSettableProperties(); if (setableProperties.Any()) { handlebarsQuery.Properties = CreateProxyProperties(setableProperties); } return(CreateProxy(artifact, template(handlebarsQuery), parsingResults)); }
void GenerateProxies( ArtifactsConfiguration artifactsConfiguration, BuildTaskConfiguration configuration, Func <object, string> template, string artifactTypeName, Func <Type, ArtifactsConfiguration, BuildTaskConfiguration, Func <object, string>, IEnumerable <Proxy> > ProxyGeneratorFunction, ref List <Proxy> proxies) { var artifactType = _artifactTypes.Single(_ => _.TypeName.Equals(artifactTypeName)).Type; var artifacts = _artifacts.Where(_ => artifactType.IsAssignableFrom(_)); foreach (var artifact in artifacts) { var newProxies = ProxyGeneratorFunction(artifact, artifactsConfiguration, configuration, template); proxies.AddRange(newProxies); } }
static void WarnIfFeatureMissingFromTopology(ArtifactsConfiguration artifacts, BoundedContextTopology boundedContextTopology, IBuildMessages buildMessages) { Dictionary <Feature, FeatureName> featureMap = boundedContextTopology.RetrieveAllFeatureIds(); foreach (var artifact in artifacts) { if (!featureMap.ContainsKey(artifact.Key)) { buildMessages.Warning($"Found artifacts under a Feature that does not exist in the topology. Feature: '{artifact.Key}':"); buildMessages.Warning("Artifacts:"); foreach (var definitionEntry in artifacts.GetAllArtifactDefinitions(artifact.Key)) { buildMessages.Warning($"\tArtifact: '{definitionEntry.Key.Value}' - '{definitionEntry.Value.Type.TypeString} @{definitionEntry.Value.Generation.Value}'"); } } } }
IEnumerable <Proxy> GenerateProxies( ArtifactsConfiguration artifactsConfiguration, BuildTaskConfiguration configuration, Func <object, string> template, string artifactTypeName, Func <Type, ArtifactsConfiguration, BuildTaskConfiguration, Func <object, string>, IEnumerable <Proxy> > proxyGeneratorFunction) { List <Proxy> proxies = new List <Proxy>(); var artifactType = _artifactTypes.Single(_ => _.TypeName.Equals(artifactTypeName, StringComparison.InvariantCulture)).Type; foreach (var artifact in _artifacts.Where(_ => artifactType.IsAssignableFrom(_))) { var newProxies = proxyGeneratorFunction(artifact, artifactsConfiguration, configuration, template); proxies.AddRange(newProxies); } return(proxies); }
Proxy GenerateCommandProxy(Type artifact, ArtifactsConfiguration artifactsConfig, BuildTaskConfiguration configuration, Func <object, string> template) { _buildMessages.Trace($"Creating command proxy for {ClrType.FromType(artifact).TypeString}"); var artifactId = GetArtifactId(artifact, artifactsConfig); var handlebarsCommand = new HandlebarsCommand() { CommandName = artifact.Name, ArtifactId = artifactId.Value.ToString() }; var setableProperties = artifact.GetSettableProperties(); if (setableProperties.Any()) { handlebarsCommand.Properties = CreateProxyProperties(setableProperties); } return(CreateProxy(artifact, template(handlebarsCommand), configuration)); }
Proxy GenerateCommandProxy(Type artifact, ArtifactsConfiguration artifactsConfig, ArgumentsParsingResult parsingResults, Func <object, string> template) { _logger.Trace($"Creating command proxy for {ClrType.FromType(artifact).TypeString}"); var artifactId = GetArtifactId(artifact, artifactsConfig); var handlebarsCommand = new HandlebarsCommand() { CommandName = artifact.Name, ArtifactId = artifactId.Value.ToString() }; var setableProperties = artifact.GetSettableProperties(); if (setableProperties.Any()) { handlebarsCommand.Properties = CreateProxyProperties(setableProperties); } return(CreateProxy(artifact, template(handlebarsCommand), parsingResults)); }
Proxy GenerateReadModelProxy(Type artifact, ArtifactsConfiguration artifactsConfig, ArgumentsParsingResult parsingResults, Func <object, string> template) { _logger.Trace($"Creating read model proxy for {ClrType.FromType(artifact).TypeString}"); var artifactId = GetArtifactId(artifact, artifactsConfig); var artifactDefinition = GetArtifactDefinition(artifact, artifactsConfig); var handlebarsReadmodel = new HandlebarsReadmodel() { ReadModelName = artifact.Name, ReadModelArtifactId = artifactId.Value.ToString(), ReadModelGeneration = artifactDefinition.Generation.Value.ToString() }; var setableProperties = artifact.GetSettableProperties(); if (setableProperties.Any()) { handlebarsReadmodel.Properties = CreateProxyProperties(setableProperties); } return(CreateProxy(artifact, template(handlebarsReadmodel), parsingResults)); }
void GenerateProxies( ArtifactsConfiguration artifactsConfiguration, ArgumentsParsingResult parsingResults, Func <object, string> template, string artifactTypeName, Func <Type, ArtifactsConfiguration, ArgumentsParsingResult, Func <object, string>, Proxy> ProxyGeneratorFunction, ref List <Proxy> proxies) { var artifactType = _artifactTypes.ArtifactTypes.Single(_ => _.TypeName.Equals(artifactTypeName)).Type; var artifacts = _artifacts.Where(_ => artifactType.IsAssignableFrom(_)); foreach (var artifact in artifacts) { var proxy = ProxyGeneratorFunction(artifact, artifactsConfiguration, parsingResults, template); if (proxy != null) { proxies.Add(proxy); } } }
IEnumerable <Proxy> GenereateQueryProxy(Type artifact, ArtifactsConfiguration artifactsConfig, BuildTaskConfiguration configuration, Func <object, string> template) { _buildMessages.Trace($"Creating query proxy for {ClrType.FromType(artifact).TypeString}"); var handlebarsQuery = new HandlebarsQuery() { ClrType = artifact.FullName, QueryName = artifact.Name }; var setableProperties = artifact.GetSettableProperties(); if (setableProperties.Any()) { handlebarsQuery.Properties = CreateProxyProperties(setableProperties); } var proxies = new List <Proxy>(); foreach (var path in configuration.ProxiesBasePath) { proxies.Add(CreateProxy(artifact, template(handlebarsQuery), configuration, path)); } return(proxies); }
static void WarnIfArtifactNoLongerInStructure(ArtifactsConfiguration artifacts, IEnumerable <Type> types, IBuildMessages messages) { var artifactDefinitions = new Dictionary <ArtifactId, ArtifactDefinition>(); foreach (var artifactDefinitionEntry in artifacts.GetAllArtifactDefinitions()) { if (!types.Contains(artifactDefinitionEntry.Value.Type.GetActualType())) { artifactDefinitions.Add(artifactDefinitionEntry.Key, artifactDefinitionEntry.Value); } } if (artifactDefinitions.Any()) { messages.Warning("There are artifacts that are not found in the Bounded Context's artifacts file:"); messages.Warning("Artifacts:"); foreach (var artifactDefinitionEntry in artifactDefinitions) { messages.Warning($"\tArtifact: '{artifactDefinitionEntry.Key.Value}' - '{artifactDefinitionEntry.Value.Type.TypeString} @{artifactDefinitionEntry.Value.Generation.Value}'"); } throw new ArtifactNoLongerInStructure(); } }
ArtifactDefinition GetArtifactDefinition(Type artifact, ArtifactsConfiguration config) { return(config.GetMatchingArtifactDefinition(artifact)); }
ArtifactId GetArtifactId(Type artifact, ArtifactsConfiguration config) { return(config.GetMatchingArtifactId(artifact)); }
/// <summary> /// Validates the <see cref="ArtifactsConfiguration"/> based on the bounded context's topology and the discoved artifact types in the assemblies of the bounded context /// </summary> public static void ValidateArtifacts(this ArtifactsConfiguration artifacts, BoundedContextTopology boundedContextTopology, Type[] types, IBuildMessages buildMessages) { ThrowIfDuplicateArtifacts(artifacts, buildMessages); WarnIfFeatureMissingFromTopology(artifacts, boundedContextTopology, buildMessages); WarnIfArtifactNoLongerInStructure(artifacts, types, buildMessages); }
/// <summary> /// Gets a <see cref="ArtifactDefinition"/> that corresponds to the artifact's <see cref="Type"/> /// </summary> public static ArtifactDefinition GetMatchingArtifactDefinition(this ArtifactsConfiguration artifacts, Type artifact) { var artifactDefinitions = artifacts.GetAllArtifactDefinitions(); return(artifactDefinitions.Single(_ => _.Value.Type.GetActualType().Equals(artifact)).Value); }
/// <summary> /// Returns all <see cref="ArtifactDefinition"/> instances with a specific <see cref="Feature"/> (id) in the <see cref="ArtifactsConfiguration"/> /// </summary> public static IEnumerable <KeyValuePair <ArtifactId, ArtifactDefinition> > GetAllArtifactDefinitions(this ArtifactsConfiguration artifacts, Feature id) { var artifactDefinitions = new List <KeyValuePair <ArtifactId, ArtifactDefinition> >(); var artifact = artifacts[id]; artifactDefinitions.AddRange(artifact.Commands); artifactDefinitions.AddRange(artifact.Events); artifactDefinitions.AddRange(artifact.EventSources); artifactDefinitions.AddRange(artifact.Queries); artifactDefinitions.AddRange(artifact.ReadModels); return(artifactDefinitions); }
/// <summary> /// Returns all <see cref="ArtifactDefinition"/> instances in the <see cref="ArtifactsConfiguration"/> by retrieving the <see cref="ArtifactDefinition"/> dictionaries with the <see cref="PropertyInfo"/> /// </summary> public static IEnumerable <KeyValuePair <ArtifactId, ArtifactDefinition> > GetAllArtifactDefinitions(this ArtifactsConfiguration artifacts, PropertyInfo targetProperty) { var artifactDefinitions = new List <KeyValuePair <ArtifactId, ArtifactDefinition> >(); foreach (var artifactEntry in artifacts) { var selectedArtifacts = targetProperty.GetValue(artifactEntry.Value) as IDictionary <ArtifactId, ArtifactDefinition>; artifactDefinitions.AddRange(selectedArtifacts); } return(artifactDefinitions); }
/// <summary> /// Returns all <see cref="ArtifactDefinition"/> instances in the <see cref="ArtifactsConfiguration"/> /// </summary> public static IEnumerable <KeyValuePair <ArtifactId, ArtifactDefinition> > GetAllArtifactDefinitions(this ArtifactsConfiguration artifacts) { var artifactDefinitions = new List <KeyValuePair <ArtifactId, ArtifactDefinition> >(); foreach (var artifactEntry in artifacts) { artifactDefinitions.AddRange(artifactEntry.Value.Commands); artifactDefinitions.AddRange(artifactEntry.Value.Events); artifactDefinitions.AddRange(artifactEntry.Value.EventSources); artifactDefinitions.AddRange(artifactEntry.Value.Queries); artifactDefinitions.AddRange(artifactEntry.Value.ReadModels); } return(artifactDefinitions); }
/// <summary> /// Builds a valid <see cref="ArtifactsConfiguration"/> based on a <see cref="BoundedContextTopology"/> /// </summary> /// <param name="boundedContextTopology"></param> /// <returns></returns> public ArtifactsConfiguration Build(BoundedContextTopology boundedContextTopology) { var newArtifacts = 0; var artifactsDictionary = new MutableAritfactsDictionary(); foreach (var(feature, featureArtifactsByType) in _currentArtifactsConfiguration) { var featureArtifacts = artifactsDictionary[feature] = new Dictionary <PropertyInfo, Dictionary <ArtifactId, ArtifactDefinition> >(); foreach (var artifactType in featureArtifactsByType.GetType().GetProperties()) { var existingArtifactsForFeatureType = artifactType.GetValue(featureArtifactsByType) as IReadOnlyDictionary <ArtifactId, ArtifactDefinition>; featureArtifacts[artifactType] = new Dictionary <ArtifactId, ArtifactDefinition>(existingArtifactsForFeatureType); } } var nonMatchingArtifacts = new List <string>(); foreach (var artifactType in _artifactTypes.ArtifactTypes) { newArtifacts += HandleArtifactOfType( artifactType, boundedContextTopology, artifactsDictionary, nonMatchingArtifacts ); } if (nonMatchingArtifacts.Any()) { foreach (var artifactNamespace in nonMatchingArtifacts) { _logger.Warning($"An artifact with namespace: '{artifactNamespace}' could not be matched with any feature in the Bounded Context's topology"); } throw new NonMatchingArtifact(); } //new Dictionary<Feature, ArtifactsByTypeDefinition>() var artifactsByTypeDefinitionConstructor = typeof(ArtifactsByTypeDefinition).GetConstructors().Single(_ => _.GetParameters().All(p => p.ParameterType.Equals(typeof(IDictionary <ArtifactId, ArtifactDefinition>)))); var updatedArtifactsConfiguration = new ArtifactsConfiguration(new Dictionary <Feature, ArtifactsByTypeDefinition>( artifactsDictionary.Select(_ => { var feature = _.Key; var arguments = artifactsByTypeDefinitionConstructor.GetParameters().Select(arg => { return(_.Value.SingleOrDefault(prop => arg.Name.ToLower().Equals(prop.Key.Name.ToLower())).Value ?? new Dictionary <ArtifactId, ArtifactDefinition>()); }).ToArray(); var artifacts = artifactsByTypeDefinitionConstructor.Invoke(arguments) as ArtifactsByTypeDefinition; return(new KeyValuePair <Feature, ArtifactsByTypeDefinition>(feature, artifacts)); }) )); updatedArtifactsConfiguration.ValidateArtifacts(boundedContextTopology, _artifacts, _logger); if (newArtifacts > 0) { _logger.Information($"Added {newArtifacts} new artifacts to the map."); } else { _logger.Information($"No new artifacts added to the map."); } return(updatedArtifactsConfiguration); }