/**
   * Tests the authentication of different calls. Currently tests adding a project, updating a
   * project and getting collections without correct permissions.
   *
   * @throws InvalidXmlException
   * @throws BizInternalException
   * @throws BizPolicyException
   * @throws IOException
   */
  @Test
  public void testAuthentication()
      throws InvalidXmlException, BizInternalException, BizPolicyException, IOException {
    Project newProject = new Project(projectOne);
    newProject.setName("Update");
    newProject.setDescription("foo-update");
    newProject.setEndDate(new DateTime(2014, 2, 10, 0, 0));

    String mimeType = "application/xml";

    // Test updating a project without proper permissions
    MockHttpServletRequest mockReq = newMockRequest("PUT", projectOne.getId(), "test.org", 80);
    MockHttpServletResponse resp = new MockHttpServletResponse();

    ByteArrayOutputStream sink = new ByteArrayOutputStream();
    businessObjectBuilder.buildProject(newProject, sink);

    controller.setAuthenticatedUser(pendingUser);
    controller.handleUpdateProjectRequest(
        projectOne.getId(), mimeType, sink.toByteArray(), mockReq, resp);
    assertNotNull(resp);
    assertEquals(403, resp.getStatus());

    // Test adding a project without proper permissions
    mimeType = "application/xml";
    mockReq = newMockRequest("POST", "/project", "test.org", 80);
    resp = new MockHttpServletResponse();

    sink = new ByteArrayOutputStream();
    newProject.setId("http://test.org/project/2");
    businessObjectBuilder.buildProject(newProject, sink);

    controller.setAuthenticatedUser(pendingUser);
    controller.handleProjectPostRequest(mimeType, sink.toByteArray(), mockReq, resp);
    assertNotNull(resp);
    assertEquals(403, resp.getStatus());

    // Test getting the collections for a project without proper permissions
    mimeType = "application/xml";
    mockReq = newMockRequest("GET", projectOne.getId() + "/collections", "test.org", 80);
    resp = new MockHttpServletResponse();

    when(requestUtil.buildRequestUrl(any(HttpServletRequest.class)))
        .thenReturn(projectOne.getId() + "/collections");

    controller.setAuthenticatedUser(pendingUser);
    controller.handleProjectCollectionsGetRequest(
        projectOne.getId(), mimeType, null, mockReq, resp);
    assertNotNull(resp);
    assertEquals(403, resp.getStatus());
  }
  /**
   * Tests getting the project's collections
   *
   * @throws InvalidXmlException
   * @throws BizInternalException
   * @throws BizPolicyException
   * @throws IOException
   */
  @Test
  public void testGetProjectsCollections()
      throws InvalidXmlException, BizInternalException, BizPolicyException, IOException {

    final String mimeType = "application/xml";
    final MockHttpServletRequest mockReq =
        newMockRequest("GET", projectOne.getId() + "/collections", "test.org", 80);
    MockHttpServletResponse resp = new MockHttpServletResponse();

    when(requestUtil.buildRequestUrl(any(HttpServletRequest.class)))
        .thenReturn(projectOne.getId() + "/collections");

    controller.setAuthenticatedUser(admin);
    controller.handleProjectCollectionsGetRequest(
        projectOne.getId(), mimeType, null, mockReq, resp);

    assertNotNull(resp);
    assertEquals(resp.getErrorMessage(), 200, resp.getStatus());
    Bop returnedBop =
        businessObjectBuilder.buildBusinessObjectPackage(
            new ByteArrayInputStream(resp.getContentAsByteArray()));
    assertNotNull(returnedBop);

    Set<Collection> collections = returnedBop.getCollections();
    assertNotNull(collections);
    assertEquals(1, collections.size());
  }
  /**
   * Tests adding a project through the API
   *
   * @throws InvalidXmlException
   * @throws BizInternalException
   * @throws BizPolicyException
   * @throws IOException
   */
  @Test
  public void testAddProject()
      throws InvalidXmlException, BizInternalException, BizPolicyException, IOException {
    Project newProject = new Project();
    newProject.setName("Test Project To Add");
    newProject.setDescription("adding this project");
    List<String> numbers = new ArrayList<String>();
    numbers.add("1");
    numbers.add("2");
    newProject.setNumbers(numbers);
    newProject.setFundingEntity("The Fed");
    newProject.setStartDate(new DateTime(2012, 5, 4, 0, 0));
    newProject.setEndDate(new DateTime(2013, 12, 23, 0, 0));
    newProject.addPi(admin.getId());

    final String mimeType = "application/xml";
    final MockHttpServletRequest mockReq = newMockRequest("POST", "/project", "test.org", 80);
    MockHttpServletResponse resp = new MockHttpServletResponse();

    ByteArrayOutputStream sink = new ByteArrayOutputStream();
    businessObjectBuilder.buildProject(newProject, sink);

    controller.setAuthenticatedUser(admin);
    controller.handleProjectPostRequest(mimeType, sink.toByteArray(), mockReq, resp);

    assertNotNull(resp);

    assertEquals(201, resp.getStatus());
    Bop bop =
        businessObjectBuilder.buildBusinessObjectPackage(
            new ByteArrayInputStream(resp.getContentAsByteArray()));

    assertNotNull(bop);

    Set<Project> projects = bop.getProjects();
    assertNotNull(projects);
    assertEquals(1, projects.size());

    Project returnedProject = projects.iterator().next();

    // Have to set the original project id to the id set by the biz service.
    newProject.setId(returnedProject.getId());
    assertEquals(newProject, returnedProject);
  }
  /**
   * Tests that the project metadata is successfully updated.
   *
   * @throws InvalidXmlException
   * @throws ProjectServiceException
   * @throws BizPolicyException
   * @throws IOException
   */
  @Test
  public void testUpdateProject()
      throws InvalidXmlException, BizInternalException, BizPolicyException, IOException {

    Project newProject = new Project(projectOne);
    newProject.setName("Update");
    newProject.setDescription("foo-update");
    newProject.setEndDate(new DateTime(2014, 2, 10, 0, 0));

    final String mimeType = "application/xml";
    final MockHttpServletRequest mockReq =
        newMockRequest("PUT", projectOne.getId(), "test.org", 80);
    MockHttpServletResponse resp = new MockHttpServletResponse();

    ByteArrayOutputStream sink = new ByteArrayOutputStream();
    businessObjectBuilder.buildProject(newProject, sink);

    controller.setAuthenticatedUser(admin);
    controller.handleUpdateProjectRequest(
        projectOne.getId(), mimeType, sink.toByteArray(), mockReq, resp);

    assertNotNull(resp);
    assertEquals(resp.getErrorMessage(), 200, resp.getStatus());

    Bop bop =
        businessObjectBuilder.buildBusinessObjectPackage(
            new ByteArrayInputStream(resp.getContentAsByteArray()));

    assertNotNull(bop);

    Set<Project> projects = bop.getProjects();
    assertNotNull(projects);
    assertEquals(1, projects.size());

    Project returnedProject = projects.iterator().next();
    assertNotNull(returnedProject);

    assertTrue(returnedProject.getName().equalsIgnoreCase(newProject.getName()));
    assertTrue(returnedProject.getDescription().equalsIgnoreCase(newProject.getDescription()));
    assertTrue(returnedProject.getEndDate().equals(newProject.getEndDate()));

    assertTrue(returnedProject.getFundingEntity().equalsIgnoreCase(newProject.getFundingEntity()));
  }
  /**
   * Test getting a project
   *
   * @throws InvalidXmlException
   * @throws BizInternalException
   * @throws BizPolicyException
   * @throws IOException
   */
  @Test
  public void testGetProject()
      throws InvalidXmlException, BizInternalException, BizPolicyException, IOException {

    final String mimeType = "application/xml";
    final MockHttpServletRequest mockReq =
        newMockRequest("GET", projectOne.getId(), "test.org", 80);
    MockHttpServletResponse resp = new MockHttpServletResponse();

    controller.setAuthenticatedUser(admin);
    controller.handleProjectGetRequest(projectOne.getId(), mimeType, null, mockReq, resp);

    assertNotNull(resp);
    assertEquals(resp.getErrorMessage(), 200, resp.getStatus());
    Bop bop =
        businessObjectBuilder.buildBusinessObjectPackage(
            new ByteArrayInputStream(resp.getContentAsByteArray()));
    assertNotNull(bop);
    assertEquals(1, bop.getProjects().size());
    assertEquals(projectOne, bop.getProjects().iterator().next());
  }
  /**
   * Test getting all the projects for a user
   *
   * @throws InvalidXmlException
   * @throws BizInternalException
   * @throws BizPolicyException
   * @throws IOException
   * @throws ServletException
   */
  @Test
  public void testGetAllProjects()
      throws InvalidXmlException, BizPolicyException, IOException, ServletException {

    // Test getting the list of project without logging in
    final String mimeType = "application/xml";
    final MockHttpServletRequest mockReq = newMockRequest("GET", "/project", "test.org", 80);
    MockHttpServletResponse resp = new MockHttpServletResponse();

    controller.handleEmptyGetRequest(mimeType, null, mockReq, resp);

    assertNotNull(resp);
    assertEquals(401, resp.getStatus());

    // Test getting a single project
    ProjectBizService bizService = mock(ProjectBizService.class);
    HashSet<Project> projects = new HashSet<Project>();
    projects.add(projectOne);

    when(bizService.findByAdmin(admin)).thenReturn(projects);
    controller.setBizService(bizService);

    controller.setAuthenticatedUser(admin);
    resp = new MockHttpServletResponse();
    controller.handleEmptyGetRequest(mimeType, null, mockReq, resp);
    assertNotNull(resp);
    assertEquals(200, resp.getStatus());

    Bop bop =
        businessObjectBuilder.buildBusinessObjectPackage(
            new ByteArrayInputStream(resp.getContentAsByteArray()));
    assertNotNull(bop);
    assertEquals(1, bop.getProjects().size());

    // Test a query that returns no projects

    projects.clear();

    when(bizService.findByAdmin(user)).thenReturn(projects);
    controller.setAuthenticatedUser(user);
    resp = new MockHttpServletResponse();
    controller.handleEmptyGetRequest(mimeType, null, mockReq, resp);
    assertNotNull(resp);
    assertEquals(200, resp.getStatus());

    bop =
        businessObjectBuilder.buildBusinessObjectPackage(
            new ByteArrayInputStream(resp.getContentAsByteArray()));
    assertNotNull(bop);
    assertEquals(0, bop.getProjects().size());

    // Test admin sees all projects in the system
    Project newProject = new Project();
    newProject.setId(testProjectIdTwo);
    newProject.setName("Second_Test_Project");
    newProject.setDescription("foo");
    List<String> numbers = new ArrayList<String>();
    numbers.add("54321");
    numbers.add("9876");
    newProject.setNumbers(numbers);
    newProject.setFundingEntity("moo");
    newProject.setStartDate(new DateTime(2012, 5, 4, 0, 0));
    newProject.setEndDate(new DateTime(2013, 12, 23, 0, 0));
    newProject.addPi(user.getId());
    projectService.create(newProject);

    controller.setBizService(projectBizService);
    controller.setAuthenticatedUser(admin);
    resp = new MockHttpServletResponse();
    controller.handleEmptyGetRequest(mimeType, null, mockReq, resp);
    assertNotNull(resp);
    assertEquals(200, resp.getStatus());

    bop =
        businessObjectBuilder.buildBusinessObjectPackage(
            new ByteArrayInputStream(resp.getContentAsByteArray()));
    assertNotNull(bop);
    assertEquals(projectService.getAll().size(), bop.getProjects().size());
  }
  /**
   * Tests that admin can be added and removed from a project
   *
   * @throws IOException
   * @throws BizPolicyException
   * @throws ProjectServiceException
   * @throws InvalidXmlException
   * @throws BizInternalException
   */
  @Test
  public void testUpdateProjectAdmin()
      throws InvalidXmlException, ProjectServiceException, BizPolicyException, IOException,
          BizInternalException {

    // Test adding an admin to the project.
    Project newProject = new Project(projectOne);
    newProject.addPi(user.getId());

    final String mimeType = "application/xml";
    final MockHttpServletRequest mockReq =
        newMockRequest("PUT", projectOne.getId(), "test.org", 80);

    MockHttpServletResponse resp = new MockHttpServletResponse();

    ByteArrayOutputStream sink = new ByteArrayOutputStream();
    businessObjectBuilder.buildProject(newProject, sink);

    controller.setAuthenticatedUser(admin);
    controller.handleUpdateProjectRequest(
        newProject.getId(), mimeType, sink.toByteArray(), mockReq, resp);

    assertNotNull(resp);
    assertEquals(resp.getErrorMessage(), 200, resp.getStatus());

    Bop bop =
        businessObjectBuilder.buildBusinessObjectPackage(
            new ByteArrayInputStream(resp.getContentAsByteArray()));

    assertNotNull(bop);

    Set<Project> projects = bop.getProjects();
    assertNotNull(projects);
    assertEquals(1, projects.size());

    Project returnedProject = projects.iterator().next();
    assertNotNull(returnedProject);

    assertEquals(newProject.getPis().size(), returnedProject.getPis().size());

    // Test removing an admin from the project.
    newProject.removePi(user.getId());

    resp = new MockHttpServletResponse();

    sink = new ByteArrayOutputStream();
    businessObjectBuilder.buildProject(newProject, sink);

    controller.setAuthenticatedUser(admin);
    controller.handleUpdateProjectRequest(
        newProject.getId(), mimeType, sink.toByteArray(), mockReq, resp);

    assertNotNull(resp);
    bop =
        businessObjectBuilder.buildBusinessObjectPackage(
            new ByteArrayInputStream(resp.getContentAsByteArray()));

    assertNotNull(bop);

    projects = bop.getProjects();
    assertNotNull(projects);
    assertEquals(1, projects.size());

    returnedProject = projects.iterator().next();
    assertNotNull(returnedProject);

    assertEquals(newProject.getPis().size(), returnedProject.getPis().size());
  }