Example #1
0
        /// <summary>
        /// Method to display information about a particular node to the user.
        /// </summary>
        /// <param name="current">The Node whose information we want to display.</param>
        /// <returns>A string with information regarding the input node.</returns>
        private string GetNodeDetail(PartNode current)
        {
            string startMessage;

            if (current.IsRejectionExpected)
            {
                startMessage = Strings.RejectionExpectedLabel;
            }
            else
            {
                startMessage = string.Empty;
            }

            if (this.Options.Verbose)
            {
                StringWriter writer = new StringWriter(new StringBuilder());
                foreach (string errorMessage in current.VerboseMessages)
                {
                    string message = startMessage + errorMessage;
                    writer.WriteLine(message);
                    writer.WriteLine();
                }

                return(writer.ToString());
            }
            else
            {
                string message = startMessage + this.GetName(current.Part, Strings.VerbosePartLabel);
                return(message);
            }
        }
Example #2
0
        /// <summary>
        /// Method to indicate all the rejection issues present in a given level.
        /// </summary>
        /// <param name="currentLevel">An integer representing the level we are intrested in.</param>
        private void ListErrorsinLevel(int currentLevel)
        {
            string errorMessage = string.Format(
                CultureInfo.CurrentCulture,
                Strings.ErrorsLevelMessage,
                currentLevel);

            this.Options.Writer.WriteLine(errorMessage);
            List <string> currentErrors = new List <string>();

            foreach (var pair in this.RejectionGraph)
            {
                PartNode currentNode = pair.Value;
                if (currentNode.Level.Equals(currentLevel))
                {
                    currentErrors.Add(this.GetNodeDetail(currentNode));
                }
            }

            this.WriteLines(currentErrors);
            if (!this.Options.Verbose)
            {
                this.Options.Writer.WriteLine();
            }
        }
Example #3
0
 /// <summary>
 /// Method to add a node that the current node caused a rejection error in.
 /// </summary>
 /// <param name="node">The node that the current node caused the error in.</param>
 /// <param name="description">Label to use when visualizing the edge.</param>
 internal void AddParent(PartNode node, string description = "")
 => this.RejectsCaused.Add(new PartEdge(node, description));
Example #4
0
 /// <summary>
 /// Method to add a node that caused a rejection error in the current node.
 /// </summary>
 /// <param name="node">The node that is the cause of the error.</param>
 /// <param name="description">Label to use when visualizing the edge.</param>
 internal void AddChild(PartNode node, string description = "")
 => this.ImportRejects.Add(new PartEdge(node, description));
Example #5
0
        /// <summary>
        /// Method to initialize the part nodes and thier "pointers" based on the error
        /// stack from the config.
        /// </summary>
        private void GenerateNodeGraph()
        {
            // Get the error stack from the composition configuration
            var expectedRejectionsChecker   = new ExpectedRejections(this.Options);
            CompositionConfiguration config = this.Creator.Config !;
            var errors      = config.CompositionErrors;
            int levelNumber = 1;

            while (errors.Count() > 0)
            {
                // Process all the parts present in the current level of the stack
                var currentLevel = errors.Peek();
                foreach (var element in currentLevel)
                {
                    var part = element.Parts.First();

                    // Create a PartNode object from the definition of the current Part
                    ComposablePartDefinition definition = part.Definition;
                    string currentName = definition.Type.FullName !;
                    if (currentName == null)
                    {
                        continue;
                    }

                    if (this.RejectionGraph.ContainsKey(currentName))
                    {
                        this.RejectionGraph[currentName].AddErrorMessage(element.Message);
                        continue;
                    }

                    PartNode currentNode = new PartNode(definition, element.Message, levelNumber);
                    currentNode.IsRejectionExpected = expectedRejectionsChecker.IsRejectionExpected(currentName);
                    this.RejectionGraph.Add(currentName, currentNode);
                }

                // Get the next level of the stack
                errors       = errors.Pop();
                levelNumber += 1;
            }

            this.MaxLevels = levelNumber - 1;
            foreach (var nodePair in this.RejectionGraph)
            {
                var node            = nodePair.Value;
                var currentNodeName = node.Name;
                var nodeDefinition  = node.Part;

                // Get the imports for the current part to update the pointers associated with the current node
                foreach (var import in nodeDefinition.Imports)
                {
                    string importName = import.ImportingSiteType.FullName !;
                    if (importName == null || !this.RejectionGraph.ContainsKey(importName))
                    {
                        continue;
                    }

                    string importLabel = importName;
                    if (import.ImportingMember != null)
                    {
                        importLabel = import.ImportingMember.Name;
                    }

                    PartNode childNode = this.RejectionGraph[importName];
                    childNode.AddParent(node, importLabel);
                    node.AddChild(childNode, importLabel);
                }
            }
        }
Example #6
0
        /// <summary>
        /// Method to the get the information about the rejection information that caused a
        /// particular import failure, rather than for the entire system.
        /// If graph was specified in the input arguments then a DGML graph tracing the rejection
        /// chain assocaited with the current path alone is saved to a file called [partName].dgml.
        /// </summary>
        /// <param name = "partName"> The name of the part which we want to analyze.</param>
        /// <remarks>
        /// Once again, the root causes can easily be accessed by looking at the rejection
        /// issues at the highest levels of the output.
        /// </remarks>
        private void ListReject(string partName)
        {
            string individualRejection = string.Format(
                CultureInfo.CurrentCulture,
                Strings.IndividualRejectionMessage,
                partName);

            this.Options.Writer.WriteLine(individualRejection);

            // Deal with the case that there are no rejection issues with the given part
            if (!this.RejectionGraph.ContainsKey(partName))
            {
                string noRejection = string.Format(
                    CultureInfo.CurrentCulture,
                    Strings.NoRejectionMessage,
                    partName);
                this.Options.ErrorWriter.WriteLine(noRejection);
                return;
            }

            // Store just the nodes that are involved in the current rejection chain to use when generating the graph
            Dictionary <string, PartNode> relevantNodes = new Dictionary <string, PartNode>();
            bool saveGraph = this.Options.GraphPath != null && this.Options.GraphPath.Length > 0;

            // Perform Breadth First Search (BFS) with the node associated with partName as the root.
            // When performing BFS, only the child nodes are considered since we want to the root to be
            // the end point of the rejection chain(s).
            // BFS was chosen over DFS because of the fact that we process level by level when performing
            // the travesal and thus easier to communicate the causes and pathway to the end user
            Queue <PartNode> currentLevelNodes = new Queue <PartNode>();

            currentLevelNodes.Enqueue(this.RejectionGraph[partName]);
            while (currentLevelNodes.Count() > 0)
            {
                int    currentLevel = currentLevelNodes.Peek().Level;
                string errorLevel   = string.Format(
                    CultureInfo.CurrentCulture,
                    Strings.ErrorsLevelMessage,
                    currentLevel);
                this.Options.Writer.WriteLine(errorLevel);

                // Iterate through all the nodes in the current level
                int           numNodes      = currentLevelNodes.Count();
                List <string> errorMessages = new List <string>(numNodes);
                for (int index = 0; index < numNodes; index++)
                {
                    // Process the current node by displaying its import issue and adding it to the graph
                    PartNode current = currentLevelNodes.Dequeue();
                    if (saveGraph)
                    {
                        relevantNodes.Add(current.Name, current);
                    }

                    errorMessages.Add(this.GetNodeDetail(current));

                    // Add the "children" of the current node to the queue for future processing
                    if (current.ImportRejects.Count() > 0)
                    {
                        foreach (var childEdge in current.ImportRejects)
                        {
                            currentLevelNodes.Enqueue(childEdge.Target);
                        }
                    }
                }

                this.WriteLines(errorMessages);
                if (!this.Options.Verbose)
                {
                    this.Options.Writer.WriteLine();
                }
            }

            // Save the output graph if the user request it
            if (saveGraph)
            {
                GraphCreator nodeGraph = new GraphCreator(relevantNodes);

                // Replacing '.' with '_' in the fileName to ensure that the '.' is associated with the file extension
                string fileName = partName.Replace(".", "_") + ".dgml";
                this.SaveGraph(fileName, nodeGraph);
            }
        }