public Question GetQuestion(int id)
        {
            Validation.IdCheck(id);

            Question question = new Question();

            using (IntelliCloudContext ctx = new IntelliCloudContext())
            {
                // TODO: make sure only users of type employee can retrieve private questions.
                QuestionEntity entity = (from q in ctx.Questions
                                                                 .Include(q => q.Source)
                                                                 .Include(q => q.User)
                                                                 .Include(q => q.User.Sources)
                                                                 .Include(q => q.Answerer)
                                                                 .Include(q => q.Answerer.Sources)
                                                                 .Include(q => q.User.Sources.Select(s => s.SourceDefinition))
                                         where q.Id == id
                                         select q).SingleOrDefault();

                if (entity == null)
                    throw new NotFoundException("No Question entity exists with the specified ID.");

                question = ConvertEntities.QuestionEntityToQuestion(entity);
            }
            return question;
        }
        public IList<Question> GetQuestions(int employeeId)
        {
            Validation.IdCheck(employeeId);

            List<Question> questions = new List<Question>();

            using (IntelliCloudContext ctx = new IntelliCloudContext())
            {
                UserEntity employee = (from u in ctx.Users
                                       where u.Id == employeeId
                                       select u).SingleOrDefault();

                // TODO: Only retrieve questions for retrieved employee.
                // TODO: Make sure only users of type employee can retrieve private questions.
                List<QuestionEntity> questionEntities = (from q in ctx.Questions
                                                                 .Include(q => q.Source)
                                                                 .Include(q => q.User)
                                                                 .Include(q => q.User.Sources)
                                                                 .Include(q => q.Answerer)
                                                                 .Include(q => q.Answerer.Sources)
                                                                 .Include(q => q.User.Sources.Select(s => s.SourceDefinition))
                                                         select q).ToList();

                questions = ConvertEntities.QuestionEntityListToQuestionList(questionEntities);
            }

            return questions;
        }
        public List<Review> GetReviews(int answerId)
        {
            Validation.IdCheck(answerId);

            using (var context = new IntelliCloudContext())
            {

                List<ReviewEntity> reviewEntities = (from r in context.Reviews.Include(r => r.Answer).Include(r => r.User)
                                                     where r.Answer.Id == answerId
                                                     select r).ToList();

                return ConvertEntities.ReviewEntityListToReviewList(reviewEntities);
            }
        }
        /// <summary>
        /// This method adds a new question to the database and saves this in a variable
        /// </summary>
        private void initializeTestData()
        {
            using (IntelliCloudContext ctx = new IntelliCloudContext())
            {
                UserEntity newUser = new UserEntity();
                newUser.CreationTime = DateTime.UtcNow;
                newUser.FirstName = "integration";
                newUser.LastName = "test";
                newUser.Type = Common.DataTransfer.UserType.Customer;

                ctx.Users.Add(newUser);
                ctx.SaveChanges();

                UserEntity newEmployee = new UserEntity();
                newEmployee.CreationTime = DateTime.UtcNow;
                newEmployee.FirstName = "employee";
                newEmployee.Type = Common.DataTransfer.UserType.Employee;

                ctx.Users.Add(newEmployee);
                ctx.SaveChanges();

                this.employee = newEmployee;

                SourceEntity newSource = new SourceEntity();
                newSource.User = newUser;
                newSource.Value = "*****@*****.**";
                newSource.CreationTime = DateTime.UtcNow;
                newSource.SourceDefinition = new SourceDefinitionEntity { CreationTime = DateTime.UtcNow, Description = "integration test def", Name = "test def", Url = "" };

                ctx.Sources.Add(newSource);
                ctx.SaveChanges();

                QuestionEntity newEntity = new QuestionEntity();
                newEntity.IsPrivate = false;
                newEntity.LanguageDefinition = new LanguageDefinitionEntity { Name = "English", ResourceName = "English" };
                newEntity.QuestionState = Common.DataTransfer.QuestionState.Open;
                newEntity.Source = new QuestionSourceEntity { Source = newSource, PostId = "" };
                newEntity.Title = "this is a test question";
                newEntity.User = newUser;
                newEntity.Content = "this is the question i want to ask, please help me?";
                newEntity.CreationTime = DateTime.UtcNow;
                newEntity.FeedbackToken = "feedbackyeah!!@#$%^&*()";

                ctx.Questions.Add(newEntity);
                ctx.SaveChanges();

                this.entity = newEntity;
            }
        }
        /// <summary>
        /// Method for retrieving user info using the AuthorizationToken HTTP header.
        /// </summary>
        /// <returns>Instance of class OpenIDUserInfo on success or null on error.</returns>
        public OpenIDUserInfo GetOpenIDUserInfo()
        {
            // OpenIDUserInfo object that will contain the OpenIDUserInfo object on success
            OpenIDUserInfo userInfo = null;

            // Get the value of the AuthorizationToken HTTP header
            IncomingWebRequestContext requestContext = WebOperationContext.Current.IncomingRequest;
            string authorizationToken = requestContext.Headers["AuthorizationToken"];

            // Only continue if an authorization token is available
            if (!String.IsNullOrWhiteSpace(authorizationToken))
            {
                try
                {
                    // Decode the Base64 representation of the JSON object
                    byte[] tokenBytes = Convert.FromBase64String(authorizationToken);

                    // Parse the token
                    AuthorizationToken parsedToken = null;
                    using (MemoryStream stream = new MemoryStream(tokenBytes))
                    {
                        // Initialize serializer (used for deserializing the JSON representation of the AuthorizationToken)
                        DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(AuthorizationToken));
                        parsedToken = (AuthorizationToken)jsonSerializer.ReadObject(stream);
                    }

                    // Get the endpoint URL of the issuer from the context
                    string endpointUrl = "";
                    using (IntelliCloudContext context = new IntelliCloudContext())
                    {
                        SourceDefinitionEntity sourceDefinition = context.SourceDefinitions.SingleOrDefault(sd => sd.Name.Equals(parsedToken.Issuer));
                        endpointUrl = sourceDefinition.Url;
                    }

                    // Get available user information from the Access Token issuer
                    userInfo = OpenIDContext.RetrieveUserInfo(endpointUrl, parsedToken);
                }
                catch (Exception)
                {
                    // Ignore all exceptions because we want to return null if no user info could be retrieved
                }
            }

            // Return the OpenIDUserInfo object
            return userInfo;
        }
        public void CreateAnswer(int questionId, string answer, int answererId, AnswerState answerState)
        {
            Validation.IdCheck(answererId);
            Validation.IdCheck(questionId);
            Validation.StringCheck(answer);

            using (var ctx = new IntelliCloudContext())
            {

                AnswerEntity answerEntity = new AnswerEntity();

                answerEntity.AnswerState = answerState;
                answerEntity.Content = answer;
                answerEntity.CreationTime = DateTime.UtcNow;

                UserEntity user = ctx.Users.SingleOrDefault(ld => ld.Id == answererId);

                if (user == null)
                    throw new NotFoundException("No user entity exists with the specified ID.");

                answerEntity.User = user;
                // TODO link answer to question and generate a feedbackToken using GUID (can both be set in the question).
                // TODO set IsPrivate based on private settings in question.
                answerEntity.IsPrivate = false;

                // TODO determine real language 
                LanguageDefinitionEntity languageDefinition = ctx.LanguageDefinitions.SingleOrDefault(ld => ld.Name.Equals("English"));

                if (languageDefinition == null)
                    throw new NotFoundException("No languageDefinition entity exists with the specified ID.");

                answerEntity.LanguageDefinition = languageDefinition;

                ctx.Answers.Add(answerEntity);

                ctx.SaveChanges();

            }

            // TODO put the SendAnswerFactory in the BaseManager.
            // TODO send the answer using the this.SendAnswerFactory.LoadPlugin(question.Source.Source.SourDefinition).SendAnswer(question, answer) method.
        }
        public void UpdateReview(string reviewId, ReviewState reviewState)
        {
            Validation.IdCheck(reviewId);

            using (var context = new IntelliCloudContext())
            {
                var id = Convert.ToInt32(reviewId);
                ReviewEntity review = context.Reviews.SingleOrDefault(r => r.Id.Equals(id));
                if (review != null)
                {
                    review.ReviewState = reviewState;

                    context.SaveChanges();
                }
                else
                {
                    throw new NotFoundException("Sequence contains no elements");
                }
            }
        }
        /// <summary>
        /// Method used for retrieving all feedback entries assigned to a specific answer.
        /// </summary>
        /// <param name="answerId">The id of the answer to which all feedback entries to be retrieved are assigned to.</param>
        /// <returns>A list of instances of class Feedback.</returns>
        public IList<Feedback> GetFeedbacks(int answerId)
        {
            // Validate input data
            Validation.IdCheck(answerId);

            // Return all feedback entries assigned to the specified answer
            using (IntelliCloudContext context = new IntelliCloudContext())
            {
                return context.Feedbacks
                       .Include(f => f.Answer)
                       .Include(f => f.Question)
                       .Include(f => f.Question.Source)
                       .Include(f => f.User)
                       .Include(f => f.User.Sources)
                       .Where(f => f.Answer.Id == answerId)
                       .ToList()
                       .Select(f => ConvertEntities.FeedbackEntityToFeedback(f))
                       .ToList();
            }
        }
        /// <summary>
        /// This method adds a new question to the database and saves this in a variable
        /// </summary>
        private void initializeTestData()
        {
            using (IntelliCloudContext ctx = new IntelliCloudContext())
            {
                UserEntity newEmployee = new UserEntity();
                newEmployee.CreationTime = DateTime.UtcNow;
                newEmployee.FirstName = "employee";
                newEmployee.Type = Common.DataTransfer.UserType.Employee;

                ctx.Users.Add(newEmployee);
                ctx.SaveChanges();

                this.employee = newEmployee;

                AnswerEntity newAnswer = new AnswerEntity();
                newAnswer.CreationTime = DateTime.UtcNow;
                newAnswer.Content = "Integration test for answer";
                newAnswer.AnswerState = AnswerState.UnderReview;
                newAnswer.IsPrivate = false;
                newAnswer.LanguageDefinition = new LanguageDefinitionEntity() {Name = "Dutch", ResourceName = "NL"};
                newAnswer.User = newEmployee;

                ctx.Answers.Add(newAnswer);
                ctx.SaveChanges();

                this.answer = newAnswer;

                ReviewEntity newReview = new ReviewEntity();
                newReview.CreationTime = DateTime.UtcNow;
                newReview.Content = "Integration test for review";
                newReview.ReviewState = ReviewState.Open;
                newReview.User = newEmployee;
                newReview.Answer = newAnswer;

                ctx.Reviews.Add(newReview);
                ctx.SaveChanges();

                this.review = newReview;

            }
        }
        /// <summary>
        /// Method for retrieving available user information from the Access Token issuer.
        /// </summary>
        /// <param name="token">Instance of class AuthorizationToken.<param>
        /// <returns>Instance of class OpenIDUserInfo.</returns>
        private OpenIDUserInfo RetrieveUserInfo(AuthorizationToken token)
        {
            // String that will contain the endpoint URL of the issuer specified in the token
            string userInfoEndpointUrl = "";

            // Get the endpoint URL of the issuer from the context
            using (IntelliCloudContext context = new IntelliCloudContext())
            {
                SourceDefinitionEntity sourceDefinition = context.SourceDefinitions.SingleOrDefault(sd => sd.Name.Equals(token.Issuer));

                if (sourceDefinition == null)
                    throw new NotFoundException("No source definition entity exists for the specified issuer.");

                userInfoEndpointUrl = sourceDefinition.Url;
            }

            // Get available user information from the Access Token issuer.
            string requestUrl = String.Format(userInfoEndpointUrl, token.AccessToken);
            WebRequest request = WebRequest.Create(requestUrl);
            WebResponse response = request.GetResponse();
            StreamReader reader = new StreamReader(response.GetResponseStream());
            string userInfo = reader.ReadToEnd();
            reader.Close();
            response.Close();

            // Convert the user info string to a byte array for further processing
            byte[] userInfoBytes = Encoding.UTF8.GetBytes(userInfo);

            using (MemoryStream stream = new MemoryStream(userInfoBytes))
            {
                // Initialize serializer (used for deserializing the JSON representation of the AuthorizationToken)
                DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(OpenIDUserInfo));
                OpenIDUserInfo parsedUserInfo = (OpenIDUserInfo)jsonSerializer.ReadObject(stream);
                parsedUserInfo.Issuer = token.Issuer;

                return parsedUserInfo;
            }
        }
        /// <summary>
        /// Retrieves all the available answers and optionally filtering them using the answer state or employee 
        /// identifier.
        /// </summary>
        /// <param name="answerState">The optional answer state, only answers with this state will be returned.
        /// </param>
        /// <param name="employeeId">The optional employee identifier, only answers about which the employee has 
        /// knowledge are returned (keywords between user and answer match).</param>
        /// <returns>Returns the answers that match the filters.</returns>
        public IList<Answer> GetAnswers(AnswerState answerState, int employeeId)
        {
            Validation.IdCheck(employeeId);

            List<Answer> answers = new List<Answer>();

            using (var ctx = new IntelliCloudContext())
            {

                List<AnswerEntity> answerentities = (from a in ctx.Answers
                                                         .Include(a => a.User)
                                                         .Include(a => a.User.Sources)
                                                         .Include(a => a.User.Sources.Select(s => s.SourceDefinition))
                                                     where a.AnswerState == answerState
                                                     select a).ToList();

                answers = ConvertEntities.AnswerEntityListToAnswerList(answerentities);

            }

            return answers;

        }
        public void CreateReview(int employeeId, int answerId, string review)
        {
            Validation.IdCheck(answerId);
            Validation.IdCheck(employeeId);
            Validation.StringCheck(review);

            using (var context = new IntelliCloudContext())
            {
                ReviewEntity reviewEntity = new ReviewEntity();
                var answer = context.Answers.SingleOrDefault(q => q.Id.Equals(answerId));
                if (review != null)
                {
                    reviewEntity.Answer = answer;
                }
                else
                {
                    throw new NotFoundException("Sequence contains no elements");
                }

                var user = context.Users.SingleOrDefault(u => u.Id.Equals(employeeId));
                if (user != null)
                {
                    reviewEntity.User = user;
                }
                else
                {
                    throw new NotFoundException("Sequence contains no elements");
                }

                reviewEntity.Content = review;
                reviewEntity.ReviewState = ReviewState.Open;

                context.Reviews.Add(reviewEntity);

                context.SaveChanges();
            }
        }
        /// <summary>
        /// Retrieve the answer with the given identifier.
        /// </summary>
        /// <param name="id">The identifier of the answer.</param>
        /// <returns>Returns the answer with the given identifier.</returns>
        public Answer GetAnswer(string id)
        {
            Validation.IdCheck(id);

            Answer answer = new Answer();

            using (var ctx = new IntelliCloudContext())
            {
                int iId = Convert.ToInt32(id);

                AnswerEntity answerentity = (from a in ctx.Answers
                                                         .Include(a => a.User)
                                                         .Include(a => a.User.Sources)
                                                         .Include(a => a.User.Sources.Select(s => s.SourceDefinition))
                                             where a.Id == iId
                                             select a).Single();

                answer = ConvertEntities.AnswerEntityToAnswer(answerentity);

            }

            return answer;

        }
        public void UpdateReview()
        {
            try
            {
                string reviewId = "1";
                ReviewState reviewState = ReviewState.Open;;

                service.UpdateReview(reviewId, reviewState);

                using (var context = new IntelliCloudContext())
                {
                    int id = Convert.ToInt32(reviewId);
                    ReviewEntity review = context.Reviews.FirstOrDefault(r => r.Id.Equals(id));
                    if (review != null)
                    {
                        Assert.AreEqual(ReviewState.Open, review.ReviewState);
                    }
                }
            }
            catch (Exception e) // TODO move exception test to different method, since this allows for skipping a part of the test...
            {
                Assert.AreEqual(e.Message, "Sequence contains no elements");
            }
        }
        public void UpdateQuestion()
        {
            try
            {
                var employeeId = this.employee.Id;
                var questionId = this.entity.Id;

                this.service.UpdateQuestion(questionId.ToString(), employeeId);

                using (IntelliCloudContext ctx = new IntelliCloudContext())
                {
                    var question = ctx.Questions.Single(q => q.Id == questionId);

                    Assert.AreEqual(questionId, question.Id);
                }

            }
            catch (Exception e) // TODO move exception test to different method, since this allows for skipping a part of the test...
            {
                Assert.AreEqual(e.Message, "Sequence contains no elements");
            }
        }
        public void Cleanup()
        {
            using (IntelliCloudContext ctx = new IntelliCloudContext())
            {
                ctx.Questions.RemoveRange(ctx.Questions.ToList());
                ctx.QuestionSources.RemoveRange(ctx.QuestionSources.ToList());
                ctx.Sources.RemoveRange(ctx.Sources.ToList());
                ctx.SourceDefinitions.RemoveRange(ctx.SourceDefinitions.ToList());
                ctx.LanguageDefinitions.RemoveRange(ctx.LanguageDefinitions.ToList());
                ctx.Users.RemoveRange(ctx.Users.ToList());

                ctx.SaveChanges();
            }
        }
        /// <summary>
        /// Updates the answer with the given identifier.
        /// </summary>
        /// <param name="id">The identifier of the answer that is updated.</param>
        /// <param name="answerState">The new state of the answer.</param>
        /// <param name="answer">The new content of the given answer.</param>
        public void UpdateAnswer(string id, AnswerState answerState, string answer)
        {
            Validation.IdCheck(id);
            Validation.StringCheck(answer);

            using (var ctx = new IntelliCloudContext())
            {
                int iId = Convert.ToInt32(id);

                AnswerEntity answerEntity = (from a in ctx.Answers
                                                 .Include(a => a.User)
                                                 .Include(a => a.LanguageDefinition)
                                             where a.Id == iId
                                             select a).SingleOrDefault();

                if (answerEntity == null)
                    throw new NotFoundException("No answer entity exists with the specified ID.");

                answerEntity.AnswerState = answerState;
                answerEntity.Content = answer;

                ctx.SaveChanges();

            }
        }
        /// <summary>
        /// Checks if the given SourceDefinitionName exists.
        /// </summary>
        /// <param name="SourceDefinitionName">SourceDefinitionName that has to be checked.</param>
        public void SourceDefinitionExistsCheck(string SourceDefinitionName)
        {
                using (IntelliCloudContext ctx = new IntelliCloudContext())
                {

                    var sourceDefinitions = from sd in ctx.SourceDefinitions
                                            where sd.Name == SourceDefinitionName
                                            select sd;

                    if (!(sourceDefinitions.Count() > 0))
                    {
                        throw new ArgumentException("Source definition not found.");
                    }
                }
        }
        public void Cleanup()
        {
            using (IntelliCloudContext ctx = new IntelliCloudContext())
            {
                ctx.Reviews.RemoveRange(ctx.Reviews.ToList());
                ctx.Answers.RemoveRange(ctx.Answers.ToList());
                ctx.Users.RemoveRange(ctx.Users.ToList());

                ctx.SaveChanges();
            }
        }
        public void CreateReview()
        {
            try
            {
                int answerId = answer.Id;
                string review = "Hallo dit is mijn review";
                int employeeId = employee.Id;

                service.CreateReview(employeeId, answerId, review);

                using (IntelliCloudContext ctx = new IntelliCloudContext())
                {
                    ReviewEntity newEntity = ctx.Reviews
                    .Include(r => r.User)
                    .Include(r => r.Answer).Single(r => r.Content == review && r.Answer.Id == answer.Id && r.User.Id == employee.Id);

                    Assert.AreEqual("Hallo dit is mijn review", newEntity.Content);
                    Assert.AreEqual(answer.Content, newEntity.Answer.Content);
                    Assert.AreEqual(employee.FirstName, newEntity.User.FirstName);
                    Assert.AreEqual(ReviewState.Open, newEntity.ReviewState);
                }
            }
            catch (Exception e) // TODO move exception test to different method, since this allows for skipping a part of the test...
            {
                Assert.AreEqual(e.Message, "Sequence contains no elements");
            }
        }
        /// <summary>
        /// Method used for creating a new user.
        /// </summary>
        /// <param name="type">The type of user. Required.</param>
        /// <param name="sources">A list of UserSource instances. Required (must contain at least one item).</param>
        /// <param name="firstName">The user's first name. Optional.</param>
        /// <param name="infix">The user's infix. Optional.</param>
        /// <param name="lastName">The user's last name. Optional.</param>
        public void CreateUser(UserType type, IList<UserSource> sources, string firstName = null, string infix = null, string lastName = null)
        {
            // Validate supplied input data
            if (firstName != null) Validation.StringCheck(firstName);
            if (infix != null) Validation.StringCheck(infix);
            if (lastName != null) Validation.StringCheck(lastName);

            using (IntelliCloudContext context = new IntelliCloudContext())
            {
                // Create a new user based on the retrieved user info
                UserEntity userEntity = new UserEntity()
                {
                    FirstName = firstName,
                    Infix = infix,
                    LastName = lastName,
                    Type = type,
                    CreationTime = DateTime.UtcNow
                };
                context.Users.Add(userEntity);

                // Add all supplied sources to the user
                foreach (UserSource source in sources)
                {
                    // Check if the source is defined
                    Validation.SourceDefinitionExistsCheck(source.Name);

                    // Create a new source for the source definition
                    SourceDefinitionEntity sourceDefinition = context.SourceDefinitions.SingleOrDefault(sd => sd.Name.Equals(source.Name));
                    SourceEntity sourceEntity = new SourceEntity()
                    {
                        Value = source.Value,
                        CreationTime = DateTime.UtcNow,
                        SourceDefinition = sourceDefinition,
                        User = userEntity,
                    };
                    context.Sources.Add(sourceEntity);
                }

                // Save the changes to the context
                context.SaveChanges();
            }
        }
        /// <summary>
        /// Method for getting a user based on it's ID or a list of UserSource instances.
        /// All parameters are optional - if no parameters are provided the currently logged in user will be returned.
        /// </summary>
        /// <param name="id">The ID of the user. Optional.</param>
        /// <param name="sources">A list of UserSource instances. Optional.</param>
        /// <returns>The matched user based on the values of the parameters, otherwise the currently logged in user.</returns>
        public User GetUser(string id = null, IList<UserSource> sources = null)
        {
            // Validate supplied input data
            if (id != null) Validation.IdCheck(id);

            // User object that will contain the User object on success
            User user = null;

            // Check if any input data is supplied
            if (id == null && sources == null)
            {
                // No input data is supplied, return the currently logged in user
                user = this.GetAuthorizedUser();
            }
            else
            {
                // Get the user from the context
                using (IntelliCloudContext context = new IntelliCloudContext())
                {
                    UserEntity userEntity = null;

                    // Build the query
                    var query = context.Users.Include(u => u.Sources.Select(s => s.SourceDefinition));

                    // Check if an id has been supplied
                    if (id != null)
                    {
                        int iId = Convert.ToInt32(id);
                        query = query.Where(u => u.Id == iId);
                        userEntity = query.SingleOrDefault();
                    }

                    // Check if sources have been supplied
                    if (sources != null && sources.Count > 0)
                        userEntity = query.ToList().Where(u => u.Sources.Any(s => sources.Any(us => us.Name == s.SourceDefinition.Name && us.Value == s.Value))).SingleOrDefault();
                    else
                        userEntity = query.SingleOrDefault();

                    // Convert the UserEntity (if found) to an instance of class User and set in the reference
                    if (userEntity != null)
                        user = ConvertEntities.UserEntityToUser(userEntity);
                }
            }

            // Return the User object
            return user;
        }
        public void UpdateQuestion(int id, int employeeId)
        {
            Validation.IdCheck(id);
            Validation.IdCheck(employeeId);

            using (IntelliCloudContext ctx = new IntelliCloudContext())
            {
                QuestionEntity questionEntity = (from q in ctx.Questions
                                                 where q.Id == id
                                                 select q).Single();

                questionEntity.Answerer = (from u in ctx.Users
                                           where u.Id == employeeId
                                           select u).Single();
                ctx.SaveChanges();
            }

        }
        public void CreateQuestion()
        {
            try
            {
                string content = "This is the content";
                string title = "This is the title";
                string source = "test def";
                string reference = "reffgdsgfd";

                this.service.CreateQuestion(source, reference, content, title);

                using (IntelliCloudContext ctx = new IntelliCloudContext())
                {
                    QuestionEntity newEntity = ctx.Questions
                    .Include(q => q.Source)
                    .Include(q => q.User)
                    .Include(q => q.User.Sources)
                    .Include(q => q.User.Sources.Select(s => s.SourceDefinition))
                    .Include(q => q.LanguageDefinition).Single(q => q.Content == content && q.Title == title);

                    Assert.AreEqual(content, newEntity.Content);
                    Assert.AreEqual(title, newEntity.Title);
                    Assert.AreEqual(source, newEntity.Source.Source.SourceDefinition.Name);
                    Assert.AreEqual(reference, newEntity.Source.Source.Value);
                }
            }
            catch (Exception e) // TODO move exception test to different method, since this allows for skipping a part of the test...
            {
                Assert.AreEqual(e.Message, "Sequence contains no elements");
            }
        }
        /// <summary>
        /// Method used for saving user feedback for an answer.
        /// </summary>
        /// <param name="feedback">The textual feedback given by the user.</param>
        /// <param name="answerId">The id of the answer for which the feedback has been given.</param>
        /// <param name="questionId">The id of the question to which the answer is assigned.</param>
        /// <param name="feedbackType">The type of feedback which indicates if the user accepted or declined the answer.</param>
        /// <param name="feedbackToken">The feedback token is required to provide feedback to answers on a question. It
        /// is used to make sure the user that asked the question is also the user giving the feedback and that feedback
        /// can only be given once.</param>
        public void CreateFeedback(string feedback, int answerId, int questionId, FeedbackType feedbackType, string feedbackToken)
        {
            // Validate input data
            Validation.StringCheck(feedback);
            Validation.IdCheck(answerId);
            Validation.IdCheck(questionId);
            Validation.StringCheck(feedbackToken);

            using (IntelliCloudContext context = new IntelliCloudContext())
            {
                // Get the answer entity from the context
                AnswerEntity answer = context.Answers
                    .Include(a => a.User)
                    .Include(a => a.User.Sources)
                    .Include(a => a.LanguageDefinition)
                    .SingleOrDefault(a => a.Id == answerId);

                if (answer == null)
                    throw new NotFoundException("No answer entity exists with the specified ID.");

                // Set the state of the answer to UnderReview - employee needs to process the feedback given by the user
                answer.AnswerState = AnswerState.UnderReview;

                // Get the question entity from the context
                QuestionEntity question = context.Questions
                                          .Include(q => q.User)
                                          .Include(q => q.User.Sources)
                                          .Include(q => q.Source)
                                          .Include(q => q.LanguageDefinition)
                                          .Include(q => q.Answer)
                                          .Include(q => q.Answer.LanguageDefinition)
                                          .Include(q => q.Answer.User)
                                          .Include(q => q.Answer.User.Sources)
                                          .Include(q => q.Answerer)
                                          .Include(q => q.Answerer.Sources)
                                          .SingleOrDefault(q => q.Id == questionId);

                if (question == null)
                    throw new NotFoundException("No question entity exists with the specified ID.");

                // Check if the user who asked the question is the one to posted the feedback and make sure feedback is
                // only given once.
                if (question.FeedbackToken != feedbackToken)
                    throw new InvalidOperationException(
                        "Feedback can only be given once by the user who asked the question.");
                
                // Set the state of the question to Open - employee needs to process the feedback given by the user
                question.QuestionState = QuestionState.Open;
                // Reset token so feedback can only be given once.
                question.FeedbackToken = null;

                // Store the user's feedback for the given answer
                FeedbackEntity feedbackEntity = new FeedbackEntity();
                feedbackEntity.Question = question;
                feedbackEntity.Answer = answer;
                feedbackEntity.Content = feedback;
                feedbackEntity.CreationTime = DateTime.UtcNow;
                feedbackEntity.FeedbackState = FeedbackState.Open;
                feedbackEntity.FeedbackType = feedbackType;
                feedbackEntity.User = question.User;
                context.Feedbacks.Add(feedbackEntity);

                // Save the changes to the context
                context.SaveChanges();
            }
        }
        /// <summary>
        /// Method for matching a user based on an instance of class OpenIDUserInfo.
        /// </summary>
        /// <param name="userInfo">The instance of class OpenIDUserInfo that will be used to match a user.</param>
        /// <param name="matchedUser">Reference to an object of class User - will be set to an instance of class User on success or null if no user could be matched.</param>
        /// <returns>Boolean value indicating if a user could be matched.</returns>
        public bool TryMatchUser(OpenIDUserInfo userInfo, out User matchedUser)
        {
            // User object that will contain the matched User object on success
            matchedUser = null;

            // Only attempt to match a user when an instance of class OpenIDUserInfo has been supplied
            if (userInfo != null)
            {
                using (IntelliCloudContext context = new IntelliCloudContext())
                {
                    // Get the user entity from the context
                    UserEntity userEntity = context.Users
                                            .Include(u => u.Sources.Select(s => s.SourceDefinition))
                                            .SingleOrDefault(s => s.Sources.Any(a => (a.SourceDefinition.Name == "Mail" && a.Value == userInfo.Email) || (a.SourceDefinition.Name == userInfo.Issuer && a.Value == userInfo.Sub)));

                    // Only continue if the user entity was found
                    if (userEntity != null)
                    {
                        // Update the user's first name and last name
                        userEntity.FirstName = userInfo.GivenName;
                        userEntity.LastName = userInfo.FamilyName;

                        // Update the user's id from the issuer
                        userEntity.Sources.Where(s => s.SourceDefinition.Name == userInfo.Issuer)
                                          .Select(s => { s.Value = userInfo.Sub; return s; });

                        // Save the changes to the context
                        context.SaveChanges();

                        // Convert the UserEntity to an instance of class User and set in the reference
                        matchedUser = this.convertEntities.UserEntityToUser(userEntity);
                    }
                }
            }

            // Return true or false indicating if a user could be matched
            return (matchedUser != null) ? true : false;
        }
        /// <summary>
        /// Method for creating a new user based on an instance of class OpenIDUserInfo.
        /// </summary>
        /// <param name="userInfo">The instance of class OpenIDUserInfo that will be used to create the new user.</param>
        /// <param name="createdUser">Reference to an object of class User - will be set to an instance of class User on success or null if the user could not be created.</param>
        /// <returns>Boolean value indicating if the user could be created.</returns>
        public bool TryCreateNewUser(OpenIDUserInfo userInfo, out User createdUser)
        {
            // User object that will contain the newly created User object on success
            createdUser = null;

            // Only attempt to create a new user when an instance of class OpenIDUserInfo has been supplied
            if (userInfo != null)
            {
                // No user could be matched; create a new user based on the retrieved user info
                UserEntity userEntity = null;
                using (IntelliCloudContext context = new IntelliCloudContext())
                {
                    // Create a new user based on the retrieved user info
                    userEntity = new UserEntity()
                    {
                        FirstName = userInfo.GivenName,
                        LastName = userInfo.FamilyName,
                        Type = UserType.Customer,
                        CreationTime = DateTime.UtcNow
                    };
                    context.Users.Add(userEntity);

                    // Create a new source for the user's email address
                    SourceDefinitionEntity mailSourceDefinition = context.SourceDefinitions.SingleOrDefault(sd => sd.Name.Equals("Mail"));
                    SourceEntity mailSourceEntity = new SourceEntity()
                    {
                        Value = userInfo.Email,
                        CreationTime = DateTime.UtcNow,
                        SourceDefinition = mailSourceDefinition,
                        User = userEntity,
                    };
                    context.Sources.Add(mailSourceEntity);

                    // Create a new source for the user's id from the issuer
                    SourceDefinitionEntity issuerSourceDefinition = context.SourceDefinitions.SingleOrDefault(sd => sd.Name.Equals(userInfo.Issuer));
                    SourceEntity issuerSourceEntity = new SourceEntity()
                    {
                        Value = userInfo.Sub,
                        CreationTime = DateTime.UtcNow,
                        SourceDefinition = issuerSourceDefinition,
                        User = userEntity,
                    };
                    context.Sources.Add(issuerSourceEntity);

                    // Save the changes to the context
                    context.SaveChanges();
                }

                // Convert the UserEntity instance to an instance of class User and set it in the matchedUser variable
                createdUser = this.convertEntities.UserEntityToUser(userEntity);
            }

            // Return true or false indicating if the user has been created
            return (createdUser != null) ? true : false;
        }
        public void CreateQuestion(
            string source, string reference, string question, string title, string postId = null, bool isPrivate = false)
        {
            Validation.StringCheck(source);
            Validation.StringCheck(reference);
            Validation.StringCheck(question);
            Validation.StringCheck(title);

            using (IntelliCloudContext ctx = new IntelliCloudContext())
            {
                // TODO determine real language 
                LanguageDefinitionEntity languageDefinition = ctx.LanguageDefinitions.SingleOrDefault(ld => ld.Name.Equals("English"));

                // TODO remove exception as you probably want to create the language if it doesn't exist.
                if (languageDefinition == null)
                    throw new NotFoundException("No languageDefinition entity exists with the specified ID.");

                SourceDefinitionEntity sourceDefinition = ctx.SourceDefinitions.SingleOrDefault(sd => sd.Name.Equals(source));

                if (sourceDefinition == null)
                    throw new NotFoundException("The provided source doesn't exists.");

                // Check if the user already exists
                SourceEntity sourceEntity = ctx.Sources.SingleOrDefault(s => s.SourceDefinition.Id == sourceDefinition.Id && s.Value == reference);

                UserEntity userEntity;

                if (sourceEntity != null)
                {
                    // user already has an account, use this
                    userEntity = ctx.Users.Single(u => u.Id == sourceEntity.UserId);
                }
                else
                {
                    // user has no account, create one
                    userEntity = new UserEntity()
                    {
                        CreationTime = DateTime.UtcNow,
                        Type = UserType.Customer
                    };

                    ctx.Users.Add(userEntity);

                    // Mount the source to the new user
                    sourceEntity = new SourceEntity()
                    {
                        Value = reference,
                        CreationTime = DateTime.UtcNow,
                        SourceDefinition = sourceDefinition,
                        User = userEntity,
                    };

                    ctx.Sources.Add(sourceEntity);
                }

                QuestionEntity questionEntity = new QuestionEntity()
                {
                    Content = question,
                    CreationTime = DateTime.UtcNow,
                    IsPrivate = isPrivate,
                    QuestionState = QuestionState.Open,
                    Title = title,
                    Source = new QuestionSourceEntity()
                    {
                        Source = sourceEntity,
                        PostId = postId
                    },
                    LanguageDefinition = languageDefinition,
                    User = userEntity
                };

                ctx.Questions.Add(questionEntity);

                ctx.SaveChanges();
            }
        }
        /// <summary>
        /// Method used for updating the state of an existing feedback entry.
        /// </summary>
        /// <param name="id">The id of the feedback entry to update.</param>
        /// <param name="feedbackState">The new state of the feedback entry.</param>
        public void UpdateFeedback(string id, FeedbackState feedbackState)
        {
            // Validate input data
            Validation.IdCheck(id);

            // Convert the textual representation of the id to an integer
            int iFeedbackId = Convert.ToInt32(id);

            using (IntelliCloudContext context = new IntelliCloudContext())
            {
                // Get the feedback entity from the context
                FeedbackEntity feedback = context.Feedbacks
                    .Include(f => f.Question)
                    .Include(f => f.User)
                    .Include(f => f.Answer)
                    .SingleOrDefault(f => f.Id == iFeedbackId);

                if (feedback == null)
                    throw new NotFoundException("No feedback entity exists with the specified ID.");

                // Update the state of the feedback entry
                feedback.FeedbackState = feedbackState;

                // Save the changes to the context
                context.SaveChanges();
            }
        }