Repository: corona-warn-app/cwa-server
File: services/distribution/src/main/java/app/coronawarn/server/services/distribution/statistics/StatisticsToProtobufMapping.java (Java)

Code before:
  private List<KeyFigureCard> buildAllKeyFigureCards(List<StatisticsJsonStringObject> jsonStringObjects) {
    Map<Integer, Optional<KeyFigureCard>> figureCardMap = new HashMap<>();

    figureCardMap.put(INFECTIONS_CARD.ordinal(), Optional.empty());
    figureCardMap.put(INCIDENCE_CARD.ordinal(), Optional.empty());
    figureCardMap.put(KEY_SUBMISSION_CARD.ordinal(), Optional.empty());
    figureCardMap.put(REPRODUCTION_NUMBER_CARD.ordinal(), Optional.empty());
    figureCardMap.put(FIRST_VACCINATION_CARD.ordinal(), Optional.empty());
    figureCardMap.put(FULLY_VACCINATED_CARD.ordinal(), Optional.empty());
    figureCardMap.put(VACCINATION_DOSES_CARD.ordinal(), Optional.empty());
    figureCardMap.put(HOSPITALIZATION_INCIDENCE_CARD.ordinal(), Optional.empty());
    figureCardMap.put(INTENSIVE_CARE_CARD.ordinal(), Optional.empty());

    List<StatisticsJsonStringObject> orderedList = jsonStringObjects.stream()
        .sorted(Comparator.comparing(a -> effectiveDateStringToLocalDate(a.getEffectiveDate())))
        .collect(Collectors.toList());
    Collections.reverse(orderedList);

    List<StatisticsJsonStringObject> collectedJsonObjects = new ArrayList<>();

    for (var stat : orderedList) {
      collectedJsonObjects.add(stat);
      Arrays.stream(Cards.values()).map(card -> card.ordinal())
          .filter(e -> getAllCardIdSequence().contains(e.intValue()))
          .forEach(id -> {
            if (figureCardMap.get(id).isEmpty()) {
              KeyFigureCard card;
              try {
                card = keyFigureCardFactory.createKeyFigureCard(stat, id);
                logger.info("[{}] {} successfully created", stat.getEffectiveDate(), getNameFor(id));
                figureCardMap.put(id, Optional.of(card));
              } catch (MissingPropertyException ex) {
                logger.warn("[{}] {}", stat.getEffectiveDate(), ex.getMessage());
              }
            }
          });

      if (figureCardMap.values().stream().allMatch(Optional::isPresent)) {
        break;
      }
    }

    if (logger.isDebugEnabled()) {
      logger.debug("The following statistics JSON entries were used to create the cards. Null values are omitted.");
      for (var stat : collectedJsonObjects) {
        var jsonString = SerializationUtils.stringifyObject(stat);
        logger.debug("[{}] {}", stat.getEffectiveDate(), jsonString);
      }
    }

    var emptyCard = keyFigureCardFactory.createKeyFigureCard(jsonStringObjects.get(0), EMPTY_CARD.ordinal());

Review comment (bug):
I think this does not reliably avoid NPEs for `figureCardMap.get(id).isEmpty()`. Technically, after the filter statement, there could still be a card id for which we forgot to put something into `figureCardMap`.

How about something like this:

```java
getAllCardIdSequence()
  .filter(id -> figureCardMap.has(id))
  .forEach(/*...*/)
```

We could also add a `warn` log in the filter statement if something is filtered out (or even error)

Code after:
  private List<KeyFigureCard> buildAllKeyFigureCards(List<StatisticsJsonStringObject> jsonStringObjects) {
    Map<Integer, Optional<KeyFigureCard>> figureCardMap = new HashMap<>();

    figureCardMap.put(INFECTIONS_CARD.ordinal(), Optional.empty());
    figureCardMap.put(INCIDENCE_CARD.ordinal(), Optional.empty());
    figureCardMap.put(KEY_SUBMISSION_CARD.ordinal(), Optional.empty());
    figureCardMap.put(REPRODUCTION_NUMBER_CARD.ordinal(), Optional.empty());
    figureCardMap.put(FIRST_VACCINATION_CARD.ordinal(), Optional.empty());
    figureCardMap.put(FULLY_VACCINATED_CARD.ordinal(), Optional.empty());
    figureCardMap.put(VACCINATION_DOSES_CARD.ordinal(), Optional.empty());
    figureCardMap.put(HOSPITALIZATION_INCIDENCE_CARD.ordinal(), Optional.empty());
    figureCardMap.put(INTENSIVE_CARE_CARD.ordinal(), Optional.empty());

    List<StatisticsJsonStringObject> orderedList = jsonStringObjects.stream()
        .sorted(Comparator.comparing(a -> effectiveDateStringToLocalDate(a.getEffectiveDate())))
        .collect(Collectors.toList());
    Collections.reverse(orderedList);

    List<StatisticsJsonStringObject> collectedJsonObjects = new ArrayList<>();

    for (var stat : orderedList) {
      collectedJsonObjects.add(stat);
      List<Integer> cardIdSequence = getAllCardIdSequence();
      Arrays.stream(Cards.values()).map(Cards::ordinal)
          .filter(cardIdSequence::contains)
          .filter(figureCardMap::containsKey)
          .forEach(id -> {
            if (figureCardMap.get(id).isEmpty()) {
              KeyFigureCard card;
              try {
                card = keyFigureCardFactory.createKeyFigureCard(stat, id);
                logger.info("[{}] {} successfully created", stat.getEffectiveDate(), getNameFor(id));
                figureCardMap.put(id, Optional.of(card));
              } catch (MissingPropertyException ex) {
                logger.warn("[{}] {}", stat.getEffectiveDate(), ex.getMessage());
              }
            }
          });

      if (figureCardMap.values().stream().allMatch(Optional::isPresent)) {
        break;
      }
    }

    if (logger.isDebugEnabled()) {
      logger.debug("The following statistics JSON entries were used to create the cards. Null values are omitted.");
      for (var stat : collectedJsonObjects) {
        var jsonString = SerializationUtils.stringifyObject(stat);
        logger.debug("[{}] {}", stat.getEffectiveDate(), jsonString);
      }
    }