package de.uni_bremen.st.quide.persistence.ratings.impl;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import de.uni_bremen.st.quide.datamodel.transferred_data.IViolation;
import de.uni_bremen.st.quide.datamodel.transferred_data.ViolationType;
import de.uni_bremen.st.quide.datamodel.transferred_data.impl.TOFilename;
import de.uni_bremen.st.quide.datamodel.transferred_data.impl.TOFragment;
import de.uni_bremen.st.quide.persistence.data.RatingEntry;
import de.uni_bremen.st.quide.persistence.ratings.IRatingLookUp;
@Service
public class RatingLookUp implements IRatingLookUp {
private static final int ERROR_VALUE = -1;
private static final String byId = "SELECT rating FROM RatingEntry WHERE :type LIKE violationType AND :id = violationId AND userId = :userId";
private static final String byFiles = "SELECT rating FROM RatingEntry "
+ "WHERE ("
+ ":file LIKE (path || '%') OR path IS NULL"
+ ") AND ("
+ ":type LIKE violationType OR violationType IS NULL"
+ ") AND userId = :userId AND violationId IS NULL "
+ "ORDER BY path DESC, violationType DESC";
private static final String forTypes =
"FROM RatingEntry WHERE violationType IS NOT NULL AND violationId IS NULL AND path IS NULL AND userId = :userId";
@PersistenceContext
private EntityManager entityManager;
@Override
@Transactional(readOnly = true)
public void setRating(String userId, final IViolation violation) {
ViolationType type = violation.getViolationType();
Long id = violation.getId();
int rating = byId(userId, type, id);
if (rating == ERROR_VALUE) {
rating = byFiles(userId, type, violation.getLocations());
}
violation.setRating(rating);
}
@Override
@Transactional
public Map<String, Integer> getViolationTypeRatings(String userId) {
Map<String, Integer> map = new HashMap<>();
entityManager.createQuery(forTypes, RatingEntry.class)
.setParameter("userId", userId)
.getResultList()
.forEach(entry -> map.put(entry.getViolationType(), entry.getRating()));
Arrays.stream(ViolationType.values())
.map(type -> type.toString())
.filter(type -> !map.containsKey(type))
.forEach(type -> map.put(type, DEFAULT_RATING));
return map;
}
private int byId(String userId, ViolationType type, Long id) {
List<Integer> result = entityManager.createQuery(byId, Integer.class)
.setParameter("userId", userId)
.setParameter("type", type.toString())
.setParameter("id", id)
.setMaxResults(1)
.getResultList();
return result.isEmpty() ? ERROR_VALUE : result.get(0);
}
private int byFiles(String userId, ViolationType type, TOFragment... locations) {
return Arrays.stream(locations)
.map(TOFragment::getFile)
.map(TOFilename::getName)
.distinct()
.mapToInt(file -> byFile(userId, type, file))
.max()
.orElse(DEFAULT_RATING);
}
private int byFile(String userId, ViolationType type, String file) {
List<Integer> list = entityManager.createQuery(byFiles, Integer.class)
.setParameter("userId", userId)
.setParameter("type", type.toString())
.setParameter("file", file)
.setMaxResults(1)
.getResultList();
return list.isEmpty() ? DEFAULT_RATING : list.get(0);
}
}