private void BuildModel(ClassElem klass, ClassDocumentation klassDoc,
			List<Integer> codeQMatches, List<Integer> codeAMatches,
			List<Integer> linkAMatches, HashSet<Integer> ansSet,
			Hashtable<Integer, Integer> AnswerIdToParentId,
			HashSet<Integer> qSet,
			Hashtable<Integer,ThreadElement> ThreadMap // Shared across all ClassDocs
			) 
	{
		List<Integer> myThreads = new ArrayList<Integer>();
		
		// Build threads
		for( Integer id : qSet )
		{
			ThreadElement thread = new ThreadElement();
			thread.Question = new QuestionElement();
			thread.Question.Id = id;
			thread.Question.IsLinked = true;
	
			// Thread detail
			PostInfo info = db.GetPostDetail(thread.Question.Id);
			thread.Question.Title = info.Title;
			thread.Question.UserId = info.OwnerUserId;
			thread.Question.Body = info.getBody();
			thread.Question.Parent = thread;
			
			thread.Votes = info.Score;
			thread.FavoriteCount = info.FavoriteCount;
			thread.ViewCount = info.ViewCount;
			thread.CreationDate = info.CreationDate;

			if( info.AcceptedAnswerId != null )
			{
				thread.Question.HasAcceptedAnswer = true;
				thread.Question.AcceptedAnswerId = info.AcceptedAnswerId;
			}

			// Validate Links
			LinkValidation validate = new LinkValidation();
			List<LinkElement> hrefs = new ArrayList<LinkElement>();
			List<LinkSpan> spans = validate.Validate(klass, thread.Question, thread.Question.Title, hrefs);
			thread.Question.setHrefs( hrefs, klass );
			thread.Question.setLinks( spans, klass );
			
			// Side effect
			CodeSampleElement sample = GetOrBuildCodeSample(klass, thread.Question, spans);
			sample.Votes = thread.Votes;
			
			ThreadMap.put(id, thread);
			myThreads.add(id);
		}
		
		for( Integer answerId : ansSet )
		{
			int parentQ = AnswerIdToParentId.get( answerId );
			if( !ThreadMap.containsKey(parentQ) )
			{
				// Non-linked Q, add thread
				ThreadElement thread = new ThreadElement();
				thread.Question = new QuestionElement();
				thread.Question.Id = parentQ;
				thread.Question.IsLinked = false;
				//thread.Question.Links = new ArrayList<LinkSpan>();
				//thread.Question.Hrefs = new ArrayList<LinkElement>();
				
				// Detail
				PostInfo tinfo = db.GetPostDetail(parentQ);
				thread.Question.Title = tinfo.Title;
				thread.Question.UserId = tinfo.OwnerUserId;
				thread.Question.Body = tinfo.getBody();
				thread.Question.Parent = thread;
				
				thread.Votes = tinfo.Score;
				thread.FavoriteCount = tinfo.FavoriteCount;
				thread.ViewCount = tinfo.ViewCount;
				thread.CreationDate = tinfo.CreationDate;

				if( tinfo.AcceptedAnswerId != null )
				{
					thread.Question.HasAcceptedAnswer = true;
					thread.Question.AcceptedAnswerId = tinfo.AcceptedAnswerId;
				}
				
				ThreadMap.put(parentQ, thread);
				myThreads.add(parentQ);
			}
		}
		
		klassDoc.Klass = klass;
		//klassDoc.ThreadElements.addAll(ThreadMap.values());
		for(Integer id : myThreads)
		{
			klassDoc.ThreadElements.add(ThreadMap.get(id));
		}

		// All Answers
		for( ThreadElement thread : klassDoc.ThreadElements )
		{
			for( PostInfo info : db.Answers(thread.Question.Id) )
			{
				AnswerElement ans = new AnswerElement();
				ans.Id = info.Id;

				// Thread detail
				ans.Votes = info.Score;
				ans.Date = info.CreationDate;
				ans.Body = info.getBody();
				ans.UserId = info.OwnerUserId;
				ans.BountyAmount = db.GetBountyAmount(ans.Id);
				ans.Parent = thread;
				
				if( ansSet.contains(info.Id) )
				{
					// Validate Links
					LinkValidation validate = new LinkValidation();
					List<LinkElement> hrefs = new ArrayList<LinkElement>();
					List<LinkSpan> spans = validate.Validate(klass, ans,null, hrefs);
					ans.setHrefs( hrefs, klass);
					ans.setLinks( spans, klass );
					//ans.setCodeSample(BuildCodeSample(spans,ans), klass );

					// Side effect
					CodeSampleElement sample = GetOrBuildCodeSample(klass, ans, spans);
					sample.Votes = ans.Votes;
				}
				thread.Answers.add(ans);
			}
		}
	}