285 lines
15 KiB
Java
285 lines
15 KiB
Java
package fr.titionfire.ffsaf.domain.service;
|
|
|
|
import fr.titionfire.ffsaf.data.model.MatchModel;
|
|
import fr.titionfire.ffsaf.data.model.MembreModel;
|
|
import fr.titionfire.ffsaf.data.model.PouleModel;
|
|
import fr.titionfire.ffsaf.data.model.TreeModel;
|
|
import fr.titionfire.ffsaf.data.repository.*;
|
|
import fr.titionfire.ffsaf.rest.data.PouleData;
|
|
import fr.titionfire.ffsaf.rest.data.PouleFullData;
|
|
import fr.titionfire.ffsaf.rest.data.TreeData;
|
|
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
|
import fr.titionfire.ffsaf.utils.SecurityCtx;
|
|
import io.quarkus.hibernate.reactive.panache.Panache;
|
|
import io.quarkus.hibernate.reactive.panache.common.WithSession;
|
|
import io.smallrye.mutiny.Uni;
|
|
import jakarta.enterprise.context.ApplicationScoped;
|
|
import jakarta.inject.Inject;
|
|
import org.hibernate.reactive.mutiny.Mutiny;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Objects;
|
|
import java.util.stream.Stream;
|
|
|
|
@WithSession
|
|
@ApplicationScoped
|
|
public class PouleService {
|
|
|
|
@Inject
|
|
PouleRepository repository;
|
|
|
|
@Inject
|
|
CompetitionRepository competRepository;
|
|
|
|
@Inject
|
|
MatchRepository matchRepository;
|
|
|
|
@Inject
|
|
TreeRepository treeRepository;
|
|
|
|
@Inject
|
|
CombRepository combRepository;
|
|
|
|
@Inject
|
|
CompetPermService permService;
|
|
|
|
public Uni<PouleData> getById(SecurityCtx securityCtx, CompetitionSystem system, Long id) {
|
|
return repository.find("systemId = ?1 AND system = ?2", id, system)
|
|
.firstResult()
|
|
.onItem().ifNull().failWith(() -> new RuntimeException("Poule not found"))
|
|
.call(data -> permService.hasViewPerm(securityCtx, data.getCompet()))
|
|
.map(PouleData::fromModel);
|
|
}
|
|
|
|
public Uni<List<PouleData>> getAll(SecurityCtx securityCtx, CompetitionSystem system) {
|
|
return repository.list("system = ?1", system)
|
|
.chain(o ->
|
|
permService.getAllHaveAccess(securityCtx.getSubject())
|
|
.chain(map -> Uni.createFrom().item(o.stream()
|
|
.filter(p -> {
|
|
if (securityCtx.getSubject().equals(p.getCompet().getOwner()))
|
|
return true;
|
|
if (p.getSystem() == CompetitionSystem.SAFCA) {
|
|
if (map.containsKey(p.getCompet().getId()))
|
|
return map.get(p.getId()).equals("admin");
|
|
return securityCtx.roleHas("federation_admin")
|
|
|| securityCtx.roleHas("safca_super_admin");
|
|
}
|
|
return securityCtx.roleHas("federation_admin");
|
|
})
|
|
.map(PouleData::fromModel).toList())
|
|
));
|
|
}
|
|
|
|
public Uni<PouleData> addOrUpdate(SecurityCtx securityCtx, CompetitionSystem system, PouleData data) {
|
|
return repository.find("systemId = ?1 AND system = ?2", data.getId(), system).firstResult()
|
|
.chain(o -> {
|
|
if (o == null) {
|
|
return competRepository.findById(data.getCompet())
|
|
.onItem().ifNull().failWith(() -> new RuntimeException("Competition not found"))
|
|
.call(o2 -> permService.hasEditPerm(securityCtx, o2))
|
|
.chain(competitionModel -> {
|
|
PouleModel model = new PouleModel();
|
|
|
|
model.setId(null);
|
|
model.setSystem(system);
|
|
model.setSystemId(data.getId());
|
|
model.setCompet(competitionModel);
|
|
model.setName(data.getName());
|
|
model.setMatchs(new ArrayList<>());
|
|
model.setTree(new ArrayList<>());
|
|
model.setType(data.getType());
|
|
|
|
return Panache.withTransaction(() -> repository.persist(model));
|
|
});
|
|
} else {
|
|
o.setName(data.getName());
|
|
o.setType(data.getType());
|
|
return Panache.withTransaction(() -> repository.persist(o));
|
|
}
|
|
}).map(PouleData::fromModel);
|
|
}
|
|
|
|
private MatchModel findMatch(List<MatchModel> matchModelList, Long id) {
|
|
return matchModelList.stream().filter(m -> m.getSystemId().equals(id))
|
|
.findFirst().orElse(null);
|
|
}
|
|
|
|
private TreeModel findNode(List<TreeModel> node, Long match_id) {
|
|
return node.stream().filter(m -> m.getMatch().getSystemId().equals(match_id))
|
|
.findFirst().orElse(null);
|
|
}
|
|
|
|
private void flatTreeChild(TreeModel current, ArrayList<TreeModel> node) {
|
|
if (current != null) {
|
|
node.add(current);
|
|
flatTreeChild(current.getLeft(), node);
|
|
flatTreeChild(current.getRight(), node);
|
|
}
|
|
}
|
|
|
|
private void flatTreeChild(TreeData current, ArrayList<TreeData> node) {
|
|
if (current != null) {
|
|
node.add(current);
|
|
flatTreeChild(current.getLeft(), node);
|
|
flatTreeChild(current.getRight(), node);
|
|
}
|
|
}
|
|
|
|
private Uni<TreeModel> persisteTree(TreeData data, List<TreeModel> node, PouleModel poule,
|
|
List<MatchModel> matchModelList) {
|
|
TreeModel mm = findNode(node, data.getMatch());
|
|
if (mm == null) {
|
|
mm = new TreeModel();
|
|
mm.setId(null);
|
|
}
|
|
mm.setLevel(data.getLevel());
|
|
mm.setPoule(poule.getId());
|
|
mm.setMatch(findMatch(matchModelList, data.getMatch()));
|
|
|
|
return Uni.createFrom().item(mm)
|
|
.call(o -> (data.getLeft() == null ? Uni.createFrom().nullItem().invoke(o1 -> o.setLeft(null)) :
|
|
persisteTree(data.getLeft(), node, poule, matchModelList).invoke(o::setLeft)))
|
|
.call(o -> (data.getRight() == null ? Uni.createFrom().nullItem().invoke(o1 -> o.setRight(null)) :
|
|
persisteTree(data.getRight(), node, poule, matchModelList).invoke(o::setRight)))
|
|
.chain(o -> Panache.withTransaction(() -> treeRepository.persist(o)));
|
|
}
|
|
|
|
public Uni<?> syncPoule(SecurityCtx securityCtx, CompetitionSystem system, PouleFullData data) {
|
|
return repository.find("systemId = ?1 AND system = ?2", data.getId(), system)
|
|
.firstResult()
|
|
.onItem().ifNotNull().call(o2 -> permService.hasEditPerm(securityCtx, o2.getCompet()))
|
|
.onItem().ifNull().switchTo(
|
|
() -> competRepository.findById(data.getCompet())
|
|
.onItem().ifNull().failWith(() -> new RuntimeException("Compet not found"))
|
|
.call(o -> permService.hasEditPerm(securityCtx, o))
|
|
.map(o -> {
|
|
PouleModel model = new PouleModel();
|
|
model.setId(null);
|
|
model.setSystem(system);
|
|
model.setSystemId(data.getId());
|
|
model.setMatchs(new ArrayList<>());
|
|
model.setTree(new ArrayList<>());
|
|
model.setCompet(o);
|
|
return model;
|
|
}))
|
|
.call(o -> Mutiny.fetch(o.getMatchs()))
|
|
.call(o -> Mutiny.fetch(o.getTree()))
|
|
.map(o -> {
|
|
o.setName(data.getName());
|
|
o.setType(data.getType());
|
|
|
|
WorkData workData = new WorkData();
|
|
workData.poule = o;
|
|
return workData;
|
|
})
|
|
.call(o -> Panache.withTransaction(() -> repository.persist(o.poule)))
|
|
.call(o -> (data.getMatches() == null || data.getMatches().isEmpty()) ? Uni.createFrom().nullItem() :
|
|
Uni.createFrom()
|
|
.item(data.getMatches().stream().flatMap(m -> Stream.of(m.getC1_id(), m.getC2_id())
|
|
.filter(Objects::nonNull)).distinct().toList())
|
|
.chain(ids -> ids.isEmpty() ? Uni.createFrom().nullItem()
|
|
: combRepository.list("id IN ?1", ids)
|
|
.invoke(o2 -> o2.forEach(m -> o.membres.put(m.getId(), m)))
|
|
)
|
|
)
|
|
.invoke(in -> {
|
|
ArrayList<TreeModel> node = new ArrayList<>();
|
|
for (TreeModel treeModel : in.poule.getTree())
|
|
flatTreeChild(treeModel, node);
|
|
|
|
ArrayList<TreeData> new_node = new ArrayList<>();
|
|
for (TreeData treeModel : data.getTrees())
|
|
flatTreeChild(treeModel, new_node);
|
|
|
|
in.toRmNode = node.stream().filter(m -> new_node.stream()
|
|
.noneMatch(m2 -> m2.getMatch().equals(m.getMatch().getSystemId())))
|
|
.map(TreeModel::getId).toList();
|
|
|
|
in.unlinkNode = node;
|
|
in.unlinkNode.forEach(n -> {
|
|
n.setRight(null);
|
|
n.setLeft(null);
|
|
});
|
|
|
|
in.toRmMatch = in.poule.getMatchs().stream()
|
|
.filter(m -> data.getMatches().stream().noneMatch(m2 -> m2.getId().equals(m.getSystemId())))
|
|
.map(MatchModel::getId).toList();
|
|
})
|
|
.call(in -> in.unlinkNode.isEmpty() ? Uni.createFrom().nullItem() :
|
|
Panache.withTransaction(() -> treeRepository.persist(in.unlinkNode)))
|
|
.call(in -> in.toRmNode.isEmpty() ? Uni.createFrom().nullItem() :
|
|
Panache.withTransaction(() -> treeRepository.delete("id IN ?1", in.toRmNode)))
|
|
.call(in -> in.toRmMatch.isEmpty() ? Uni.createFrom().nullItem() :
|
|
Panache.withTransaction(() -> Uni.join().all(
|
|
in.toRmMatch.stream().map(l -> matchRepository.deleteById(l)).toList())
|
|
.andCollectFailures()))
|
|
.call(in -> data.getMatches().isEmpty() ? Uni.createFrom().nullItem() :
|
|
Uni.join().all(
|
|
data.getMatches().stream().map(m -> {
|
|
MatchModel mm = findMatch(in.poule.getMatchs(), m.getId());
|
|
if (mm == null) {
|
|
mm = new MatchModel();
|
|
mm.setId(null);
|
|
mm.setSystem(system);
|
|
mm.setSystemId(m.getId());
|
|
}
|
|
mm.setPoule(in.poule);
|
|
mm.setPoule_ord(m.getPoule_ord());
|
|
mm.setC1_str(m.getC1_str());
|
|
mm.setC2_str(m.getC2_str());
|
|
mm.setC1_id(in.membres.getOrDefault(m.getC1_id(), null));
|
|
mm.setC2_id(in.membres.getOrDefault(m.getC2_id(), null));
|
|
mm.setEnd(m.isEnd());
|
|
mm.setGroupe(m.getGroupe());
|
|
mm.getScores().clear();
|
|
mm.getScores().addAll(m.getScores());
|
|
|
|
MatchModel finalMm = mm;
|
|
return Panache.withTransaction(() -> matchRepository.persist(finalMm)
|
|
.invoke(o -> in.match.add(o)));
|
|
}).toList())
|
|
.andCollectFailures())
|
|
.call(in -> data.getTrees().isEmpty() ? Uni.createFrom().nullItem() :
|
|
Uni.join().all(data.getTrees().stream()
|
|
.map(m -> persisteTree(m, in.poule.getTree(), in.poule, in.match)).toList())
|
|
.andCollectFailures())
|
|
.map(__ -> "OK");
|
|
}
|
|
|
|
private static class WorkData {
|
|
PouleModel poule;
|
|
HashMap<Long, MembreModel> membres = new HashMap<>();
|
|
List<MatchModel> match = new ArrayList<>();
|
|
List<Long> toRmMatch;
|
|
List<TreeModel> unlinkNode;
|
|
List<Long> toRmNode;
|
|
}
|
|
|
|
public Uni<?> delete(SecurityCtx securityCtx, CompetitionSystem system, Long id) {
|
|
return repository.find("systemId = ?1 AND system = ?2", id, system).firstResult()
|
|
.onItem().ifNull().failWith(() -> new RuntimeException("Poule not found"))
|
|
.call(o -> permService.hasEditPerm(securityCtx, o.getCompet()))
|
|
.call(o -> Mutiny.fetch(o.getMatchs()))
|
|
.call(o -> Mutiny.fetch(o.getTree())
|
|
.call(o2 -> o2.isEmpty() ? Uni.createFrom().nullItem() :
|
|
Uni.createFrom().item(o2.stream().peek(m -> {
|
|
m.setRight(null);
|
|
m.setLeft(null);
|
|
}).toList())
|
|
.call(in -> Panache.withTransaction(() -> treeRepository.persist(in)))
|
|
.map(in -> in.stream().map(TreeModel::getId).toList())
|
|
.call(in -> in.isEmpty() ? Uni.createFrom().nullItem() :
|
|
Panache.withTransaction(() -> treeRepository.delete("id IN ?1", in)))
|
|
)
|
|
)
|
|
.call(o -> o.getMatchs().isEmpty() ? Uni.createFrom().nullItem() :
|
|
Panache.withTransaction(() -> Uni.join().all(
|
|
o.getMatchs().stream().map(l -> matchRepository.deleteById(l.getId())).toList())
|
|
.andCollectFailures()))
|
|
.chain(model -> Panache.withTransaction(() -> repository.delete("id", model.getId())));
|
|
}
|
|
}
|