ch.openchvote.framework.services.Service Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of framework Show documentation
Show all versions of framework Show documentation
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 extends Service> 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 extends Service> 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