@VisibleForTesting
  static IssueCache.Issue toProto(IssueCache.Issue.Builder builder, DefaultIssue defaultIssue) {
    builder.clear();
    builder.setKey(defaultIssue.key());
    builder.setRuleType(defaultIssue.type().getDbConstant());
    ofNullable(defaultIssue.getCleanCodeAttribute()).ifPresent(value -> builder.setCleanCodeAttribute(value.name()));
    ofNullable(defaultIssue.componentUuid()).ifPresent(builder::setComponentUuid);
    builder.setComponentKey(defaultIssue.componentKey());
    builder.setProjectUuid(defaultIssue.projectUuid());
    builder.setProjectKey(defaultIssue.projectKey());
    builder.setRuleKey(defaultIssue.ruleKey().toString());
    ofNullable(defaultIssue.language()).ifPresent(builder::setLanguage);
    ofNullable(defaultIssue.severity()).ifPresent(builder::setSeverity);
    builder.setManualSeverity(defaultIssue.manualSeverity());
    ofNullable(defaultIssue.message()).ifPresent(builder::setMessage);
    ofNullable(defaultIssue.getMessageFormattings()).ifPresent(m -> builder.setMessageFormattings((DbIssues.MessageFormattings) m));
    ofNullable(defaultIssue.line()).ifPresent(builder::setLine);
    ofNullable(defaultIssue.gap()).ifPresent(builder::setGap);
    ofNullable(defaultIssue.effort()).map(Duration::toMinutes).ifPresent(builder::setEffort);
    builder.setStatus(defaultIssue.status());
    ofNullable(defaultIssue.resolution()).ifPresent(builder::setResolution);
    ofNullable(defaultIssue.assignee()).ifPresent(builder::setAssigneeUuid);
    ofNullable(defaultIssue.assigneeLogin()).ifPresent(builder::setAssigneeLogin);
    ofNullable(defaultIssue.checksum()).ifPresent(builder::setChecksum);
    ofNullable(defaultIssue.authorLogin()).ifPresent(builder::setAuthorLogin);
    defaultIssue.defaultIssueComments().forEach(c -> builder.addComments(toProtoComment(c)));
    ofNullable(defaultIssue.tags()).ifPresent(t -> builder.setTags(String.join(TAGS_SEPARATOR, t)));
    ofNullable(defaultIssue.codeVariants()).ifPresent(codeVariant -> builder.setCodeVariants(String.join(TAGS_SEPARATOR, codeVariant)));
    ofNullable(defaultIssue.getLocations()).ifPresent(l -> builder.setLocations((DbIssues.Locations) l));
    defaultIssue.getRuleDescriptionContextKey().ifPresent(builder::setRuleDescriptionContextKey);
    builder.setIsFromExternalRuleEngine(defaultIssue.isFromExternalRuleEngine());
    builder.setCreationDate(defaultIssue.creationDate().getTime());
    ofNullable(defaultIssue.updateDate()).map(Date::getTime).ifPresent(builder::setUpdateDate);
    ofNullable(defaultIssue.closeDate()).map(Date::getTime).ifPresent(builder::setCloseDate);
    ofNullable(defaultIssue.currentChange()).ifPresent(c -> builder.setCurrentChanges(toProtoIssueChanges(c)));
    builder.setIsNew(defaultIssue.isNew());
    builder.setIsOnChangedLine(defaultIssue.isOnChangedLine());
    builder.setIsPrioritizedRule(defaultIssue.isPrioritizedRule());
    builder.setIsNewCodeReferenceIssue(defaultIssue.isNewCodeReferenceIssue());
    builder.setIsCopied(defaultIssue.isCopied());
    builder.setBeingClosed(defaultIssue.isBeingClosed());
    builder.setOnDisabledRule(defaultIssue.isOnDisabledRule());
    builder.setIsChanged(defaultIssue.isChanged());
    builder.setSendNotifications(defaultIssue.mustSendNotifications());
    ofNullable(defaultIssue.selectedAt()).ifPresent(builder::setSelectedAt);
    builder.setQuickFixAvailable(defaultIssue.isQuickFixAvailable());
    builder.setIsNoLongerNewCodeReferenceIssue(defaultIssue.isNoLongerNewCodeReferenceIssue());
    defaultIssue.getAnticipatedTransitionUuid().ifPresent(builder::setAnticipatedTransitionUuid);


    for (Map.Entry<SoftwareQuality, Severity> impact : defaultIssue.impacts().entrySet()) {
      builder.addImpacts(IssueCache.Impact.newBuilder()
        .setSoftwareQuality(impact.getKey().name())
        .setSeverity(impact.getValue().name())
        .build());
    }
    for (FieldDiffs fieldDiffs : defaultIssue.changes()) {
      builder.addChanges(toProtoIssueChanges(fieldDiffs));
    }

    return builder.build();
  }
@Test
  public void toProto_whenCleanCodeAttributeIsSet_shouldCopyToIssueProto() {
    DefaultIssue defaultIssue = createDefaultIssueWithMandatoryFields();
    defaultIssue.setCleanCodeAttribute(CleanCodeAttribute.FOCUSED);

    IssueCache.Issue issue = ProtobufIssueDiskCache.toProto(IssueCache.Issue.newBuilder(), defaultIssue);

    assertThat(issue.getCleanCodeAttribute()).isEqualTo(CleanCodeAttribute.FOCUSED.name());
  }