@Override
  public void update(
      Comment comment, Map<String, JSONObject> commentProperties, boolean dispatchEvent) {
    if (comment == null) {
      throw new IllegalArgumentException("Comment must not be null");
    }
    if (comment.getId() == null) {
      throw new IllegalArgumentException("Comment ID must not be null");
    }

    // create persistable generic value
    GenericValue commentGV;

    // We need an in-memory copy of the old comment so we can pass it through in the fired event and
    // to make sure
    // that some fields have changed.
    Comment originalComment = getCommentById(comment.getId());
    if (originalComment == null) {
      throw new IllegalArgumentException(
          "Can not find a comment in the datastore with id: " + comment.getId());
    }

    // Make sure that either the comment body or visibility data has changed, otherwise do not
    // update the datastore
    if (!areCommentsEquivalent(originalComment, comment)) {
      try {
        commentGV = delegator.findById(COMMENT_ENTITY, comment.getId());
        populateGenericValueFromComment(comment, commentGV);
        commentGV.store();
      } catch (GenericEntityException e) {
        throw new DataAccessException(e);
      }

      // Update the issue object
      IssueFactory issueFactory = ComponentAccessor.getComponentOfType(IssueFactory.class);
      GenericValue issueGV = comment.getIssue().getGenericValue();
      MutableIssue mutableIssue = issueFactory.getIssue(issueGV);
      mutableIssue.setUpdated(UtilDateTime.nowTimestamp());
      mutableIssue.store();
    }

    // Update comment properties
    if (commentProperties != null) {
      setProperties(comment.getAuthorApplicationUser(), comment, commentProperties);
    }

    // Dispatch an event if required
    if (dispatchEvent) {
      dispatchIssueCommentEditedEvent(
          comment,
          MapBuilder.build(
              "eventsource",
              IssueEventSource.ACTION,
              EVENT_ORIGINAL_COMMENT_PARAMETER,
              originalComment));
    }
  }
 /**
  * We need to make sure that we account for failed upgrades - the QA-EACJ migration showed that
  * the table may linger but the sequence ids go
  *
  * @param entityName
  * @param nextId
  * @throws GenericEntityException
  */
 private void setNextId(String entityName, Long nextId) throws GenericEntityException {
   final GenericDelegator delegator = getDelegator();
   // First ensure we have an entry in SequenecValueItem table
   delegator.getNextSeqId(entityName);
   // Now set it to nextId
   GenericValue sequenceItem =
       EntityUtil.getOnly(
           delegator.findByAnd("SequenceValueItem", ImmutableMap.of("seqName", entityName)));
   if (sequenceItem != null) {
     sequenceItem.set("seqId", nextId);
     sequenceItem.store();
     delegator.refreshSequencer();
   }
 }
 @Override
 public Attachment setZip(Attachment attachment, boolean zip) {
   GenericValue attachmentGV;
   try {
     attachmentGV =
         ofBizDelegator.findById(AttachmentConstants.ATTACHMENT_ENTITY_NAME, attachment.getId());
     attachmentGV.put("zip", zip ? IS_ZIP : NOT_ZIP);
     attachmentGV.store();
   } catch (DataAccessException e) {
     log.error("Unable to find a file attachment with id: " + attachment.getId());
     throw e;
   } catch (GenericEntityException e) {
     log.error("Unable to find a file attachment with id: " + attachment.getId());
     throw new DataAccessException(e);
   }
   return new Attachment(issueManager, attachmentGV, attachment.getProperties());
 }
  @Test
  public void testDefaultAssigneeWithUnassigned()
      throws DefaultAssigneeException, GenericEntityException, OperationNotPermittedException,
          InvalidUserException, InvalidCredentialException {
    final User projectLead = userMockFactory.getProjectLead();
    final GenericValue projectWithDefaultAssigneeLead =
        projectMockFactory.getProjectWithDefaultAssigneeLead();
    final GenericValue projectWithDefaultUnassigned =
        projectMockFactory.getProjectWithDefaultUnassigned();

    // Should be false as unassigned is turned off and project lead cannot be assigned issues.
    _testNoDefaultAssignee(projectWithDefaultUnassigned, null);

    when(permissionManager.hasPermission(
            Permissions.ASSIGNABLE_USER, projectWithDefaultAssigneeLead, projectLead))
        .thenReturn(Boolean.TRUE);
    when(permissionManager.hasPermission(
            Permissions.ASSIGNABLE_USER, projectWithDefaultUnassigned, projectLead))
        .thenReturn(Boolean.TRUE);

    // Should be false as unassigned is turned off and the lead is null so it fails
    _testNoDefaultAssignee(projectWithDefaultUnassigned, null);

    projectWithDefaultUnassigned.set("lead", projectLead.getName());
    projectWithDefaultUnassigned.store();

    // Should be true as unassigned is turned off and project lead can be assigned issues,
    // so it defaults to project lead.
    assertTrue(testedObject.isDefaultAssignee(projectWithDefaultUnassigned, null));

    final User defaultAssignee =
        testedObject.getDefaultAssignee(projectWithDefaultUnassigned, null);
    assertEquals(projectLead, defaultAssignee);

    // Turn on unassigned
    ComponentAccessor.getApplicationProperties()
        .setOption(APKeys.JIRA_OPTION_ALLOWUNASSIGNED, true);

    // Reset permissions

    // Should be true as unassigned is turned on
    _testDefaultAssignee(projectWithDefaultUnassigned, null, null);
  }