Paramètres ########## Présentation ------------ Dans tout le projet Vitam sont utilisés différents paramètres transmis aux différentes classes ou au différentes méthodes. Afin de ne pas bloquer toute évolution, il est recommandé d'utiliser une classe de paramètres (afin d'éviter de modifier le nombre de paramètres en signature de méthodes) ou d'utiliser une Map. Principe -------- L'idée ici est de mettre en place une mécanique de paramètres commune à tous les modules Vitam. Pour se faire, une interface VitamParameter a été créée. Afin de créer une nouvelle classe de paramètre, il faut alors implémenter cette interface qui retourne une Map de paramètre et un Set de noms de paramètre obligatoires. Cette interface est générique et prend comme typage une énum qui dispose du nom des paramètres. Une classe utilitaire, ParameterHelper a été mise en place afin de vérifier les champs obligatoires. Elle s'appuie sur les deux méthodes définies dans l'interface VitamParameter. Mise en place ------------- Nom des paramètres ****************** Nous souhaitons mettre en place une classe de paramètre pour le module storage, StorageParameter. Il faut dans un premier temps une énum disposant des noms de paramètre. .. code-block:: java public enum StorageParameterName { /** * Nom du premier paramètre **/ field1, /** * Nom du deuxième paramètre **/ field2, /** * Nom du troisième paramètre **/ field3; } Interface ********* Ensuite, une interface va définir les différentes methodes nécéssaires à la classe de paramètre ("définition du contrat") tout en héritant de l'interface VitamParameter (afin que la classe implémentant cette nouvelle interface implémente les deux méthodes getMapParameters et getMandatoriesParameters. .. code-block:: java /** * Exemple d'interface de paramètres **/ public interface StorageParameters extends VitamParameter { /** * Put parameterValue on mapParameters with parameterName key
*
* If parameterKey already exists, then override it (no check) * * @param parameterName the key of the parameter to put on the parameter map * @param parameterValue the value to put on the parameter map * @return actual instance of WorkerParameter (fluent like) * @throws IllegalArgumentException if the parameterName is null or if parameterValue is null or empty **/ StorageParameters putParameterValue(StorageParameterName parameterName, String parameterValue); /** * Get the parameter according to the parameterName * * @param parameterName the wanted parameter * @return the value or null if not found * @throws IllegalArgumentException throws if parameterName is null **/ String getParameterValue(StorageParameterName parameterName); /** * Set from map using String as Key * * @param map the map parameters to set * @return the current instance of WorkerParameters * @throws IllegalArgumentException if parameter key is unknown or if the map is null **/ StorageParameters setMap(Map map); /** * Get the field1 value * * @return the field1's value **/ String getStorageParameterField1(); } Possibilité d'avoir une classe abstraite **************************************** Le but est d'implémenter cette interface. Cependant, il est possible de vouloir plusieurs classes de paramètres en fonction des besoins. Il est alors possible de mettre en place une classe abstraite qui implémente les méthodes communes aux différentes classes de paramètre (par exemple les getters / setters). .. code-block:: java abstract class AbstractStorageParameters implements StorageParameters { @JsonIgnore private final Map mapParameters = new TreeMap<>(); @JsonIgnore private Set mandatoryParameters; AbstractStorageParameters(final Set mandatory) { mandatoryParameters = mandatory; } @JsonCreator protected AbstractStorageParameters(Map map) { mandatoryParameters = StorageParametersFactory.getDefaultMandatory(); setMap(map); } @JsonIgnore @Override public Set getMandatoriesParameters() { return Collections.unmodifiableSet(new HashSet<>(mandatoryParameters)); } @JsonIgnore @Override public Map getMapParameters() { return Collections.unmodifiableMap(new HashMap<>(mapParameters)); } @JsonIgnore @Override public WorkerParameters putParameterValue(StorageParameterName parameterName, String parameterValue) { ParameterHelper.checkNullOrEmptyParameter(parameterName, parameterValue, getMandatoriesParameters()); mapParameters.put(parameterName, parameterValue); return this; } @JsonIgnore @Override public String getParameterValue(StorageParameterName parameterName) { ParametersChecker.checkParameter(String.format(ERROR_MESSAGE, "parameterName"), parameterName); return mapParameters.get(parameterName); } @JsonIgnore @Override public StorageParameters setMap(Map map) { ParametersChecker.checkParameter(String.format(ERROR_MESSAGE, "map"), map); for (String key : map.keySet()) { mapParameters.put(WorkerParameterName.valueOf(key), map.get(key)); } return this; } @JsonIgnore @Override public String getField1() { return mapParameters.get(StorageParameterName.field1); } } Possibilité d'avoir une factory ******************************* On voit dans le code d'exemple l'utilisation d'une factory qui permet d'obetnir la bonne implémentation de la classe de paramètres. En effet, au travers de la factory il est facilement possible de mettre en place les champs requis en fonction des besoins. Par exemple, certains paramètres peuvent être obligatoire pour toutes les implémentations alors que certains sont en plus requis pour certaines implémentations. Voir ici s'il n'est pas possible de faire une factory commune. .. code-block:: java public class WorkerParametersFactory { private static final Set genericMandatories = new HashSet<>(); static { genericMandatories.add(StorageParameterName.field1); genericMandatories.add(StorageParameterName.field2); } private StorageParametersFactory() { // do nothing } // Méthodes de la factory // ... } Code exemple ************ Ensuite, là où les paramètres sont nécéssaires, il suffit d'utiliser l'interface afin d'être le plus générique possible. .. code-block:: java public void methode(StorageParameters parameters) { // Check des paramètres ParameterHelper.checkNullOrEmptyParameters(parameters); // Récupération des paramètres String value = parameters.getField1(); String value 2 = parameters.get(StorageParameterName.field2); // etc... } // Exemple d'ajout de champs requis public void methode2() { Set mandatoryToAdd = new Set<>(); mandatoryToAdd.put(StorageParameterName.field3); // Initialisation des paramètres StorageParameters parameters = StorageParameterFactory.newStorageParameters(mandatoryToAdd); // etc.. } Exemple d'utilisation dans le code Vitam ----------------------------------------- Il est possible de retrouver l'utilisation des paramètres génériques Vitam dans les modules suivants : * Processing * Logbook