Implemented optimizations

This commit is contained in:
2023-07-10 22:15:15 +02:00
parent ed9da5ef79
commit e4fd4629a9
10 changed files with 122 additions and 35 deletions
@@ -1,6 +1,6 @@
package de.twomartens.wahlrecht.model.db;
import java.util.Date;
import java.time.Instant;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
@@ -28,12 +28,15 @@ import org.springframework.data.mongodb.core.mapping.Document;
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class Candidate {
@EqualsAndHashCode.Exclude
@Id
ObjectId id;
@EqualsAndHashCode.Exclude
@CreatedDate
Date created;
Instant created;
@EqualsAndHashCode.Exclude
@LastModifiedDate
Date lastModified;
Instant lastModified;
@Indexed
String name;
@@ -29,10 +29,13 @@ import org.springframework.data.mongodb.core.mapping.Document;
@CompoundIndex(def = "{'number': 1, 'electionName': 1}")
public class Constituency {
@EqualsAndHashCode.Exclude
@Id
ObjectId id;
@EqualsAndHashCode.Exclude
@CreatedDate
Instant created;
@EqualsAndHashCode.Exclude
@LastModifiedDate
Instant lastModified;
@@ -1,9 +1,9 @@
package de.twomartens.wahlrecht.model.db;
import de.twomartens.wahlrecht.model.dto.v1.VotingThreshold;
import java.time.Instant;
import java.time.LocalDate;
import java.util.Collection;
import java.util.Date;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
@@ -31,12 +31,15 @@ import org.springframework.data.mongodb.core.mapping.Document;
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class Election {
@EqualsAndHashCode.Exclude
@Id
ObjectId id;
@EqualsAndHashCode.Exclude
@CreatedDate
Date created;
Instant created;
@EqualsAndHashCode.Exclude
@LastModifiedDate
Date lastModified;
Instant lastModified;
@Indexed(unique = true)
String name;
@@ -1,7 +1,7 @@
package de.twomartens.wahlrecht.model.db;
import java.time.Instant;
import java.util.Collection;
import java.util.Date;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
@@ -30,12 +30,15 @@ import org.springframework.data.mongodb.core.mapping.Document;
@CompoundIndex(def = "{'name': 1, 'partyAbbreviation': 1, 'electionName': 1}")
public class Nomination {
@EqualsAndHashCode.Exclude
@Id
ObjectId id;
@EqualsAndHashCode.Exclude
@CreatedDate
Date created;
Instant created;
@EqualsAndHashCode.Exclude
@LastModifiedDate
Date lastModified;
Instant lastModified;
String name;
String partyAbbreviation;
@@ -1,6 +1,6 @@
package de.twomartens.wahlrecht.model.db;
import java.util.Date;
import java.time.Instant;
import java.util.Map;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
@@ -30,12 +30,15 @@ import org.springframework.data.mongodb.core.mapping.Document;
@CompoundIndex(def = "{'abbreviation': 1, 'electionName': 1}")
public class PartyInElection {
@EqualsAndHashCode.Exclude
@Id
ObjectId id;
@EqualsAndHashCode.Exclude
@CreatedDate
Date created;
Instant created;
@EqualsAndHashCode.Exclude
@LastModifiedDate
Date lastModified;
Instant lastModified;
String abbreviation;
String electionName;
@@ -0,0 +1,5 @@
package de.twomartens.wahlrecht.model.internal;
public record NominationId(String electionName, String partyAbbreviation, String name) {
}
@@ -0,0 +1,5 @@
package de.twomartens.wahlrecht.model.internal;
public record PartyId(String electionName, String abbreviation) {
}
@@ -2,7 +2,9 @@ package de.twomartens.wahlrecht.service;
import de.twomartens.wahlrecht.model.db.Candidate;
import de.twomartens.wahlrecht.repository.CandidateRepository;
import java.util.Optional;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;
@@ -12,16 +14,30 @@ import org.springframework.stereotype.Service;
public class CandidateService {
private final CandidateRepository repository;
private Map<String, Candidate> candidates;
public Candidate storeCandidate(@NonNull Candidate candidate) {
Optional<Candidate> foundOptional = repository.findByName(candidate.getName());
if (foundOptional.isPresent()) {
Candidate found = foundOptional.get();
found.setProfession(candidate.getProfession());
return repository.save(found);
} else {
return repository.save(candidate);
if (candidates == null) {
fetchCandidates();
}
Candidate existing = candidates.get(candidate.getName());
boolean needsUpdate = !candidate.equals(existing);
if (!needsUpdate) {
return existing;
}
if (existing != null) {
existing.setProfession(candidate.getProfession());
candidate = existing;
}
candidate = repository.save(candidate);
candidates.put(candidate.getName(), candidate);
return candidate;
}
private void fetchCandidates() {
candidates = repository.findAll().stream()
.collect(Collectors.toMap(Candidate::getName, Function.identity()));
}
}
@@ -2,10 +2,13 @@ package de.twomartens.wahlrecht.service;
import de.twomartens.wahlrecht.model.db.Candidate;
import de.twomartens.wahlrecht.model.db.Nomination;
import de.twomartens.wahlrecht.model.internal.NominationId;
import de.twomartens.wahlrecht.repository.NominationRepository;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Optional;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@@ -15,22 +18,43 @@ public class NominationService {
private final NominationRepository repository;
private final CandidateService candidateService;
private Map<NominationId, Nomination> nominations;
public Nomination storeNomination(Nomination nomination) {
if (nomination == null) {
return null;
}
Optional<Nomination> existingOptional = repository
.findByNameAndElectionNameAndPartyAbbreviation(nomination.getName(),
nomination.getElectionName(), nomination.getPartyAbbreviation());
if (nominations == null) {
fetchNominations();
}
NominationId nominationId = new NominationId(nomination.getElectionName(),
nomination.getPartyAbbreviation(), nomination.getName());
Nomination existing = nominations.get(nominationId);
boolean needsUpdate = !nomination.equals(existing);
if (!needsUpdate) {
return existing;
}
Collection<Candidate> candidates = new ArrayList<>();
nomination.getCandidates()
.forEach(candidate -> candidates.add(candidateService.storeCandidate(candidate)));
if (existingOptional.isPresent()) {
nomination = existingOptional.get();
if (existing != null) {
nomination = existing;
}
nomination.setCandidates(candidates);
return repository.save(nomination);
nomination = repository.save(nomination);
nominations.put(nominationId, nomination);
return nomination;
}
private void fetchNominations() {
nominations = repository.findAll().stream()
.collect(Collectors.toMap(
n -> new NominationId(n.getElectionName(), n.getPartyAbbreviation(), n.getName()),
Function.identity()));
}
}
@@ -2,11 +2,15 @@ package de.twomartens.wahlrecht.service;
import de.twomartens.wahlrecht.model.db.Nomination;
import de.twomartens.wahlrecht.model.db.PartyInElection;
import de.twomartens.wahlrecht.model.internal.PartyId;
import de.twomartens.wahlrecht.repository.PartyRepository;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
@@ -18,6 +22,7 @@ public class PartyService {
private final PartyRepository partyRepository;
private final NominationService nominationService;
private Map<PartyId, PartyInElection> parties = null;
public Collection<PartyInElection> getPartiesByElectionName(String electionName) {
Collection<PartyInElection> parties = partyRepository.findByElectionName(electionName);
@@ -34,22 +39,30 @@ public class PartyService {
abbreviation, electionName);
if (optionalParty.isEmpty()) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND,
"no party found for %s and %s".formatted(electionName, abbreviation));
"no party found for %s and %s" .formatted(electionName, abbreviation));
}
return optionalParty.get();
}
public boolean storeParty(PartyInElection partyInElection) {
if (parties == null) {
fetchParties();
}
boolean createdNew = true;
Optional<PartyInElection> existingOptional = partyRepository
.findByAbbreviationAndElectionName(partyInElection.getAbbreviation(),
partyInElection.getElectionName());
PartyId partyId = new PartyId(partyInElection.getElectionName(),
partyInElection.getAbbreviation());
PartyInElection existing = parties.get(partyId);
boolean needsUpdate = !partyInElection.equals(existing);
if (!needsUpdate) {
return false;
}
Map<Integer, Nomination> constituencyNominations = new HashMap<>();
partyInElection.getConstituencyNominations()
.forEach((key, value) -> constituencyNominations.put(key,
nominationService.storeNomination(value)));
if (existingOptional.isPresent()) {
PartyInElection existing = existingOptional.get();
if (existing != null) {
existing.setName(partyInElection.getName());
if (constituencyNominations.isEmpty()) {
constituencyNominations.putAll(existing.getConstituencyNominations());
@@ -60,8 +73,17 @@ public class PartyService {
partyInElection.setConstituencyNominations(constituencyNominations);
partyInElection.setOverallNomination(
nominationService.storeNomination(partyInElection.getOverallNomination()));
partyRepository.save(partyInElection);
partyInElection = partyRepository.save(partyInElection);
parties.put(partyId, partyInElection);
return createdNew;
}
private void fetchParties() {
List<PartyInElection> allParties = partyRepository.findAll();
parties = allParties.stream()
.collect(Collectors.toMap(
p -> new PartyId(p.getElectionName(), p.getAbbreviation()),
Function.identity()));
}
}