vbAccelerator - Contents of code file: Solution.cs

using System;
using System.IO;
using System.Text;
using System.Collections;
using System.Xml;

namespace NetProjectZip
{

   #region ProjectFile
   public class ProjectFile
   {
      private string relPath = "";
      private string basePath = "";
      private string buildAction = "";
      private string subType = "";

      public string AbsolutePath
      {
         get
         {
            return Path.Combine(basePath, relPath);
         }
      }
      public string AbsoluteDirectory
      {
         get
         {
            return Path.GetDirectoryName(Path.Combine(basePath, relPath));
         }
      } 

      public string RelativePath
      {
         get
         {
            return relPath;
         }
      }

      public string BasePath
      {
         get
         {
            return basePath;
         }
      }
      public string BuildAction
      {
         get
         {
            return buildAction;
         }
      }
      public string SubType
      {
         get
         {
            return subType;
         }
      }

      public override string ToString()
      {
         StringBuilder buff = new StringBuilder("\nProject File:");
         buff.Append("\n\tRelativePath:");
         buff.Append(relPath);
         buff.Append("\n\tBuildAction:");
         buff.Append(buildAction);
         buff.Append("\n\tSubType:");
         buff.Append(subType);
         buff.Append("\n\tBasePath:");
         buff.Append(basePath);
         return buff.ToString();
      }

      public ProjectFile(
         string relPath,
         string buildAction,
         string subType,
         string basePath)
      {
         this.relPath = relPath;
         this.buildAction = buildAction;
         this.subType = subType;
         this.basePath = basePath;
      }
   }
   #endregion

   #region ProjectFileCollection
   public class ProjectFileCollection : ReadOnlyCollectionBase
   {
      public ProjectFile this[int index]
      {
         get
         {
            return (ProjectFile)this.InnerList[index];
         }
      }

      public override string ToString()
      {
         StringBuilder buff = new StringBuilder();
         buff.Append("\nProjectFileCollection");
         foreach (ProjectFile pf in this.InnerList)
         {
            buff.Append(pf.ToString());
         }
         return buff.ToString();
      }
      
      public ProjectFileCollection(ProjectFile[] projectFileArray)
      {
         foreach (ProjectFile projectFile in projectFileArray)
         {
            this.InnerList.Add(projectFile);
         }
      }


   }
   #endregion

   #region ProjectReference
   public class ProjectReference
   {
      private string name = "";
      private string assemblyName = "";
      private string hintPath = "";
      private string basePath = "";

      public string Name
      {
         get
         {
            return this.name;

         }
      }
      public string AssemblyName
      {
         get
         {
            return this.assemblyName;
         }
      }
      public string HintPath
      {
         get
         {
            return this.hintPath;
         }
      }
      public string AbsolutePath
      {
         get
         {
            return Path.Combine(this.basePath, this.hintPath);
         }
      }

      public string BasePath
      {
         get
         {
            return this.basePath;
         }
      }
      public override string ToString()
      {
         StringBuilder buff = new StringBuilder("\nReference:");
         buff.Append("\n\tName");
         buff.Append(name);
         buff.Append("\n\tAssemblyName");
         buff.Append(assemblyName);
         buff.Append("\n\tHintPath:");
         buff.Append(hintPath);
         buff.Append("\n\tBasePath:");
         buff.Append(basePath);
         return buff.ToString();
      }

      public ProjectReference(string name,
         string assemblyName,
         string hintPath,
         string basePath)
      {
         this.name = name;
         this.assemblyName = assemblyName;
         this.hintPath = hintPath;
         this.basePath = basePath;
      }

   }
   #endregion

   #region ProjectReferenceCollection
   public class ProjectReferenceCollection : ReadOnlyCollectionBase
   {
      public ProjectReference this[int index]
      {
         get
         {
            return (ProjectReference)this.InnerList[index];
         }
      }

      public override string ToString()
      {
         StringBuilder buff = new StringBuilder();
         buff.Append("\nProjectReferenceCollection");
         foreach (ProjectReference pr in this.InnerList)
         {
            buff.Append(pr.ToString());
         }
         return buff.ToString();
      }
      
      public ProjectReferenceCollection(ProjectReference[]
       projectReferenceArray)
      {
         foreach (ProjectReference projectReference in projectReferenceArray)
         {
            this.InnerList.Add(projectReference);
         }
      }

   }
   #endregion

   #region ProjectConfigItem
   public class ProjectConfigItem
   {
      private string key = "";
      private string keyValue = "";

      public string Key
      {
         get
         {
            return key;
         }
      }
      public string Value
      {
         get
         {
            return keyValue;
         }
      }
      
      public override string ToString()
      {
         StringBuilder buff = new StringBuilder();
         buff.Append("\nProjectConfigItem:");
         buff.Append("\n\tKey:");
         buff.Append(key);
         buff.Append("\n\tValue:");
         buff.Append(keyValue);
         return buff.ToString();
      }

      public ProjectConfigItem(string key, string keyValue)
      {
         this.key = key;
         this.keyValue = keyValue;

      }
   }
   #endregion

   #region ProjectConfigItemCollection
   public class ProjectConfigItemCollection : ReadOnlyCollectionBase
   {
      private string basePath = "";

      public string Name
      {
         get
         {
            string name = "";
            foreach (ProjectConfigItem pc in this.InnerList)
            {
               if (pc.Key.Equals("Name"))
               {
                  name = pc.Value;
                  break;
               }
            }
            return name;
         }
      }

      public string OutputRelPath
      {
         get
         {
            string relPath = "";
            foreach (ProjectConfigItem pc in this.InnerList)
            {
               if (pc.Key.Equals("OutputPath"))
               {
                  relPath = pc.Value;
                  break;
               }
            }
            return relPath;
         }
      }
      
      public string OutputAbsolutePath
      {
         get
         {
            string absPath = OutputRelPath;
            absPath = Path.Combine(this.basePath, absPath);
            return absPath.Replace("\\.\\", "");
         }
      }

      public ProjectConfigItem this[int index]
      {
         get
         {
            return (ProjectConfigItem)this.InnerList[index];
         }
      }

      public override string ToString()
      {
         StringBuilder buff = new StringBuilder();
         buff.Append("\nProjectConfigItemCollection:");
         foreach (ProjectConfigItem pc in this.InnerList)
         {
            buff.Append(pc.ToString());
         }
         return buff.ToString();
      }

      public ProjectConfigItemCollection(ProjectConfigItem[]
       projectConfigItemArray, string basePath)
      {
         this.basePath = basePath;
         foreach(ProjectConfigItem pc in projectConfigItemArray)
         {
            this.InnerList.Add(pc);
         }
   
      }
   }
   #endregion

   #region ProjectConfigCollection
   public class ProjectConfigCollection : ReadOnlyCollectionBase
   {
      public override string ToString()
      {
         StringBuilder buff = new StringBuilder();
         buff.Append("\nProjectConfigCollection:");
         foreach (ProjectConfigItemCollection pc in this.InnerList)
         {
            buff.Append(pc.ToString());
         }
         return buff.ToString();
      }

      public ProjectConfigItemCollection this[int index]
      {
         get
         {
            return (ProjectConfigItemCollection)this.InnerList[index];
         }
      }

      public ProjectConfigCollection(XmlNodeList configItems, string basePath)
      {
         if (configItems.Count > 0)
         {
            foreach (XmlNode configItem in configItems)
            {
               // create an array of items:
               ProjectConfigItem[] projectConfigItemArray = new
                ProjectConfigItem[configItem.Attributes.Count];
               int i =0;
               foreach (XmlAttribute attrib in configItem.Attributes)
               {
                  projectConfigItemArray[i] = new
                   ProjectConfigItem(attrib.Name, attrib.Value);
                  i++;
               }
               // create a ProjectConfigItemCollection:
               ProjectConfigItemCollection projectConfigItemCollection = new
                ProjectConfigItemCollection(projectConfigItemArray, basePath);
               this.InnerList.Add(projectConfigItemCollection);
            }            
         }         
      }
   }
   #endregion

   #region Project
   public class Project
   {
      private string basePath = "";
      private string projectBasePath = "";
      private string projectFileName = "";
      private string projectGuid = "";
      private string projectConfigurationGuid = "";
      private string projectName = "";
      private string projectType = "";
      private ProjectConfigCollection configCollection = null;
      private ProjectReferenceCollection referenceCollection = null;
      private ProjectFileCollection fileCollection = null;

      public string AbsolutePath
      {
         get
         {
            return Path.Combine(basePath, projectFileName);
         }
      }

      public string AbsoluteDirectory
      {
         get
         {
            return basePath;
         }
      }

      public ProjectConfigCollection Configurations
      {
         get
         {
            return configCollection;
         }
      }
      public ProjectReferenceCollection ReferenceCollection 
      {
         get
         {
            return referenceCollection;
         }
      }
      public ProjectFileCollection FileCollection
      {
         get
         {
            return fileCollection;
         }
      }

      public string RelPath
      {
         get
         {
            return projectFileName;
         }
      }
      
      public string Guid
      {
         get
         {
            return projectGuid;
         }
      }

      public string ConfigurationGuid
      {
         get
         {
            return projectConfigurationGuid;
         }
      }

      public string Name
      {
         get
         {
            return projectName;
         }
      }

      public string ProjectType
      {
         get
         {
            return projectType;
         }
      }

      public override string ToString()
      {
         StringBuilder buff = new StringBuilder();
         buff.Append("\nProject:");
         buff.Append("\n\tName:");
         buff.Append(projectName);
         buff.Append("\n\tFileName:");
         buff.Append(projectFileName);
         buff.Append("\n\tBasePath:");
         buff.Append(basePath);
         buff.Append("\n\tGuid:");
         buff.Append(projectGuid);
         buff.Append("\nConfiguration:");
         buff.Append(configCollection.ToString());
         buff.Append("\nReferences:");
         buff.Append(referenceCollection.ToString());
         buff.Append("\nFiles:");
         buff.Append(fileCollection.ToString());
         return buff.ToString();
      }

      private void ParseConfig(XmlNodeList configItems)
      {
         configCollection = new ProjectConfigCollection(configItems,
          Path.GetDirectoryName(this.AbsolutePath));
      }

      private void ParseReference(XmlNodeList referenceItems)
      {
         ProjectReference[] prArray = new
          ProjectReference[referenceItems.Count];
         int i = 0;
         foreach(XmlNode reference in referenceItems)
         {
            string name = "";
            string assemblyName = "";
            string hintPath = "";
            foreach (XmlAttribute attrib in reference.Attributes)
            {
               switch (attrib.Name)
               {
                  case "Name":
                     name = attrib.Value;
                     break;
                  case "AssemblyName":
                     assemblyName = attrib.Value;
                     break;
                  case "HintPath":
                     hintPath = attrib.Value;
                     break;                  
               }
            }
            ProjectReference pr = new ProjectReference(name, assemblyName,
             hintPath, Path.GetDirectoryName(this.AbsolutePath));
            prArray[i] = pr;
            i++;
         }
         referenceCollection = new ProjectReferenceCollection(prArray);
      }

      private void ParseFile(XmlNodeList fileList)
      {
         ProjectFile[] pf = new ProjectFile[fileList.Count];
         int i = 0;
         foreach(XmlNode file in fileList)
         {
            string relPath = "";
            string buildAction = "";
            string subType = "Other";
            string dependentUpon = "";
            foreach (XmlAttribute attrib in file.Attributes)
            {
               switch (attrib.Name)
               {
                  case "RelPath":
                     relPath = attrib.Value;
                     break;
                  case "RelativePath":
                     relPath = attrib.Value;
                     break;
                  case "BuildAction":
                     buildAction = attrib.Value;
                     break;
                  case "SubType":
                     subType = attrib.Value;
                     break;
                  case "DependentUpon":
                      dependentUpon = attrib.Value;
                     break;
               }
            }
            pf[i] = new ProjectFile(relPath, buildAction, subType,
             Path.GetDirectoryName(this.AbsolutePath));
            i ++;
         }
         fileCollection = new ProjectFileCollection(pf);
      }

      private void Load()
      {
         string absPath = Path.Combine(basePath, projectFileName);
         projectBasePath = Path.GetDirectoryName(absPath);
         
         // a project file is relatively small so we use an XmlDocument to load
          it
         XmlDocument doc = new XmlDocument();

         FileStream fs = new FileStream(projectFileName, FileMode.Open,
          FileAccess.Read, FileShare.Read);
         StreamReader tr = new StreamReader(fs);
         XmlTextReader reader = new XmlTextReader(tr);
         doc.Load(reader);         

         // build
         ParseConfig(doc.SelectNodes("//Config"));

         // references
         ParseReference(doc.SelectNodes("//Reference"));

         // files
         ParseFile(doc.SelectNodes("//File"));

         tr.Close();         
      }

      // protected constructor provided in case you want to override the class:
      protected Project(
         string projectName, 
         string projectGuid, 
         string projectFileName, 
         string projectConfigurationGuid)
      {
         this.projectName = projectName;
         this.projectGuid = projectGuid;
         this.projectFileName = projectFileName;
         this.projectConfigurationGuid = projectConfigurationGuid;
      }

      // internal constructor builds directly from a project file:
      internal Project(
         string projectFileName
         )
      {
         this.projectName = Path.GetFileNameWithoutExtension(projectFileName);
         this.projectGuid = "";
         this.projectFileName = projectFileName;
         projectFileName = projectFileName.Replace("http://localhost/", "");
         this.projectConfigurationGuid = "";
         basePath = Path.GetDirectoryName(projectFileName);
         Load();
      }


      // internal constructor builds from the actual project:
      internal Project(string solutionPath, string solutionLine)
      {
         string[] parts = solutionLine.Split(new char[] {'='}, 2);
         if (parts.Length == 2)
         {
            // parts[0] == FileName:Project{"[project guid)"}
            // parts[1] == "[Name]", "[Path]", "[Configuration Guid]"

            // parse part 0:
            int iPos = parts[0].IndexOf("\"");
            if (iPos > -1)
            {
               int iPos2 = parts[0].Substring(iPos+1).IndexOf("\"");
               if (iPos2 > -1)
               {
                  projectGuid = parts[0].Substring(iPos + 1, iPos2 - iPos - 1);

                  // parse part 1:
                  string[] parts2 = parts[1].Split(new char[] {','});
                  if (parts2.Length >= 3)
                  {
                     projectName = parts2[0].Replace("\"","").Trim();
                     projectFileName = parts2[1].Replace("\"","").Trim();
                     projectFileName =
                      projectFileName.Replace("http://localhost/", "");
                     projectConfigurationGuid =
                      parts2[2].Replace("\"","").Trim();
                  }
                  basePath = solutionPath;

                  Load();
               }
            }
         }
      }
   }
   #endregion

   #region ProjectCollection
   public class ProjectCollection : ReadOnlyCollectionBase
   {
      public Project this[int index]
      {
         get
         {
            return (Project)this.InnerList[index];
         }
      }

      public override string ToString()
      {
         StringBuilder buff = new StringBuilder();
         buff.Append("\nProject Collection:");         
         foreach (Project p in this.InnerList)
         {
            buff.Append(p.ToString());
         }
         return buff.ToString();
      }
      
      public ProjectCollection(Project[] projects)
      {
         foreach (Project project in projects)
         {
            this.InnerList.Add(project);
         }
      }

   }
   #endregion

   #region Solution
   public class Solution
   {
      private string solutionFileName = "";
      private string solutionDirectory = "";
      private string solutionFileVersion = "";
      private ProjectCollection projectCollection = null;

      public string LongestSharedPath
      {
         get
         {
            // find the longest path which is shared by all of the 
            // objects in the project (if any)
            string longestSharedPath = solutionDirectory;
            foreach (Project p in projectCollection)
            {
               string projectDir = p.AbsoluteDirectory;
               longestSharedPath = getMinimumSharedPath(longestSharedPath,
                projectDir);
               foreach (ProjectFile pf in p.FileCollection)
               {
                  string fileDir = pf.AbsoluteDirectory;
                  longestSharedPath = getMinimumSharedPath(longestSharedPath,
                   fileDir);
               }
            }
            return longestSharedPath;
         }
      }

      private string getMinimumSharedPath(
         string sharedPath,
         string newPath
         )
      {
         string retSharedPath = "";
         if (sharedPath.Length > 0)
         {
            string[] sharedPathParts = sharedPath.Split(
               (new char[] {Path.DirectorySeparatorChar,
                Path.AltDirectorySeparatorChar }));
            string[] newPathParts = newPath.Split(
               (new char[] {Path.DirectorySeparatorChar,
                Path.AltDirectorySeparatorChar}));
            int max = Math.Min(sharedPathParts.Length, newPathParts.Length);
            int sharedCount = 0;
            for (int i = 0; i < max; i++)
            {
               if
                (!sharedPathParts[i].ToUpper().Equals(newPathParts[i].ToUpper())
               )
               {
                  break;
               }
               else
               {
                  sharedCount = i + 1;
               }
            }
            if (sharedCount == 0)
            {
               return "";
            }
            else
            {
               for (int i = 0; i < sharedCount; i++)
               {
                  if (retSharedPath.Length > 0)
                  {
                     retSharedPath += Path.DirectorySeparatorChar;
                  }
                  retSharedPath += sharedPathParts[i];
               }               
            }
         }
         return retSharedPath;
      }

      public string FileVersion
      {
         get
         {
            return solutionFileVersion;
         }
      }

      public ProjectCollection Projects
      {
         get
         {
            return projectCollection;
         }
      }

      public string FileName
      {
         get
         {
            return solutionFileName;
         }
         set
         {
            solutionFileName = value;
            Load();
         }
      }

      public string BasePath
      {
         get
         {
            return solutionDirectory;
         }
      }

      public override string ToString()
      {
         StringBuilder s = new StringBuilder();
         s.Append("\nSolution:");
         s.Append("\nFileName:");
         s.Append(solutionFileName);
         s.Append("\nVersion:");
         s.Append(solutionFileVersion);
         if (projectCollection != null)
         {
            s.Append(projectCollection.ToString());
         }
         return s.ToString();
      }

      private void Load()
      {
         solutionDirectory = "";
         solutionFileVersion = "";
         projectCollection = null;

         if (File.Exists(solutionFileName))
         {            
            solutionDirectory = Path.GetDirectoryName(solutionFileName);
            ArrayList pArray = new ArrayList();
            FileStream fs = new FileStream(solutionFileName, FileMode.Open,
             FileAccess.Read, FileShare.Read);
            StreamReader tr = new StreamReader(fs);
            int state = 0;
            Project p = null;
            bool fileIsProject = false;
            while (tr.Peek() != -1)
            {
               string line = tr.ReadLine();
               if (state == 0)
               {
                  if (line.StartsWith("Microsoft Visual Studio Solution File"))
                  {
                     int iPos = line.IndexOf(",");
                     if (iPos > 0)
                     {
                        solutionFileVersion = line.Substring(iPos + 1).Trim();
                     }
                     state = 1;
                  }                  
                  else if (line.StartsWith("<VisualStudioProject>"))
                  {
                     // this is actually a project file
                     fileIsProject = true;
                     break;
                  }
               }
               else if (state == 1)
               {
                  if (line.StartsWith("Project"))
                  {
                     p = new Project(solutionDirectory, line);
                     if (p != null)
                     {
                        pArray.Add(p);
                     }
                     state = 2;
                  }
               }
               else if (state == 2)
               {
                  if (line.StartsWith("EndProject"))
                  {
                     state = 1;
                  }
               }
            }
            tr.Close();
            
            if (p != null)
            {
               Project[] projects = (Project[])pArray.ToArray(p.GetType());
               projectCollection = new ProjectCollection(projects);
            }
            else if (fileIsProject)
            {
               Project[] projects = new Project[1];
               projects[0] = new Project(solutionFileName);
               projectCollection = new ProjectCollection(projects);
            }
         }
         else
         {
            solutionFileName = "";
         }
      }

      public Solution(string fileName)
      {
         solutionFileName = fileName;
         Load();
      }
   }
   #endregion
}