private bool ExtractEstimate(string line, int length, DebtInfo debtInfo)
		{
			double estimate;
			bool validToken = double.TryParse(line.Substring(0, length).Trim(), out estimate);
			if (validToken)
				debtInfo.Estimate = estimate;
			return validToken;
		}
		private bool ExtractComments(string line, int length, DebtInfo debtInfo)
		{
			//We extract whatever remains as the comment.
			int start = 0;
			for (int i = 0; i < line.Length; i++)
			{
				if (line[i] == CodeDebtCollector.DebtSeparator)
					start++;
			}
			debtInfo.Comments = line.Substring(start).Trim();
			return true;
		}
		private bool ExtractCriticality(string line, int length, DebtInfo debtInfo)
		{
			//Next token should be the debt criticality. The switch statement will verify that it is correct.
			string criticality = line.Substring(0, length).ToUpper().Trim();
			bool validToken = true;
			switch (criticality)
			{
				case "A":
				case "B":
				case "C":
					break;

				default:
					criticality = ((char)Criticality.Critical).ToString();
					validToken = false;
					break;
			}
			//Conversion should be safe since the default is to correct to critical.
			debtInfo.Criticality = Convert.ToChar(criticality);
			return validToken;
		}
		private bool ExtractInitials(string line, int length, DebtInfo debtInfo)
		{
			bool validToken = length < 5;
			if (validToken)
				debtInfo.Initials = line.Substring(0, length).Trim();
			return validToken;
		}
		private void ValidateDebtInfo(DebtInfo debtInfo)
		{
			//If no criticality not found, default to type "A"
			if (debtInfo.Criticality == 0)
				debtInfo.Criticality = (char)Criticality.Critical;
			if (debtInfo.Initials == null || debtInfo.Initials.Length > 5)
				debtInfo.Initials = string.Empty;
			if (debtInfo.Comments == null)
				debtInfo.Comments = string.Empty;
		}
		private bool ExtractToken(string line, DebtInfo debtInfo, int length, TokenType tokenType)
		{
			bool validToken;
			switch (tokenType)
			{
				case TokenType.Initials:
					validToken = ExtractInitials(line, length, debtInfo);
					break;

				case TokenType.Criticality:
					validToken = ExtractCriticality(line, length, debtInfo);
					break;

				case TokenType.Estimate:
					validToken = ExtractEstimate(line, length, debtInfo);
					break;

				case TokenType.Comments:
					validToken = ExtractComments(line, length, debtInfo);
					break;

				default:
					validToken = false;
					break;
			}
			return validToken;
		}
		private DebtInfo GetCodeDebtData(string line, string debtType)
		{
			DebtInfo debtInfo = new DebtInfo(debtType);
			try
			{
				bool validToken = true;
				int pos = debtType.Length;
				for (int i = 0; i <= (int)TokenType.Comments; i++)
				{
					if (validToken)
					{
						//This will make certain that we don't exceed the line when there is a token but the rest is empty.
						int start = (line.Length >= pos + 1) ? 1 : 0;
						line = line.Substring(pos + start).TrimStart();
						//This is a kludge for the estimate. We will allow a space or colon delimiter just in case the developer left off
						//the final colon seperating the estimate from the comment.
						char[] delims = (i == (int)TokenType.Estimate)
							? new char[] { CodeDebtCollector.DebtSeparator, ' ' }
							: new char[] { CodeDebtCollector.DebtSeparator };
						pos = line.IndexOfAny(delims);
					}
					//If the token was invalid, treat remainder of line as a comment.
					if (!validToken || pos < 0)
					{
						ExtractComments(line, line.Length, debtInfo);
						break;
					}
					validToken = ExtractToken(line, debtInfo, pos, (TokenType)i);
				}
			}
			catch (Exception exc)
			{
				debtInfo.Comments = line.TrimStart();
				Exception baseExc = exc.GetBaseException();
				Trace.WriteLine(string.Format("Exception={0}\r\nTargetSite={1}\r\n{2}",
					baseExc.Message, baseExc.TargetSite.Name, baseExc.StackTrace));
			}
			ValidateDebtInfo(debtInfo);
			return debtInfo;
		}