All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ch.openchvote.simpleservices.SimplePersistenceService Maven / Gradle / Ivy

Go to download

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);
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy