ch.openchvote.simpleservices.SimplePersistenceService Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of simple-services Show documentation
Show all versions of simple-services Show documentation
This module provides simple implementations of several infrastructure services.
The newest version!
/*
* Copyright (C) 2024 Berner Fachhochschule https://e-voting.bfh.ch
*
* - This program is free software: you can redistribute it and/or modify -
* - it under the terms of the GNU Affero General Public License as published by -
* - the Free Software Foundation, either version 3 of the License, or -
* - (at your option) any later version. -
* - -
* - This program is distributed in the hope that it will be useful, -
* - but WITHOUT ANY WARRANTY; without even the implied warranty of -
* - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -
* - GNU General Public License for more details. -
* - -
* - You should have received a copy of the GNU Affero General Public License -
* - along with this program. If not, see . -
*/
package ch.openchvote.simpleservices;
import ch.openchvote.framework.exceptions.EventContextException;
import ch.openchvote.framework.party.EventContext;
import ch.openchvote.framework.services.PersistenceService;
import java.util.*;
import static ch.openchvote.framework.exceptions.EventContextException.Type.*;
/**
* This is a simple implementation of the {@link PersistenceService} interface. The purpose of this class is to allow
* parties in tests and simulations to behave like 'real' parties, but without persisting the election data to
* non-volatile memory. For that, the event contexts are kept in a {@link HashMap} with the event ids as keys. Manipulations are
* conducted on a shallow copy of the event context, which allows the rejection of unsaved operations. Saving the event
* context then means to override the entry in the {@link HashMap} by the modified copy.
*/
public final class SimplePersistenceService extends AbstractSimpleService implements PersistenceService {
// hashmap for keeping the contexts of the election event
private final Map> contextMap = Collections.synchronizedMap(new HashMap<>());
// set of ides of locked events
private final Set lockedEvents = Collections.synchronizedSet(new HashSet<>());
// set of ids of sealed events
private final Set sealedEvents = Collections.synchronizedSet(new HashSet<>());
/**
* Explicit no-argument constructor used by {@link java.util.ServiceLoader}.
*/
public SimplePersistenceService() {
}
@Override
public boolean hasContext(String eventId) {
return this.contextMap.containsKey(eventId);
}
@Override
public EventContext, ?> loadContext(String eventId) {
var eventContext = this.contextMap.get(eventId);
if (eventContext == null) {
throw new EventContextException(UNKNOWN_EVENT_ID, eventId);
}
return eventContext.getCopy();
}
@Override
public void saveContext(EventContext, ?> eventContext) {
var eventId = eventContext.getEventId();
if (this.sealedEvents.contains(eventId)) {
throw new EventContextException(EVENT_CONTEXT_SEALED, eventContext);
}
this.contextMap.put(eventId, eventContext);
}
@Override
public synchronized void lockContext(String eventId) {
while (this.lockedEvents.contains(eventId)) {
try {
this.wait();
} catch (InterruptedException exception) {
throw new EventContextException(SYNCHRONIZATION_INTERRUPTED, eventId);
}
}
this.lockedEvents.add(eventId);
}
@Override
public synchronized void unlockContext(String eventId) {
if (this.lockedEvents.remove(eventId)) {
this.notifyAll();
}
}
@Override
public void sealContext(String eventId) {
if (this.hasContext(eventId)) {
this.sealedEvents.add(eventId);
}
}
}