NetLogo permet aux utilisateurs d'écrire de nouvelles commandes et de nouveaux reporters en langage Java et de les utiliser dans leurs modèles. Ce chapitre du Guide de l'utilisateur présente cette fonctionnalité.
La première partie explique comment utiliser une extension dans vos modèles une fois que vous l'avez écrite, ou une fois que quelqu'un d'autre l'a écrite pour vous.
La seconde partie est destinée aux programmeurs Java intéressés à écrire leurs propres extensions en utilisant le NetLogo Extension API.
Le document NetLogo Extension API Specification (non traduit) contient d'autres détails.
Pour utiliser une extension dans un modèle, ajoutez le mot-clé extensions au tout début de votre code (dans le panneau "Procedures"), avant toute déclaration de races et/ou de variables.
Après le mot extensions vient une liste (entre crochets) des noms des extensions utilisées. Par exemple :
extensions [sound speech]
L'utilisation de la primitive extensions demande à NetLogo de trouver et d'ouvrir les extensions spécifiées et de mettre les commandes et reporters qui s'y trouvent à disposition du modèle courant. Vous pouvez alors utiliser ces commandes et reporters comme s'ils étaient des primitives NetLogo normales.
NetLogo recherche les extensions à plusieurs endroits :
Chaque extension NetLogo consiste en un dossier portant le même nom que l'extension, nom entièrement en minuscules. Ce dossier doit contenir un fichier JAR portant le même nom que le dossier. Par exemple, l'extension sound est stockée dans un dossier appelé sound, lequel contient un fichier appelé sound.jar. Pour plus d'informations concernant le contenu du dossier d'une extension, voyez la section Programmer des extensions de ce manuel.
Pour installer une extension NetLogo qui puisse être utilisée par n'importe quel modèle, placez le dossier de l'extension dans le dossier extensions du dossier NetLogo. Ou alors, vous pouvez laisser le dossier de l'extension dans le même dossier que le modèle qui l'utilise.
Certaines extensions dépendent de fichiers additionnels. Ces fichiers doivent se trouver dans le dossier de l'extension, avec le fichier JAR. Ce dossier peut aussi contenir d'autres fichiers, tels qu'une documentation et des exemples de modèles.
Les modèles sauvegardés sous forme d'applets (en utilisant la commande "Save as Applet" du menu "File" de NetLogo) peuvent aussi utiliser les extensions. L'extension doit être placée dans le même répertoire que le fichier du modèle. Toutefois, les applets ne peuvent (pour le moment) pas utiliser des extensions qui demandent des fichiers JAR externes. (Cette possibilité est planifiée pour une future version.)
Nous présupposons que vous avez des notions de programmation en Java.
Une extension NetLogo consiste en un dossier contenant :
Obligatoirement :
En option :
Un ou plusieurs modèles NetLogo montrant comment l'extension est utilisée.
Pour construire votre extension, vous devez inclure NetLogo.jar dans le chemin des classes.
Plusieurs exemples d'extensions avec leurs codes sources complets sont livrées avec NetLogo. D'autres sont disponibles à l'adresse http://ccl.northwestern.edu/netlogo/extensions pour téléchargement.
Écrivons une extension, appelée sample et ne comprenant qu'un seul reporter appelé first-n-integers.
Le reporter first-n-integers possède un seul argument n qui demande une valeur numérique, et retourne une liste de nombres entiers allant de 0 à n - 1. (Bien entendu, vous pourriez aussi le faire facilement en NetLogo; il s'agit juste d'un exemple.)
Puisqu'une extension est un dossier contenant plusieurs fichiers, nous devons d'abord créer ce dossier. Dans cet exercice, il est nommé example. Nous allons mettre tout notre travail dans ce dossier. Il nous faut aussi créer un sous-dossier src qui contiendra le code Java et un sous-dossier classes pour les classes compilées.
Les primitives sont implémentées sous la forme d'une ou de plusieurs classes Java. Les fichiers .java pour ces classes doivent être placés dans le sous-dossier src que nous venons de créer.
Une commande accomplit une action, un reporter retourne une valeur. Pour créer une nouvelle commande ou un nouveau reporter, il faut créer une classe qui implémente l'interface de cette nouvelle primitive : org.nlogo.api.Command ou org.nlogo.api.Reporter, qui étend org.nlogo.api.Primitive. Dans la plupart des cas, vous pouvez étendre la classe abstraite org.nlogo.api.DefaultReporter ou org.nlogo.api.DefaultCommand.
DefaultReporter demande que nous implémentions :
Object report (Argument args[], Context context) throws ExtensionException;
Puisque notre reporter possède un argument, nous devons aussi implémenter :
Syntax getSyntax();
Voici l'implémentation de notre reporter, dans un fichier appelé src/IntegerList.java :
import org.nlogo.api.*; public class IntegerList extends DefaultReporter { // reçoit un nombre en entrée, retourne une liste public Syntax getSyntax() { return Syntax.reporterSyntax( new int[] {Syntax.TYPE_NUMBER}, Syntax.TYPE_LIST ); } public Object report(Argument args[], Context context) throws ExtensionException { // crée une liste NetLogo pour le résultat LogoList list = new LogoList(); int n ; // utilise la méthode typesafe helper de // org.nlogo.api.Argument pour accéder aux arguments try { n = args[0].getIntValue(); } catch( LogoException e ) { throw new ExtensionException( e.getMessage() ) ; } if (n < 0) { // signale une erreur d'exécution NetLogo au modélisateur throw new ExtensionException ("l'argument doit être positif"); } // remplit la liste // notez que nous utilisons des objets Double car // les nombres NetLogo sont toujours des doubles for (int i = 0; i < n; i++) { list.add(new Double(i)); } return list; } }
Remarques :
Une commande est presque semblable à un reporter, sauf que le reporter implémente Object report(...) alors qu'une commande implémente void perform(...).
Chaque extension doit inclure, en plus d'un certain nombres de classes de commandes et de reporters, une classe qui implémente l'interface org.nlogo.api.ClassManager. Ce "ClassManager" indique à NetLogo quelles sont les primitives qui font parties de cette extension. Dans les cas simples, étendez la classe abstraite org.nlogo.api.DefaultClassManager qui fournit des implémentations vides pour les méthodes de ClassManager dont vous n'avez pas besoin.
Voici le gestionnaire de classes pour notre exemple d'extension src/SampleExtension.java :
import org.nlogo.api.*;
public class SampleExtension extends DefaultClassManager { public void load(PrimitiveManager primitiveManager) { primitiveManager.addPrimitive ("first-n-integers", new IntegerList()); } }
addPrimitive() dit à NetLogo que notre reporter existe et lui communique son nom.
L'extension doit aussi comprendre un manifeste. Ce manifeste est un fichier texte manifest.txt qui transmet à NetLogo le nom de l'extension et l'emplacement du gestionnaire de classes ClassManager.
Ce manifeste, manifest.txt doit contenir les quatre informations suivantes :
Voici un manifeste pour notre exemple d'extension,
manifest.txt
:
Manifest-Version: 1.0 Extension-Name: example Class-Manager: SampleExtension NetLogo-Extension-API-Version: 4.0
La ligne NetLogo-Extension-API-Version doit contenir la version de l'Extension API de NetLogo que vous utilisez.
Assurez-vous que même la dernière ligne du fichier se termine par un caractère « newline ».
Pour créer un fichier JAR de l'extension, compilez d'abord vos classes comme d'habitude, soit en utilisant la ligne de commande, soit avec votre environnement de développement (IDE) Java.
Important : Vous devez ajouter NetLogo.jar (de la distribution NetLogo) dans vos chemins des classes (classpath) pour la compilation.
Voici un exemple montrant à quoi pourrait ressembler la compilation de votre extension au moyen de la ligne de commandes :
$ mkdir -p classes # create the classes subfolder if it does not exist $ javac -classpath NetLogo.jar -d classes src/IntegerList.java src/SampleExtension.java
Vous devrez certainement modifier l'argument classpath de manière à ce qu'il pointe vers le fichier NetLogo.jar de votre installation. Cette ligne de commandes va compiler vos fichiers .java et mettre les fichiers .class dans le sous-dossier classes.
Il faut ensuite créer un JAR contenant les fichiers class résultants ainsi que le manifeste. Par exemple :
$ jar cvfm example.jar manifest.txt -C classes .
Pour en savoir plus au sujet des fichiers manifest, des fichiers JAR et des outils Java, consultez le site java.sun.com.
Pour pouvoir utiliser l'exemple d'extension dans un modèle, placer le dossier example dans le dossiers des extensions de NetLogo ou dans le même dossier que celui contenant le modèle qui fait appel à cette extension. Écrivez ensuite au tout début du code du modèle (dans le panneau "Procedures") :
extensions [example]
Dès maintenant, vous pouvez utiliser example:first-n-integers comme si c'était un reporter pré-programmé de NetLogo. Par exemple, activez le panneau "Interface" et écrivez dans la Ligne de commandes du Centre de commande :
observer> show example:first-n-integers 5 observer: [0 1 2 3 4]
Votre gestionnaire de classes est instancié au moment où un modèle utilisant l'extension est chargé.
Les objets commande et reporter sont instanciés chaque fois que le code NetLogo qui utilise vos commandes et reporters est compilé.
N'oubliez pas d'inclure le fichier NetLogo.jar dans le chemin des classes pour la compilation. C'est l'erreur la plus fréquente commise par les nouveaux programmeurs d'extensions. (Si le compilateur ne peut pas trouver le fichier NetLogo.jar, il vous envoie des messages d'erreurs indiquant que des classes du paquet org.nlogo.api n'ont pas été trouvées).
Il existe des primitives NetLogo pour vous aider à développer et déverminer votre extension. Elles sont pour le moment expérimentales et leur implémentation est susceptible de changer dans le futur. (C'est pourquoi leur nom commence par deux caractères soulignement.)
Si votre extension dépend de code stocké dans un fichier JAR séparé, copiez ce JAR externe dans le dossier extension. Chaque fois qu'une extension est importée, NetLogo fait en sorte que tous les fichiers JAR de ce dossier soient à disposition de l'extension.
Si vous prévoyez de distribuer votre extension à d'autres utilisateurs de NetLogo, n'oubliez pas de fournir des instructions d'installation adéquates.
NetLogo fonctionne avec les versions 1.4.1 et ultérieures de Java. Si vous voulez que votre extension soit utilisable par tous les utilisateurs de NetLogo, votre extension doit supporter Java 1.4.1.
La manière la plus simple de remplir cette condition est de faire tout votre développement avec le JDK Java 1.4.1.
Il est aussi possible de développer pour Java 1.4 en utilisant le compilateur Java 1.5 ou 1.6, mais vous devez alors faire deux choses :
N'oubliez pas de consulter NetLogo API Specification pour tous les détails concernant ces classes, interfaces et méthodes.
Notez que le programmeur de modèles NetLogo n'a aucun moyen d'obtenir la liste des commandes et des reporters fournis par une extension. C'est pourquoi il est important que vous fournissiez la documentation adéquate.
L'outil extension n'est pour le moment pas complet. Son API ne contient pas tout ce que vous pourriez espérer. Certaines fonctionnalités existent mais ne sont pas encore documentées. Si vous n'y trouvez pas une fonctionnalité que vous aimeriez, faites-nous le savoir. N'hésitez pas à nous contacter à l'adresse feedback@ccl.northwestern.edu pour nous posez des questions, car nous pouvons peut-être trouver une solution de remplacement ou fournir des informations supplémentaires là où notre documentation est lacunaire.
Vos avis, questions et commentaires au sujet de cet API nous permettrons de concentrer nos efforts de manière appropriée pour les versions futures. Nous nous sommes engagés à faire de NetLogo un logiciel souple et extensible, et accueillons bien volontiers votre « feedback ».