Example #1
0
        /// <summary>
        /// Loads the current <see cref="ArtifactsConfiguration"/> from file and uses it to build the updated <see cref="ArtifactsConfiguration"/> using the <see cref="ArtifactsConfigurationBuilder"/>.
        /// </summary>
        /// <param name="types">The discovered artifact types from the bounded context's assemblies.</param>
        /// <param name="topology">The <see cref="Applications.Configuration.Topology"/> that's used for building the <see cref="ArtifactsConfiguration"/>.</param>
        /// <param name="configuration">Current <see cref="BuildTaskConfiguration"/>.</param>
        /// <returns>The built <see cref="ArtifactsConfiguration"/>.</returns>
        public ArtifactsConfiguration Build(IEnumerable <Type> types, Applications.Configuration.Topology topology, BuildTaskConfiguration configuration)
        {
            var artifactsConfiguration = _configurationManager.Load();
            var boundedContextTopology = new BoundedContextTopology(topology, configuration.UseModules, configuration.NamespaceSegmentsToStrip);

            return(new ArtifactsConfigurationBuilder(types, artifactsConfiguration, _artifactTypes, _buildMessages).Build(boundedContextTopology));
        }
        /// <summary>
        /// Loads the current <see cref="ArtifactsConfiguration"/> from file and uses it to build the updated <see cref="ArtifactsConfiguration"/> using the <see cref="ArtifactsConfigurationBuilder"/>
        /// </summary>
        /// <param name="types">The discovered artifact types from the bounded context's assemblies</param>
        /// <param name="topology">The <see cref="Applications.Configuration.Topology"/> that's used for building the <see cref="ArtifactsConfiguration"/></param>
        /// <param name="parsingResults"></param>
        public ArtifactsConfiguration Build(Type[] types, Applications.Configuration.Topology topology, ArgumentsParsingResult parsingResults)
        {
            var artifactsConfiguration = _configurationManager.Load();
            var boundedContextTopology = new BoundedContextTopology(topology, parsingResults.UseModules, parsingResults.NamespaceSegmentsToStrip);

            return(new ArtifactsConfigurationBuilder(types, artifactsConfiguration, _artifactTypes, _logger).Build(boundedContextTopology));
        }
        /// <summary>
        /// Returns a <see cref="Dictionary{Feature, FeatureName}"/> where Key is the Feature (id) and Value is the FeatureName of all <see cref="FeatureDefinition"/> in <see cref="Applications.Configuration.Topology"/>
        /// </summary>
        public static Dictionary <Feature, FeatureName> RetrieveAllFeatureIds(this BoundedContextTopology configuration)
        {
            var featureMap = new Dictionary <Feature, FeatureName>();

            AddAllFeaturesToMap(RetrieveFeatures(configuration), featureMap);

            return(featureMap);
        }
 /// <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);
 }
        int HandleArtifactOfType(ArtifactType artifactType, BoundedContextTopology boundedContextConfiguration, MutableAritfactsDictionary artifactsDictionary, List <string> nonMatchingArtifacts)
        {
            var targetProperty = artifactType.TargetPropertyExpression.GetPropertyInfo();

            var newArtifacts = 0;
            var artifacts    = _artifacts.Where(_ => artifactType.Type.IsAssignableFrom(_));

            foreach (var artifact in artifacts)
            {
                var feature = boundedContextConfiguration.FindMatchingFeature(artifact.Namespace, nonMatchingArtifacts);
                if (feature.Value != null)
                {
                    MutableArtifactsByTypeDictionary artifactsByType;
                    if (!artifactsDictionary.TryGetValue(feature.Key, out artifactsByType))
                    {
                        artifactsByType = artifactsDictionary[feature.Key] = new Dictionary <PropertyInfo, Dictionary <ArtifactId, ArtifactDefinition> >();
                    }

                    Dictionary <ArtifactId, ArtifactDefinition> mutableArtifacts;
                    if (!artifactsByType.TryGetValue(targetProperty, out mutableArtifacts))
                    {
                        mutableArtifacts = artifactsByType[targetProperty] = new Dictionary <ArtifactId, ArtifactDefinition>();
                    }

                    if (!mutableArtifacts.Any(_ => _.Value.Type.GetActualType() == artifact))
                    {
                        var artifactObject = new Dolittle.Artifacts.Artifact(ArtifactId.New(), ArtifactGeneration.First);
                        if (artifact.HasAttribute <ArtifactAttribute>())
                        {
                            artifactObject = (artifact.GetTypeInfo().GetCustomAttributes(typeof(ArtifactAttribute), false).First() as ArtifactAttribute).Artifact;
                        }

                        AddNewArtifact(artifactObject, artifact, mutableArtifacts, artifactType.TypeName);
                        newArtifacts++;
                    }
                    else
                    {
                        if (artifact.HasAttribute <ArtifactAttribute>())
                        {
                            var artifactObject = (artifact.GetTypeInfo().GetCustomAttributes(typeof(ArtifactAttribute), false).First() as ArtifactAttribute).Artifact;

                            var existingArtifact = mutableArtifacts.Single(_ => _.Value.Type.GetActualType() == artifact);
                            if (!existingArtifact.Key.Value.Equals(artifactObject.Id.Value))
                            {
                                mutableArtifacts.Remove(existingArtifact.Key);
                                AddNewArtifact(artifactObject, artifact, mutableArtifacts, artifactType.TypeName);
                                newArtifacts++;
                            }
                        }
                    }
                }
            }
            return(newArtifacts);
        }
        /// <summary>
        /// Returns a <see cref="FeatureDefinition"/> that matches the artifact with the given namespace based on the <see cref="BoundedContextTopology">BoundedContextConfiguration's </see> topology
        /// </summary>
        public static KeyValuePair <Feature, FeatureDefinition> FindMatchingFeature(this BoundedContextTopology boundedContextConfiguration, string @namespace)
        {
            var nonMatchingList = new List <string>();
            var featureDef      = boundedContextConfiguration.FindMatchingFeature(@namespace, nonMatchingList);

            if (featureDef.Key == null)
            {
                throw new NonMatchingArtifact();
            }
            return(featureDef);
        }
 /// <summary>
 /// Returns all <see cref="FeatureDefinition"/> from the <see cref="Applications.Configuration.Topology"/>
 /// </summary>
 public static IDictionary <Feature, FeatureDefinition> RetrieveFeatures(this BoundedContextTopology configuration)
 {
     if (configuration.UseModules)
     {
         return(configuration.Topology.Modules.SelectMany(_ => _.Value.Features).ToDictionary(_ => _.Key, _ => _.Value));
     }
     else
     {
         return(configuration.Topology.Features);
     }
 }
Example #8
0
        /// <summary>
        /// Returns a <see cref="FeatureDefinition"/> that matches the artifact with the given namespace based on the <see cref="BoundedContextTopology">BoundedContextConfiguration's </see> topology.
        /// </summary>
        /// <param name="configuration"><see cref="BoundedContextTopology"/> to extend.</param>
        /// <param name="namespace">Namespace to find matching feature in.</param>
        /// <param name="artifactsWithoutMatch">The artifacts that was unmatched.</param>
        /// <returns>A <see cref="KeyValuePair{TKey, TValue}"/> of <see cref="Feature"/> to <see cref="FeatureDefinition"/>.</returns>
        public static KeyValuePair <Feature, FeatureDefinition> FindMatchingFeature(
            this BoundedContextTopology configuration,
            string @namespace,
            List <string> artifactsWithoutMatch)
        {
            var area = new Area()
            {
                Value = @namespace.Split('.').First()
            };
            var segments = @namespace.Split('.').Skip(1).ToArray();

            if (configuration.NamespaceSegmentsToStrip.ContainsKey(area))
            {
                var newSegments = new List <string>(segments);
                foreach (var segment in configuration.NamespaceSegmentsToStrip[area])
                {
                    newSegments.Remove(segment);
                }
                segments = newSegments.ToArray();
            }

            if (configuration.UseModules)
            {
                var matchingModule = configuration.Topology.Modules
                                     .SingleOrDefault(module => module.Value.Name.Value.Equals(segments[0], StringComparison.InvariantCulture));

                try
                {
                    return(FindMatchingFeature(segments.Skip(1).ToArray(), matchingModule.Value.Features));
                }
                catch (Exception)
                {
                    artifactsWithoutMatch.Add(@namespace);
                    return(new KeyValuePair <Feature, FeatureDefinition>(null, null));
                }
            }

            try
            {
                return(FindMatchingFeature(segments, configuration.Topology.Features));
            }
            catch (Exception)
            {
                artifactsWithoutMatch.Add(@namespace);
                return(new KeyValuePair <Feature, FeatureDefinition>(null, null));
            }
        }
Example #9
0
        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:");

                    var artifactDefinitions = artifacts.GetAllArtifactDefinitions(artifact.Key);
                    foreach (var definitionEntry in artifactDefinitions)
                    {
                        buildMessages.Warning($"\tArtifact: '{definitionEntry.Key.Value}' - '{definitionEntry.Value.Type.TypeString} @{definitionEntry.Value.Generation.Value}'");
                    }
                }
            }
        }
        /// <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);
        }