Configuration des Nodes
Dans la mémoire, la configuration est représentée à l’aide de ConfigurationNodes. Un ConfigurationNode
conserve une valeur (Comme un nombre, une chaîne de caractères ou une liste) ou a des nodes enfants, une structure de configuration arborescente. Lorsque vous utilisez un ConfigurationLoader pour charger ou créer de nouvelles configurations, il retournera la node racine. Il est recommandé que vous gardiez toujours une référence vers cette node stockée quelque part.
Note
Selon le ConfigurationLoader
utilisé, vous pouvez même obtenir un CommentedConfigurationNode, qui, en plus du comportement normal du ConfigurationNode
est capable de conserver un commentaire qui va persister sur le fichier de configuration enregistré.
Valeurs
Valeurs basiques
Les types de valeurs basiques comme les int
, double
, boolean
ou String
ou chacun leur propre méthode getter qui retournera valeur ou une valeur par défaut si la node ne contient pas de valeur de ce type. Vérifions si l’administrateur du serveur veut que le module blockCheats de notre plugin soit activé en vérifiant la valeur au chemin modules.blockCheats.enabled
.
boolean shouldEnable = rootNode.getNode("modules", "blockCheats", "enabled").getBoolean();
Oui, c’est vraiment aussi simple que cela. Comme dans l’exemple ci-dessus, les méthodes comme ConfigurationNode#getInt(), ConfigurationNode#getDouble() ou ConfigurationNode#getString() existent pour vous permettre de récupérer facilement une valeur de ce type.
Pour définir une valeur basique à une node, utilisez juste la méthode ConfigurationNode#setValue(Object). Ne soyez pas confus qu’il accepte un Object
- cela signifie qu’il peut prendre n’importe quoi et qu’il va déterminer comme procéder de lui-même.
Imaginez que le module blockCheats soit désactivé par une commande de l’utilisateur. Ce changement devra être réflété dans la configuration et peut se faire comme suit :
rootNode.getNode("modules", "blockCheats", "enabled").setValue(false);
Avertissement
Les autres types que les types de valeurs de base ne peuvent pas être traités par ces fonctions basiques, et doivent à la place être lues et écrites en utilisant la méthode de (dé)sérialisation décrite ci-dessous. Les types basiques sont ceux qui sont gérés nativements par l’implémentation sous-jacente du format de fichier utilisé par le ConfigurationLoader
, mais généralement incluent les types de données primitifs, ainsi que les String
s et les List
s et les Map
s de types basiques.
(Dé)Sérialisation
Si vous essayez de lire ou d’écrire un objet qui n’est pas un des types de bases mentionnés ci-dessus, vous devrez passer tout d’abord à travers la désérialisation. Dans l”ConfigurationOptions
utilisé pour créer votre ConfigurationNode
racine, il y a une collection de TypeSerializers que Configurate utilise pour convertir vos objets en un ConfigurationNode
et vice versa.
Pour dire à Configurate quel type il doit traiter, nous devons fournir un TypeToken
de guava. Imaginez que nous voulons lire le UUID
d’un joueur depuis la node de configuration towns.aFLARDia.mayor
. Pour faire ceci, nous devrons appeler la méthode getValeur()
tout en fournissant un TypeToken
représentant la classe UUID
.
import java.util.UUID;
UUID mayor = rootNode.getNode("towns", "aFLARDia", "mayor").get(TypeToken.of(UUID.class));
Cela demande à Configurate de localiser le bon TypeSerializer
pour les UUID
s et de l’utiliser pour convertir la valeur stockée en un UUID
. Le TypeSerializer
(et par extension la méthode ci-dessus) peut levé une ObjectMappingException
si il rencontre des données incomplètes ou invalides.
Maintenant si nous voulez écrire un nouvel UUID
vers ce node de configuration, la syntaxe est très similaire. Utilisez la méthode setValue()
avec un TypeToken
et l’objet que vous souhaitez sérialiser.
rootNode.getNode("towns","aFLARDia", "mayor").setValue(TypeToken.of(UUID.class), newUuid);
Note
Sérialiser une valeur va lever une ObjectMappingException
si aucun TypeSerializer
pour le TypeToken
donné ne peut être trouvé.
Pour des classes simples comme UUID
, vous pouvez simplement créer un TypeToken
en utilisant la méthode statique TypeToken.of()
. Mais quand la classe que vous voulez utiliser possède ses propres types de paramètres (comme Map<String,UUID>
) la syntaxe devient un peu plus compliquée. Dans la plupart des cas vous saurez exactement quel types de paramètres ça va être au moment de la compilation, donc vous pouvez juste créer un TypeToken
en tant que classe anonyme : new TypeToken<Map<String, UUID>>()
. De cette façon, même les types génériques peuvent aisément être écrits et lus.
Voir aussi
Pour plus d’informations à propos des TypeToken
s, référez-vous à la documentation guava
Les types sérialisables à l’aide de ces méthodes sont :
N’importe quelle valeur de base (voir ci-dessus)
N’importe quelle
Liste
ouMap
de types sérialisablesLes types
java.util.UUID
,java.net.URL
,java.net.URI
etjava.util.regex.Pattern
Tous les types qui ont été faits sérialisables comme décrit sur la page de sérialisation de la configuration
Par défaut
Contrairement à l’API de Sponge, la librairie Configurate n’utilise pas l”Optional
pour les valeurs qui pourraient ne pas être présentes, mais plutôt null. Alors que les getters des méthodes primitives (comme getBoolean()
ou getInt()
) peuvent retourner false
ou 0
, ceux qui retournent un objet (comme getString()
) vont retourner null
si aucune valeur n’est présente. Si vous ne voulez pas gérer manuellement ces cas spéciaux, vous pouvez utiliser les valeurs par défaut. Chaque méthode getXXX()
discutée plus haut a une forme surchargée acceptant un paramètre supplémentaire comme valeur par défaut.
Jetons un coup d’oeil à l’exemple pour la lecture d’une valeur booléenne à nouveau.
boolean shouldEnable = rootNode.getNode("modules", "blockCheats", "enabled").getBoolean();
Cet appel va retourner false
si la valeur false
est sauvegardé dans la configuration ou si la valeur n’est pas présente dans la configuration. Étant donné que ces deux cas ne sont pas distinguables nous n’avons pas de moyen simple de définir notre variable à false
seulement si c’est la valeur spécifiée dans la configuration. Sauf si nous spécifions true
comme valeur par défaut.
boolean shouldEnable = rootNode.getNode("modules", "blockCheats", "enabled").getBoolean(true);
De la même façon, vous pouvez spécifié des valeurs par défaut sur n’importe quelle valeur que vous récupérer depuis la configuration, évitant ainsi les null
ou les ObjectMappingException
causés par l’absence de la valeur entière. Cela peut aussi fonctionner sur la désérialisation de la méthode getValue()
. Quelques exemples :
String greeting = rootNode.getNode("messages", "greeting").getString("FLARD be with you good man!");
UUID mayor = rootNode.getNode("towns", "aFLARDia", "mayor")
.getValue(TypeToken.of(UUID.class), somePlayer.getUniqueId());
Une autre application utile de ces valeurs par défaut, c’est qu’ils peuvent être copiés vers votre configuration si nécessaire. Lors de la création de votre node racine de configuration, vous pouvez créer votre ConfigurationOptions
avec setShouldCopyDefaults(true)
. Par la suite, quand vous fournirez une valeur par défaut, Configurate vérifiera d’abord si la valeur que vous essayerez de récupérer est présente, et si elle n’e l’est pas, il écrira la valeur par défaut sur la node avant de retourner la valeur par défaut.
Supposons que votre plugin s’exécute pour la première fois et que le fichier de configuration n’existe pas encore. Vous essayez de le charger avec ConfigurationOptions
qui permet de copier les valeurs par défaut et de récupérer une node de configuration vide. Maintenant vous exécutez la ligne rootNode.getNode("modules", "blockCheats", "enabled").getBoolean(true)
. Comme la node n’existe pas encore, Configurate la crée et écrit la valeur true
dessus selon les directives du ConfigurationOptions
avant de la retourner. Lorsque la configuration est alors terminée, la valeur true
va rester sur la node sans jamais être définie explicitement.