/// <summary>
        /// Analyzes the resulting metrics file and compares the metrics against the threshold values
        /// </summary>
        /// <param name="parent">The parent node in the build log</param>
        /// <param name="metrics">List of metric values</param>
        /// <param name="thresholds">Thresholds for errors and warnings </param>
        /// <param name="fullyQualifiedName">FQN for the method/type under test</param>
        /// <param name="currentName">Name of current method/type </param>
        /// <returns>Number if violations</returns>
        private int ProcessMetrics(IBuildInformationNode parent, IEnumerable <Metric> metrics, SpecificMetricThresholds thresholds, string fullyQualifiedName, string currentName)
        {
            var thecomplainlist = new List <string>();

            foreach (var metric in metrics.Where(metric => metric != null && !string.IsNullOrEmpty(metric.Value)))
            {
                switch (metric.Name)
                {
                case MaintainabilityIndex:
                    this.CheckLimits(metric, thresholds.MIMetricChecker, fullyQualifiedName, thecomplainlist);
                    break;

                case CyclomaticComplexity:
                    this.CheckLimits(metric, thresholds.CCMetricChecker, fullyQualifiedName, thecomplainlist);
                    break;

                case ClassCoupling:
                    this.CheckLimits(metric, thresholds.COMetricChecker, fullyQualifiedName, thecomplainlist);
                    break;

                case DepthOfInheritance:
                    this.CheckLimits(metric, thresholds.DOIMetricChecker, fullyQualifiedName, thecomplainlist);
                    break;

                case LinesOfCode:
                    this.CheckLimits(metric, thresholds.LOCMetricChecker, fullyQualifiedName, thecomplainlist);
                    break;

                default:
                    throw new UnknownMetricNameException(metric.Name);
                }
            }

            if (this.logCodeMetrics && parent != null && thecomplainlist.Count > 0)
            {
                var result = "Metrics for " + currentName + @"\n";
                thecomplainlist.ForEach(s => result += s + @"\n");
                BaseCodeActivity.AddTextNode(result, parent);
            }

            return(thecomplainlist.Count);
        }
        /// <summary>
        /// Executes the logic for this workflow activity
        /// </summary>
        protected override void InternalExecute()
        {
            this.logCodeMetrics = this.LogCodeMetrics.Get(this.ActivityContext);
            this.BuildDetail    = this.ActivityContext.GetExtension <IBuildDetail>();
            string generatedFile = "Metrics.xml";

            string outputLocation = this.BuildDetail.DropLocation;

            if (string.IsNullOrEmpty(outputLocation))
            {
                outputLocation = this.BinariesDirectory.Get(this.ActivityContext);
            }

            if (this.GeneratedFileName != null && !string.IsNullOrEmpty(this.GeneratedFileName.Get(this.ActivityContext)))
            {
                generatedFile = Path.Combine(outputLocation, this.GeneratedFileName.Get(this.ActivityContext));
            }

            if (!this.RunCodeMetrics(generatedFile))
            {
                return;
            }

            IActivityTracking currentTracking = this.ActivityContext.GetExtension <IBuildLoggingExtension>().GetActivityTracking(this.ActivityContext);

            if (!this.AnalyzeMetricsResult.Get(this.ActivityContext))
            {
                BaseCodeActivity.AddTextNode("Skipped code metrics analysis (not set to run)", currentTracking.Node);
                return;
            }

            IBuildInformationNode rootNode = AddTextNode("Analyzing code metrics results", currentTracking.Node);

            string fileName = Path.GetFileName(generatedFile);
            string pathToFileInDropFolder = Path.Combine(outputLocation, fileName);

            BaseCodeActivity.AddLinkNode(fileName, new Uri(pathToFileInDropFolder), rootNode);

            CodeMetricsReport result = CodeMetricsReport.LoadFromFile(generatedFile);

            if (result == null)
            {
                this.LogBuildMessage("Could not load metric result file ");
                return;
            }

            // Get thresholds for each level.
            var memberMetricThresholds = new MethodMetricsThresholds(this);
            var typeMetricThresholds   = new TypeMetricsThresholds(this, memberMetricThresholds);

            // var namespaceMetricThresholds = new NameSpaceMetricsThresholds(this);  //Uncomment in this if you want to perform metric checks on namespaces
            // var assemblyMetricThresholds = new AssemblyMetricsThresholds(this);  // Uncomment in this if you want to perform metric checks on assemblies
            int noOfTypeViolations   = 0;
            int noOfMethodViolations = 0;

            foreach (var target in result.Targets)
            {
                var targetNode = this.logCodeMetrics ? AddTextNode("Target: " + target.Name, rootNode) : null;
                foreach (var module in target.Modules)
                {
                    var moduleNode = this.logCodeMetrics ? AddTextNode("Module: " + module.Name, targetNode) : null;

                    foreach (var ns in module.Namespaces)
                    {
                        var namespaceNode = this.logCodeMetrics ? AddTextNode("Namespace: " + ns.Name, moduleNode) : null;

                        foreach (var type in ns.Types)
                        {
                            var typeNode        = this.logCodeMetrics ? AddTextNode("Type: " + type.Name, namespaceNode) : null;
                            var typeInformation = new MemberInformation(null, type, ns, module);
                            noOfTypeViolations   += this.ProcessMetrics(typeNode, typeInformation.TheClass.Metrics, typeMetricThresholds, typeInformation.FullyQualifiedName, typeInformation.TheClass.Name);
                            noOfMethodViolations += (from member in type.Members let memberNode = this.logCodeMetrics ? AddTextNode("Member: " + member.Name + " " + member.MetricsInformation, typeNode) : null let memberInformation = new MemberInformation(member, type, ns, module) select this.ProcessMetrics(memberNode, memberInformation.TheMember.Metrics, memberMetricThresholds, memberInformation.FullyQualifiedName, memberInformation.TheMember.Name)).Sum();
                        }
                    }
                }
            }

            var numberMessageTypes   = string.Format("Number of Code Metric warnings/errors on types: {0}", noOfTypeViolations);
            var numberMessageMethods = string.Format("Number of Code Metric warnings/errors on methods: {0}", noOfMethodViolations);

            BaseCodeActivity.AddTextNode(numberMessageTypes, rootNode);
            BaseCodeActivity.AddTextNode(numberMessageMethods, rootNode);
        }