@CheckForNull
  public Duration calculate(DefaultIssue issue) {
    if (issue.isFromExternalRuleEngine()) {
      return issue.effort();
    }
    Rule rule = ruleRepository.getByKey(issue.ruleKey());
    DebtRemediationFunction fn = rule.getRemediationFunction();
    if (fn != null) {
      verifyEffortToFix(issue, fn);

      Duration debt = Duration.create(0);
      String gapMultiplier = fn.gapMultiplier();
      if (fn.type().usesGapMultiplier() && !Strings.isNullOrEmpty(gapMultiplier)) {
        int effortToFixValue = MoreObjects.firstNonNull(issue.gap(), 1).intValue();
        // TODO convert to Duration directly in Rule#remediationFunction -> better performance + error handling
        debt = durations.decode(gapMultiplier).multiply(effortToFixValue);
      }
      String baseEffort = fn.baseEffort();
      if (fn.type().usesBaseEffort() && !Strings.isNullOrEmpty(baseEffort)) {
        // TODO convert to Duration directly in Rule#remediationFunction -> better performance + error handling
        debt = debt.add(durations.decode(baseEffort));
      }
      return debt;
    }
    return null;
  }
@Test
  public void no_debt_if_function_is_not_defined() {
    DefaultIssue issue = new DefaultIssue().setRuleKey(rule.getKey());

    assertThat(underTest.calculate(issue)).isNull();
  }