/// <summary>
		/// Constructor for IVSOutput2 implementation
		/// </summary>
		/// <param name="projectManager">Project that produce this output</param>
		/// <param name="outputAssembly">MSBuild generated item corresponding to the output assembly (by default, these would be of type MainAssembly</param>
		public Output(ProjectNode projectManager, ProjectElement outputAssembly)
		{
			if(projectManager == null)
				throw new ArgumentNullException("projectManager");
			if(outputAssembly == null)
				throw new ArgumentNullException("outputAssembly");

			project = projectManager;
			output = outputAssembly;
		}
		/// <summary>
		/// Constructor for the DependentFileNode
		/// </summary>
		/// <param name="root">Root of the hierarchy</param>
		/// <param name="e">Associated project element</param>
		public DependentFileNode(ProjectNode root, ProjectElement element)
			: base(root, element)
		{
			this.HasParentNodeNameRelation = false;
		}
		/// <summary>
		/// constructor for the ReferenceNode
		/// </summary>
		protected ReferenceNode(ProjectNode root)
			: base(root)
		{
			this.ExcludeNodeFromScc = true;
		}
		/// <summary>
		/// Constructor for the FileNode
		/// </summary>
		/// <param name="root">Root of the hierarchy</param>
		/// <param name="e">Associated project element</param>
		public FileNode(ProjectNode root, ProjectElement element)
			: base(root, element)
		{
			if(this.ProjectMgr.NodeHasDesigner(this.ItemNode.GetMetadata(ProjectFileConstants.Include)))
			{
				this.HasDesigner = true;
			}
		}
		public ProjectNodeProperties(ProjectNode node)
			: base(node)
		{
		}
		internal TrackDocumentsHelper(ProjectNode project)
		{
			this.projectMgr = project;
		}
		/// <summary>
		/// Calling this method remove this item from the project file.
		/// Once the item is delete, you should not longer be using it.
		/// Note that the item should be removed from the hierarchy prior to this call.
		/// </summary>
		public void RemoveFromProjectFile()
		{
			if(!deleted && item != null)
			{
				deleted = true;
				itemProject.BuildProject.RemoveItem(item);
			}
			itemProject = null;
			item = null;
		}
		/// <summary>
		/// Constructor for the AssemblyReferenceNode
		/// </summary>
		public AssemblyReferenceNode(ProjectNode root, string assemblyPath)
			: base(root)
		{
			// Validate the input parameters.
			if(null == root)
			{
				throw new ArgumentNullException("root");
			}
			if(string.IsNullOrEmpty(assemblyPath))
			{
				throw new ArgumentNullException("assemblyPath");
			}

			this.InitializeFileChangeEvents();

			// The assemblyPath variable can be an actual path on disk or a generic assembly name.
			if(File.Exists(assemblyPath))
			{
				// The assemblyPath parameter is an actual file on disk; try to load it.
				this.assemblyName = System.Reflection.AssemblyName.GetAssemblyName(assemblyPath);
				this.assemblyPath = assemblyPath;

				// We register with listeningto chnages onteh path here. The rest of teh cases will call into resolving the assembly and registration is done there.
				this.fileChangeListener.ObserveItem(this.assemblyPath);
			}
			else
			{
				// The file does not exist on disk. This can be because the file / path is not
				// correct or because this is not a path, but an assembly name.
				// Try to resolve the reference as an assembly name.
				this.CreateFromAssemblyName(new System.Reflection.AssemblyName(assemblyPath));
			}
		}
		public BuildDependency(ProjectNode projectMgr, Guid projectReference)
		{
			this.referencedProjectGuid = projectReference;
			this.projectMgr = projectMgr;
		}
		/// <summary>
		/// constructor for the ProjectReferenceNode
		/// </summary>
		public ProjectReferenceNode(ProjectNode root, string referencedProjectName, string projectPath, string projectReference)
			: base(root)
		{
			Debug.Assert(root != null && !String.IsNullOrEmpty(referencedProjectName) && !String.IsNullOrEmpty(projectReference)
				&& !String.IsNullOrEmpty(projectPath), "Can not add a reference because the input for adding one is invalid.");
			this.referencedProjectName = referencedProjectName;

			int indexOfSeparator = projectReference.IndexOf('|');


			string fileName = String.Empty;

			// Unfortunately we cannot use the path part of the projectReference string since it is not resolving correctly relative pathes.
			if(indexOfSeparator != -1)
			{
				string projectGuid = projectReference.Substring(0, indexOfSeparator);
				this.referencedProjectGuid = new Guid(projectGuid);
				if(indexOfSeparator + 1 < projectReference.Length)
				{
					string remaining = projectReference.Substring(indexOfSeparator + 1);
					indexOfSeparator = remaining.IndexOf('|');

					if(indexOfSeparator == -1)
					{
						fileName = remaining;
					}
					else
					{
						fileName = remaining.Substring(0, indexOfSeparator);
					}
				}
			}

			Debug.Assert(!String.IsNullOrEmpty(fileName), "Can not add a project reference because the input for adding one is invalid.");

			// Did we get just a file or a relative path?
			Uri uri = new Uri(projectPath);

			string referenceDir = PackageUtilities.GetPathDistance(this.ProjectMgr.BaseURI.Uri, uri);

			Debug.Assert(!String.IsNullOrEmpty(referenceDir), "Can not add a project reference because the input for adding one is invalid.");

			string justTheFileName = Path.GetFileName(fileName);
			this.referencedProjectRelativePath = Path.Combine(referenceDir, justTheFileName);

			this.referencedProjectFullPath = Path.Combine(projectPath, justTheFileName);

			this.buildDependency = new BuildDependency(this.ProjectMgr, this.referencedProjectGuid);

		}
		/// <summary>
		/// Constructor for the ReferenceNode
		/// </summary>
		public AssemblyReferenceNode(ProjectNode root, ProjectElement element)
			: base(root, element)
		{
			this.GetPathNameFromProjectFile();

			this.InitializeFileChangeEvents();

			string include = this.ItemNode.GetMetadata(ProjectFileConstants.Include);

			this.CreateFromAssemblyName(new System.Reflection.AssemblyName(include));
		}
		public ProjectReferenceNode(ProjectNode root, ProjectElement element)
			: base(root, element)
		{
			this.referencedProjectRelativePath = this.ItemNode.GetMetadata(ProjectFileConstants.Include);
			Debug.Assert(!String.IsNullOrEmpty(this.referencedProjectRelativePath), "Could not retrive referenced project path form project file");

			string guidString = this.ItemNode.GetMetadata(ProjectFileConstants.Project);

			// Continue even if project setttings cannot be read.
			try
			{
				this.referencedProjectGuid = new Guid(guidString);

				this.buildDependency = new BuildDependency(this.ProjectMgr, this.referencedProjectGuid);
				this.ProjectMgr.AddBuildDependency(this.buildDependency);
			}
			finally
			{
				Debug.Assert(this.referencedProjectGuid != Guid.Empty, "Could not retrive referenced project guidproject file");

				this.referencedProjectName = this.ItemNode.GetMetadata(ProjectFileConstants.Name);

				Debug.Assert(!String.IsNullOrEmpty(this.referencedProjectName), "Could not retrive referenced project name form project file");
			}

			Uri uri = new Uri(this.ProjectMgr.BaseURI.Uri, this.referencedProjectRelativePath);

			if(uri != null)
			{
				this.referencedProjectFullPath = Microsoft.VisualStudio.Shell.Url.Unescape(uri.LocalPath, true);
			}
		}
		public ReferenceContainerNode(ProjectNode root)
			: base(root)
		{
			this.VirtualNodeName = ReferencesNodeVirtualName;
			this.ExcludeNodeFromScc = true;
		}
		/// <summary>
		/// Constructor to create a new MSBuild.BuildItem and add it to the project
		/// Only have internal constructors as the only one who should be creating
		/// such object is the project itself (see Project.CreateFileNode()).
		/// </summary>
		internal ProjectElement(ProjectNode project, string itemPath, string itemType)
		{
			if(project == null)
			{
				throw new ArgumentNullException("project");
			}

			if(String.IsNullOrEmpty(itemPath))
			{
				throw new ArgumentException(SR.GetString(SR.ParameterCannotBeNullOrEmpty, CultureInfo.CurrentUICulture), "itemPath");
			}


			if(String.IsNullOrEmpty(itemType))
			{
				throw new ArgumentException(SR.GetString(SR.ParameterCannotBeNullOrEmpty, CultureInfo.CurrentUICulture), "itemType");
			}

			this.itemProject = project;

			// create and add the item to the project

			this.item = project.BuildProject.AddNewItem(itemType, Microsoft.Build.BuildEngine.Utilities.Escape(itemPath));
			this.itemProject.SetProjectFileDirty(true);
			this.RefreshProperties();
		}
		public NestedProjectNode(ProjectNode root, ProjectElement element)
			: base(root, element)
		{
			this.IsExpanded = true;
		}
		public virtual void SetObjects(uint count, object[] punk)
		{
			if(count > 0)
			{
				if(punk[0] is ProjectConfig)
				{
					ArrayList configs = new ArrayList();

					for(int i = 0; i < count; i++)
					{
						ProjectConfig config = (ProjectConfig)punk[i];

						if(this.project == null)
						{
							this.project = config.ProjectMgr;
						}

						configs.Add(config);
					}

					this.projectConfigs = (ProjectConfig[])configs.ToArray(typeof(ProjectConfig));
				}
				else if(punk[0] is NodeProperties)
				{
					if(this.project == null)
					{
						this.project = (punk[0] as NodeProperties).Node.ProjectMgr;
					}

					System.Collections.Generic.Dictionary<string, ProjectConfig> configsMap = new System.Collections.Generic.Dictionary<string, ProjectConfig>();

					for(int i = 0; i < count; i++)
					{
						NodeProperties property = (NodeProperties)punk[i];
						IVsCfgProvider provider;
						ErrorHandler.ThrowOnFailure(property.Node.ProjectMgr.GetCfgProvider(out provider));
						uint[] expected = new uint[1];
						ErrorHandler.ThrowOnFailure(provider.GetCfgs(0, null, expected, null));
						if(expected[0] > 0)
						{
							ProjectConfig[] configs = new ProjectConfig[expected[0]];
							uint[] actual = new uint[1];
							ErrorHandler.ThrowOnFailure(provider.GetCfgs(expected[0], configs, actual, null));

							foreach(ProjectConfig config in configs)
							{
								if(!configsMap.ContainsKey(config.ConfigName))
								{
									configsMap.Add(config.ConfigName, config);
								}
							}
						}
					}

					if(configsMap.Count > 0)
					{
						if(this.projectConfigs == null)
						{
							this.projectConfigs = new ProjectConfig[configsMap.Keys.Count];
						}
						configsMap.Values.CopyTo(this.projectConfigs, 0);
					}
				}
			}
			else
			{
				this.project = null;
			}

			if(this.active && this.project != null)
			{
				UpdateObjects();
			}
		}
		public ConfigProvider(ProjectNode manager)
		{
			this.project = manager;
		}
		public string GetFileNamespace(string fileFullPath, ProjectNode node)
		{
			// Get base namespace from the project
			string namespce = node.GetProjectProperty("RootNamespace");
			if(String.IsNullOrEmpty(namespce))
				namespce = Path.GetFileNameWithoutExtension(fileFullPath); ;

			// If the item is added to a subfolder, the name space should reflect this.
			// This is done so that class names from 2 files with the same name but different
			// directories don't conflict.
			string relativePath = Path.GetDirectoryName(fileFullPath);
			string projectPath = Path.GetDirectoryName(node.GetMkDocument());
			// Our project system only support adding files that are sibling of the project file or that are in subdirectories.
			if(String.Compare(projectPath, 0, relativePath, 0, projectPath.Length, true, CultureInfo.CurrentCulture) == 0)
			{
				relativePath = relativePath.Substring(projectPath.Length);
			}
			else
			{
				Debug.Fail("Adding an item to the project that is NOT under the project folder.");
				// We are going to use the full file path for generating the namespace
			}

			// Get the list of parts
			int index = 0;
			string[] pathParts;
			pathParts = relativePath.Split(Path.DirectorySeparatorChar);

			// Use a string builder with default size being the expected size
			StringBuilder result = new StringBuilder(namespce, namespce.Length + relativePath.Length + 1);
			// For each path part
			while(index < pathParts.Length)
			{
				string part = pathParts[index];
				++index;

				// This could happen if the path had leading/trailing slash, we want to ignore empty pieces
				if(String.IsNullOrEmpty(part))
					continue;

				// If we reach here, we will be adding something, so add a namespace separator '.'
				result.Append('.');

				// Make sure it starts with a letter
				if(!char.IsLetter(part, 0))
					result.Append('N');

				// Filter invalid namespace characters
				foreach(char c in part)
				{
					if(char.IsLetterOrDigit(c))
						result.Append(c);
				}
			}
			return result.ToString();
		}
		public ProjectDesignerDocumentManager(ProjectNode node)
			: base(node)
		{
		}
		/// <summary>
		/// Constructor to Wrap an existing MSBuild.BuildItem
		/// Only have internal constructors as the only one who should be creating
		/// such object is the project itself (see Project.CreateFileNode()).
		/// </summary>
		/// <param name="project">Project that owns this item</param>
		/// <param name="existingItem">an MSBuild.BuildItem; can be null if virtualFolder is true</param>
		/// <param name="virtualFolder">Is this item virtual (such as reference folder)</param>
		internal ProjectElement(ProjectNode project, MSBuild.BuildItem existingItem, bool virtualFolder)
		{
			if(project == null)
				throw new ArgumentNullException("project");
			if(!virtualFolder && existingItem == null)
				throw new ArgumentNullException("existingItem");

			// Keep a reference to project and item
			this.itemProject = project;
			this.item = existingItem;
			this.isVirtual = virtualFolder;

			if(this.isVirtual)
				this.virtualProperties = new Dictionary<string, string>();
		}