@Override
 public void deleteAccessApproval(UserInfo userInfo, String accessApprovalId)
     throws NotFoundException, DatastoreException, UnauthorizedException, ForbiddenException {
   AccessApproval accessApproval = accessApprovalDAO.get(accessApprovalId);
   verifyAccess(userInfo, accessApproval, ADMINISTER_ACCESS_APPROVAL_ACCESS_TYPE);
   accessApprovalDAO.delete(accessApproval.getId().toString());
 }
  @Test
  public void testCRUD() throws Exception {
    // first of all, we should see the unmet requirement
    RestrictableObjectDescriptor rod =
        AccessRequirementUtilsTest.createRestrictableObjectDescriptor(node.getId());
    List<Long> unmetARIds =
        accessRequirementDAO.unmetAccessRequirements(
            rod,
            Arrays.asList(new Long[] {Long.parseLong(individualGroup.getId())}),
            downloadAccessType);
    assertEquals(1, unmetARIds.size());
    assertEquals(accessRequirement.getId(), unmetARIds.iterator().next());
    // while we're at it, check the edge cases:
    // same result for ficticious principal ID
    unmetARIds =
        accessRequirementDAO.unmetAccessRequirements(
            rod, Arrays.asList(new Long[] {8888L}), downloadAccessType);
    assertEquals(1, unmetARIds.size());
    assertEquals(accessRequirement.getId(), unmetARIds.iterator().next());
    // no unmet requirements for ficticious node ID
    assertTrue(
        accessRequirementDAO
            .unmetAccessRequirements(
                AccessRequirementUtilsTest.createRestrictableObjectDescriptor("syn7890"),
                Arrays.asList(new Long[] {Long.parseLong(individualGroup.getId())}),
                downloadAccessType)
            .isEmpty());
    // no unmet requirement for other type of access
    assertTrue(
        accessRequirementDAO
            .unmetAccessRequirements(
                rod,
                Arrays.asList(new Long[] {Long.parseLong(individualGroup.getId())}),
                updateAccessType)
            .isEmpty());

    // Create a new object
    accessApproval = newAccessApproval(individualGroup, accessRequirement);

    // Create it
    accessApproval = accessApprovalDAO.create(accessApproval);
    String id = accessApproval.getId().toString();
    assertNotNull(id);

    // no unmet requirement anymore ...
    assertTrue(
        accessRequirementDAO
            .unmetAccessRequirements(
                rod,
                Arrays.asList(new Long[] {Long.parseLong(individualGroup.getId())}),
                downloadAccessType)
            .isEmpty());
    // ... but for a different (ficticious) user, the requirement isn't met...
    unmetARIds =
        accessRequirementDAO.unmetAccessRequirements(
            rod, Arrays.asList(new Long[] {8888L}), downloadAccessType);
    assertEquals(1, unmetARIds.size());
    assertEquals(accessRequirement.getId(), unmetARIds.iterator().next());
    // ... and it's still unmet for the second node
    RestrictableObjectDescriptor rod2 =
        AccessRequirementUtilsTest.createRestrictableObjectDescriptor(node2.getId());
    unmetARIds =
        accessRequirementDAO.unmetAccessRequirements(
            rod2,
            Arrays.asList(new Long[] {Long.parseLong(individualGroup.getId())}),
            participateAndDownload);
    assertEquals(1, unmetARIds.size());
    assertEquals(accessRequirement2.getId(), unmetARIds.iterator().next());

    // Fetch it
    AccessApproval clone = accessApprovalDAO.get(id);
    assertNotNull(clone);
    assertEquals(accessApproval, clone);

    // Get by Node Id
    Collection<AccessApproval> ars =
        accessApprovalDAO.getForAccessRequirementsAndPrincipals(
            Arrays.asList(new String[] {accessRequirement.getId().toString()}),
            Arrays.asList(new String[] {individualGroup.getId().toString()}));
    assertEquals(1, ars.size());
    assertEquals(accessApproval, ars.iterator().next());

    // update it
    clone = ars.iterator().next();
    AccessApproval updatedAA = accessApprovalDAO.update(clone);
    assertEquals(
        ((TermsOfUseAccessApproval) clone).getEntityType(),
        ((TermsOfUseAccessApproval) updatedAA).getEntityType());
    assertTrue(
        "etags should be different after an update", !clone.getEtag().equals(updatedAA.getEtag()));

    try {
      accessApprovalDAO.update(clone);
      fail("conflicting update exception not thrown");
    } catch (ConflictingUpdateException e) {
      // We expected this exception
    }

    try {
      // Update from a backup.
      updatedAA = accessApprovalDAO.updateFromBackup(clone);
      assertEquals(clone.getEtag(), updatedAA.getEtag());
    } catch (ConflictingUpdateException e) {
      fail("Update from backup should not generate exception even if the e-tag is different.");
    }

    // Delete it
    accessApprovalDAO.delete(id);
  }