/**
   * Calculate the key value for a summary definition.
   *
   * @param def the definition
   * @param kv the key value
   */
  private static void calculateSummarisedKeyValue(final Definition def, final KeyValue kv) {

    // Load all of the contributed values for this definition/record combination

    List<Definition> definitions = Definition.findSummarisedDefinitions(def);

    List<Object> values = getSummarisedValues(definitions, kv);

    logger.info("Number of values: " + values.size());
    logger.info("Key value id: " + kv.getId());

    // No submitted fields associated with a summary definition
    kv.setSubmittedFieldCount(0);

    boolean refresh = false;

    if (values.size() == 0) {
      // No submitted values exist - delete the key value if one exists
      if (kv.getId() != null && kv.getId() > 0) {
        deleteKeyValue(kv);
        refresh = true;
      }
    } else {
      Object result = KeyValueGenerator.calculateFromObjects(def, values);

      refresh = checkChanged(kv, result);

      kv.setValue(result);
      logger.info("Calculated string value: " + kv.getStringValue());
      logger.info("Calculated double value: " + kv.getDoubleValue());

      // Save the key value
      saveKeyValue(kv);
    }

    if (refresh) {
      recalculateRelatedDefinitions(def, kv);
    }
  }
  /**
   * Calculate the key value for a standard definition.
   *
   * @param def the definition
   * @param kv the key value
   */
  private static void calculateStandardKeyValue(final Definition def, final KeyValue kv) {

    // Load all of the contributed values for this definition/record combination
    List<String> values = new ArrayList<String>();

    try {
      List<SubmittedField> fields =
          SubmittedField.findSubmittedFields(
              def, kv.getPrimaryRecordId(), kv.getSecondaryRecordId(), kv.getTertiaryRecordId());

      for (SubmittedField field : fields) {
        values.add(field.getValue());
      }
    } catch (Exception e) {
      logger.error(
          "Error loading submitted fields for record "
              + kv.getPrimaryRecordId()
              + "-"
              + kv.getSecondaryRecordId()
              + "-"
              + kv.getTertiaryRecordId()
              + ": "
              + e.getMessage());
    }

    logger.info("Number of values: " + values.size());
    logger.info("Values: " + values);
    logger.info("Key value id: " + kv.getId());
    logger.info("Primary record id: " + kv.getPrimaryRecordId());
    logger.info("Secondary record id: " + kv.getSecondaryRecordId());
    logger.info("Tertiary record id: " + kv.getTertiaryRecordId());

    kv.setSubmittedFieldCount(values.size());

    boolean refresh = false;

    if (values.size() == 0) {
      // No submitted values exist - delete the key value if one exists
      if (kv.getId() != null && kv.getId() > 0) {
        deleteKeyValue(kv);
        refresh = true;
      }
    } else {
      // Check to see if the definition is applicable to the key value
      boolean applicable = true;

      if (def.getApplicability() == Applicability.RECORD_SECONDARY
          && StringUtils.isBlank(kv.getSecondaryRecordId())) {
        // Not applicable as no secondary record id is defined
        applicable = false;
      }

      if (def.getApplicability() == Applicability.RECORD_SECONDARY
          && StringUtils.isBlank(kv.getTertiaryRecordId())) {
        // Not applicable as no tertiary record id is defined
        applicable = false;
      }

      if (applicable) {
        Object result = KeyValueGenerator.calculateFromRawStrings(def, values);

        refresh = checkChanged(kv, result);

        kv.setValue(result);
        logger.info("Calculated string value: " + kv.getStringValue());
        logger.info("Calculated double value: " + kv.getDoubleValue());

        // Save the key value
        saveKeyValue(kv);

      } else {
        logger.error(
            "This key value "
                + kv.getPrimaryRecordId()
                + ":"
                + kv.getSecondaryRecordId()
                + ":"
                + kv.getTertiaryRecordId()
                + " is not applicable to this definition: "
                + def.getName());
      }
    }

    if (refresh) {
      recalculateRelatedDefinitions(def, kv);
    }
  }