PageRenderTime 40ms CodeModel.GetById 15ms app.highlight 16ms RepoModel.GetById 2ms app.codeStats 0ms

/V1/spikes/AGCompositeApplicationLibrary/AGComposite/Modularity/ModuleDependencySolver.cs

#
C# | 169 lines | 107 code | 20 blank | 42 comment | 16 complexity | 3f6cfa1dbe9900458b449311a865be4b MD5 | raw file
  1//===============================================================================
  2// Microsoft patterns & practices
  3// Composite Application Guidance for Windows Presentation Foundation and Silverlight
  4//===============================================================================
  5// Copyright (c) Microsoft Corporation.  All rights reserved.
  6// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
  7// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
  8// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  9// FITNESS FOR A PARTICULAR PURPOSE.
 10//===============================================================================
 11// The example companies, organizations, products, domain names,
 12// e-mail addresses, logos, people, places, and events depicted
 13// herein are fictitious.  No association with any real company,
 14// organization, product, domain name, email address, logo, person,
 15// places, or events is intended or should be inferred.
 16//===============================================================================
 17
 18using System;
 19using System.Collections.Generic;
 20using System.Globalization;
 21using Microsoft.Practices.Composite.Properties;
 22
 23namespace Microsoft.Practices.Composite.Modularity
 24{
 25    /// <summary>
 26    /// Used by <see cref="ModuleLoader"/> to get the load sequence
 27    /// for the modules to load according to their dependencies.
 28    /// </summary>
 29    public class ModuleDependencySolver
 30    {
 31        private readonly ListDictionary<string, string> dependencyMatrix = new ListDictionary<string, string>();
 32        private readonly List<string> knownModules = new List<string>();
 33
 34        /// <summary>
 35        /// Adds a module to the solver.
 36        /// </summary>
 37        /// <param name="name">The name that uniquely identifies the module.</param>
 38        public void AddModule(string name)
 39        {
 40            if (String.IsNullOrEmpty(name))
 41                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.StringCannotBeNullOrEmpty, "name"));
 42
 43            AddToDependencyMatrix(name);
 44            AddToKnownModules(name);
 45        }
 46
 47        /// <summary>
 48        /// Adds a module dependency between the modules specified by dependingModule and
 49        /// dependentModule.
 50        /// </summary>
 51        /// <param name="dependingModule">The name of the module with the dependency.</param>
 52        /// <param name="dependentModule">The name of the module dependingModule
 53        /// depends on.</param>
 54        public void AddDependency(string dependingModule, string dependentModule)
 55        {
 56            if (String.IsNullOrEmpty(dependingModule))
 57                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.StringCannotBeNullOrEmpty, "dependingModule"));
 58
 59            if (String.IsNullOrEmpty(dependentModule))
 60                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.StringCannotBeNullOrEmpty, "dependentModule"));
 61
 62            if (!knownModules.Contains(dependingModule))
 63                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.DependencyForUnknownModule, dependingModule));
 64
 65            AddToDependencyMatrix(dependentModule);
 66            dependencyMatrix.Add(dependentModule, dependingModule);
 67        }
 68
 69        private void AddToDependencyMatrix(string module)
 70        {
 71            if (!dependencyMatrix.ContainsKey(module))
 72            {
 73                dependencyMatrix.Add(module);
 74            }
 75        }
 76
 77        private void AddToKnownModules(string module)
 78        {
 79            if (!knownModules.Contains(module))
 80            {
 81                knownModules.Add(module);
 82            }
 83        }
 84
 85        /// <summary>
 86        /// Calculates an ordered vector according to the defined dependencies.
 87        /// Non-dependant modules appears at the beginning of the resulting array.
 88        /// </summary>
 89        /// <returns>The resulting ordered list of modules.</returns>
 90        /// <exception cref="CyclicDependencyFoundException">This exception is thrown
 91        /// when a cycle is found in the defined depedency graph.</exception>
 92        public string[] Solve()
 93        {
 94            List<string> skip = new List<string>();
 95            while (skip.Count < dependencyMatrix.Count)
 96            {
 97                List<string> leaves = this.FindLeaves(skip);
 98                if (leaves.Count == 0 && skip.Count < dependencyMatrix.Count)
 99                {
100                    throw new CyclicDependencyFoundException();
101                }
102                skip.AddRange(leaves);
103            }
104            skip.Reverse();
105
106            if (skip.Count > knownModules.Count)
107            {
108                throw new ModuleLoadException(String.Format(CultureInfo.CurrentCulture,
109                                                            Resources.DependencyOnMissingModule,
110                                                            FindMissingModules(skip)));
111            }
112
113            return skip.ToArray();
114        }
115
116        private string FindMissingModules(List<string> skip)
117        {
118            string missingModules = "";
119
120            foreach (string module in skip)
121            {
122                if (!knownModules.Contains(module))
123                {
124                    missingModules += ", ";
125                    missingModules += module;
126                }
127            }
128
129            return missingModules.Substring(2);
130        }
131
132        /// <summary>
133        /// Gets the number of modules added to the solver.
134        /// </summary>
135        /// <value>The number of modules.</value>
136        public int ModuleCount
137        {
138            get { return dependencyMatrix.Count; }
139        }
140
141        private List<string> FindLeaves(List<string> skip)
142        {
143            List<string> result = new List<string>();
144
145            foreach (string precedent in dependencyMatrix.Keys)
146            {
147                if (skip.Contains(precedent))
148                {
149                    continue;
150                }
151
152                int count = 0;
153                foreach (string dependent in dependencyMatrix[precedent])
154                {
155                    if (skip.Contains(dependent))
156                    {
157                        continue;
158                    }
159                    count++;
160                }
161                if (count == 0)
162                {
163                    result.Add(precedent);
164                }
165            }
166            return result;
167        }
168    }
169}