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