FootballResultReadThroughWriteBehindService.java

package com.mojosoft.demo.service;

import com.hazelcast.map.IMap;
import com.hazelcast.query.Predicate;
import com.hazelcast.query.Predicates;
import com.mojosoft.demo.cache.MatchKey;
import com.mojosoft.demo.config.CacheConfig;
import com.mojosoft.demo.dto.FootballResultDTO;
import com.mojosoft.demo.dto.FootballResultJsonDTO;
import com.mojosoft.demo.dto.UploadResponseDTO;
import com.mojosoft.demo.mapper.MapperHelper;
import com.mojosoft.demo.service.base.FootballResultServiceI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * Base Service class for managing football results cache map.
 */
@Slf4j
@Transactional
@Service("footballResultReadThroughWriteBehindService")
public class FootballResultReadThroughWriteBehindService implements FootballResultServiceI {

  private final IMap<String, FootballResultDTO> resultsMap;
  private final MapperHelper mapper;

  public FootballResultReadThroughWriteBehindService(
      @Qualifier(CacheConfig.FRSLT_READ_THROUGH_WRITE_BEHIND_CACHE)
      IMap<String, FootballResultDTO> resultsMap,
      MapperHelper mapper) {
    this.resultsMap = resultsMap;
    this.mapper = mapper;
  }

  @Override
  public UploadResponseDTO save(List<FootballResultJsonDTO> results)  {
    Map<String, FootballResultDTO> cacheEntries = results.stream()
        .map(mapper::footballMatchJsonToDto)
        .collect(Collectors.toMap(
            dto -> MatchKey.createKey(dto.season(), dto.homeTeam(), dto.awayTeam()),
            dto -> dto));

    resultsMap.putAll(cacheEntries);

    String message = String.format(
        "Successfully uploaded %d football results.", cacheEntries.size());
    return new UploadResponseDTO(cacheEntries.size(), message);
  }

  @Override
  public List<FootballResultDTO> getAll() {
    return resultsMap.values().stream().toList();
  }

  @Override
  public List<FootballResultDTO> getBySeason(String season) {

    Predicate<String, FootballResultDTO> predicate = Predicates.equal("season", season);
    Collection<FootballResultDTO> results = resultsMap.values(predicate);

    return new ArrayList<>(results);
  }

  @Override
  public Optional<FootballResultDTO> getByMatch(String season, String homeTeam, String awayTeam) {

    Predicate<Object, Object> seasonPredicate = Predicates.equal("season", season);
    Predicate<Object, Object> homeTeamPredicate = Predicates.equal("homeTeam", homeTeam);
    Predicate<Object, Object> awayTeamPredicate = Predicates.equal("awayTeam", awayTeam);
    Predicate<String, FootballResultDTO> combinedPredicate =
        Predicates.and(seasonPredicate, homeTeamPredicate, awayTeamPredicate);

    Collection<FootballResultDTO> results = resultsMap.values(combinedPredicate);
    return results.stream().findFirst();
  }
}