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

ch.openchvote.framework.services.Service Maven / Gradle / Ivy

Go to download

This module offers a generic framework for implementing cryptographic protocols such as CHVote.

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.framework.services;

import ch.openchvote.framework.annotations.service.Priority;
import ch.openchvote.framework.exceptions.FrameworkException;
import ch.openchvote.framework.interfaces.Identifiable;

import java.util.Comparator;
import java.util.ServiceLoader;

import static ch.openchvote.framework.exceptions.FrameworkException.Type.SERVICE_NOT_AVAILABLE;

/**
 * This is the common interface that all services must implement for being used within the framework. It furthermore
 * provides a static helper method {@link Service#load(Class)} for loading a service of a given service interface type.
 */
public interface Service {

    /**
     * Returns an instance of a service class implementing the provided service interface. If multiple service classes
     * are available, the one with the highest priory value is selected. Priority values can be specified using the
     * {@link Priority} annotation. If no such annotation is available, the default value 0 is taken into consideration.
     * If multiple service classes with the same maximum priority value are available, one of them is selected without
     * specifying which one. If no suitable service classes are available, an exception is thrown.
     *
     * @param service The given class object of the service interface to load
     * @param      The generic type of the service interface
     * @return An instance of a service class implementing the provided service interface
     * @throws FrameworkException if no service implementation is available
     */
    static  T load(Class service) throws FrameworkException {
        var providers = ServiceLoader.load(service);
        return providers.stream()
                .max(Comparator.comparingInt(provider -> Service.getAssignedPriority(provider.type())))
                .map(ServiceLoader.Provider::get)
                .orElseThrow(() -> new FrameworkException(SERVICE_NOT_AVAILABLE, service));
    }

    /**
     * Return the service class's priority value as specified using the {@link Priority} annotation. If no such
     * annotation has been assigned in the specified class, the default value 0 is returned.
     *
     * @param service The given service class
     * @return The assigned priority value
     */
    static int getAssignedPriority(Class service) {
        var annotationClass = Priority.class;
        return service.isAnnotationPresent(annotationClass)
                ? service.getAnnotation(annotationClass).value()
                : 0;
    }

    /**
     * Returns the id of a given service class. The id corresponds to the service class's fully qualified name (the name
     * of the class prefixed with the package name), which is obtained by calling {@link Class#getName()}.
     *
     * @param service The given service class
     * @return The id of the given role
     */
    static String getId(Class service) {
        return service.getName();
    }

    /**
     * Many services require their consumers to subscribe to the service before using it. From such consumers within
     * this framework, it is expected that they do and undo their subscriptions in a uniform way. By implementing this
     * interface, they are all required to provide corresponding methods {@link Subscriber#subscribeToServices()} and
     * {@link Subscriber#unsubscribeFromServices()}, in which the service subscribing/unsubscribing is handled.
     */
    interface Subscriber extends Identifiable {

        /**
         * Subscribes the consumer to all services.
         */
        void subscribeToServices();

        /**
         * Unsubscribes the consumer from all services.
         */
        void unsubscribeFromServices();

    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy