Extensions Guide

NetLogo User Manual   

NetLogo allows users to write new commands and reporters in Java and use them in their models. This section of the User Manual introduces this facility.

The first part discusses how to use an extension in your model once you have written one, or once someone has given you one.

The second part is intended for Java programmers interested in writing their own extensions.

Caution! The extensions facility is new in NetLogo 2.0.1 and is still in an early stage of development. Therefore it is considered "experimental". It is likely to continue to change and grow. If you write an extension now, it may need changes in order to continue to work in future NetLogo versions.

The NetLogo API Specification contains further details.

Using Extensions

NetLogo extensions have names that end in ".jar" (short for "Java Archive").

To use an extension in a model, add the __extensions keyword at the beginning of the Procedures tab, before declaring any breeds or variables. (The keyword begins with two underscores to indicate that it is experimental. In a future NetLogo version, it may have a different name and syntax.)

__extensions takes one input, a list of strings. Each string contains the name of a NetLogo extension. For example:

__extensions [ "sound.jar" ]

NetLogo will look for extensions in two places: the directory that holds the model, and the NetLogo extensions folder.

So to install a NetLogo extension for use by any model, put the extension file (for example, "sound.jar") in the "extensions" directory inside the NetLogo directory. Or, you can just keep the extension in the same folder as the model that uses it.

You can also use extensions that are not installed in your NetLogo extensions folder by providing a path relative to the directory that contains the model, or an absolute path:

__extensions [ "lib/sound.jar" ]           ;; relative path
__extensions [ "../../jars/sound.jar" ]    ;; relative path
__extensions [ "c:\\myfiles\\sound.jar" ]  ;; absolute Windows path
__extensions [ "/Users/me/sound.jar" ]     ;; absolute Mac/Unix path

You may also use an extension which is stored on an Internet server instead of your local computer. Just use the URL where you have stored the extension. For example:

__extensions [ "http://yourdomain.net/jars/sound.jar" ]

Using __extensions tells NetLogo to find and open the specified extension and makes the custom commands and reporters found in the extension available to the current model. You can use these commands and reporters just as if they were built-in NetLogo primitives.

To use more than one extension, list each extension seperately. For example,

__extensions [ "sound.jar" "speech.jar" ]

Some extensions depend on additional files. Check the instructions that come with the extension to see if you need to keep any other files with the extension.

Applets

Models saved as applets (using "Save as Applet" on NetLogo's File menu) cannot make use of extensions. (We plan to fix this in a future release.)

Writing Extensions

We assume you have experience programming in Java.

Summary

A NetLogo extension is a JAR that contains: The manifest file must contain three tags:

Tutorial

Let's write an extension that provides a single reporter called first-n-integers.

first-n-integers will take a single numeric input n and report a list of the integers 1 through n. (Of course, you could easily do this just in NetLogo; it's only an example.)

1. Write primitives

A command performs an action; a reporter reports a value. To create a new command or reporter, create a class that implements the interface org.nlogo.api.Command or org.nlogo.api.Reporter, which extend org.nlogo.api.Primitive. In most cases, you can extend the abstract class org.nlogo.api.DefaultReporter or org.nlogo.api.DefaultCommand.

DefaultReporter requires that we implement:

Object report (Argument args[], Context context)
  throws ExtensionException;
Since our reporter takes an argument, we also implement:
Syntax getSyntax();

Here's the implementation of our reporter, in a file called IntegerList.java:

import org.nlogo.agent.LogoList;
import org.nlogo.api.Argument;
import org.nlogo.api.ExtensionException;
import org.nlogo.api.DefaultReporter;
import org.nlogo.api.Syntax;

public class IntegerList extends DefaultReporter
{
    // this reporter takes a number as an argument and returns a list
    public Syntax getSyntax() {
        return Syntax.reporterSyntax(
            new int[] { Syntax.TYPE_NUMBER}, Syntax.TYPE_LIST
        );
    }
    
    public Object report(Argument args[], Context context)
        throws ExtensionException
    {
        // create a NetLogo list for the result
        LogoList list = new LogoList();   
        
        // use typesafe helper method from 
        // org.nlogo.api.Argument to access argument
        int n = args[0].getIntegerValue();  
        
        if (n < 0) {
            // throw org.nlogo.api.ExtensionException to signal
            // a NetLogo runtime error to the modeler
            throw new ExtensionException
              ("input must be positive");
        }
        
        // populate the list 
        for (int i = 1; i <= n; i++) {
            list.add(new Integer(i));
        }
        return list;
    }
}

Notice:

A Command is just like a Reporter, except that reporters implement Object report(...) while commands implement void perform(...).

2. Write a ClassManager

Each extension must include, in addition to any number of command and reporter classes, a class that implements the interface org.nlogo.api.ClassManager. The ClassManager tells NetLogo which primitives are part of this extension. In simple cases, extend the abstract class org.nlogo.api.DefaultClassManager, which provides empty implementations of the methods from ClassManager that you aren't likely to need.

Here's the class manager for our example extension, SampleExtension.java:

import org.nlogo.api.DefaultClassManager;
import org.nlogo.api.PrimitiveManager;

public class SampleExtension extends DefaultClassManager {
    public void load(PrimitiveManager primitiveManager) {
        primitiveManager.addPrimitive
          ("first-n-integers", new IntegerList());
    }
}

addPrimitive() tells NetLogo that our reporter exists and what its name is.

3. Write a Manifest

The extension must also include a manifest. The manifest is a text file which tells NetLogo the name of the extension and the location of the ClassManager.

The manifest must contain three tags:

Here's a manifest for our example extension, manifest.txt:
Extension-Name: example
Class-Manager: SampleExtension
NetLogo-Version: 2.0.2

4. Create a JAR

To create an extension JAR, first compile your classes as usual. Make sure NetLogo.jar (from the NetLogo distribution) is in your classpath. For example:

$ javac -classpath NetLogo.jar IntegerList.java SampleExtension.java
Then create a JAR containing the resulting class files and the manifest. For example:
$ jar cvfm example.jar manifest.txt IntegerList.class SampleExtension.class

For information about manifest files, JAR files and Java tools, see java.sun.com.

5. Use your extension in a model

To use our example extension, put the extension JAR in the NetLogo extensions folder, or in the same directory as the model that will use the extension. At the top of the Procedures tab write:

__extensions [ "example.jar" ]
Now you can use first-n-integers just like it was a built-in NetLogo reporter. For example, select the Interface tab and type in the Command Center:
O> show first-n-integers 5
observer: [1 2 3 4 5]

Extension development tips

Debugging extensions

There are special NetLogo primitives to help you as you develop and debug your extension. Like the extensions facility itself, these are considered experimental and will be changed at a later date. (That's why they have underscores in their name.)

Third party JARs

If your extension depends on code stored in a separate JAR, copy the extra JARs into the "extensions" directory of the NetLogo installation. Whenever an extension is imported, NetLogo makes all the JARs in this folder available to the extension.

If you plan to distribute your extension to other NetLogo users, make sure to provide installation instructions that describe which files should be copied to their extensions directory.

Conclusion

Don't forget to consult the NetLogo API Specification for full details on these classes, interfaces, and methods.

Note that there is no way for the modeler to get a list of commands and reporters provided by an extension, so it's important that you provide adequate documentation.

The extensions facility is considered experimental. This initial API doesn't include everything you might expect. Some facilities exist but are not yet documented. If you don't see a capability you want, please let us know. Do not hesitate to contact us at feedback@ccl.northwestern.edu with questions, as we may be able to find a workaround or provide additional guidance where our documentation is thin.

Hearing from users of this API will also allow us to appropriately focus our efforts for future releases. We are committed to making NetLogo flexible and extensible, and we very much welcome your feedback.