Extensions Guide

NetLogo 4.0.5 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 using the NetLogo Extension API.

The NetLogo Extension API Specification contains further details.

Using Extensions

To use an extension in a model, add the extensions keyword at the beginning of the Procedures tab, before declaring any breeds or variables.

After extensions comes a list of extension names in square brackets. For example:

extensions [sound speech]

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.

Where extensions are located

NetLogo will look for extensions in several places:

  1. In the folder of the current model.
  2. The extensions folder in the same location as the NetLogo application.

Each NetLogo extension consists of a folder with the same name as the extension, entirely in lower case. This folder must contain a JAR file with the same name as the folder. For example the sound extension is stored in a folder called sound with a file inside called sound.jar. For more information about the contents of an extension's folder, please see the section of this manual on Writing Extensions.

To install a NetLogo extension for use by any model, put the extension's folder in the extensions directory in the NetLogo directory. Or, you can just keep the extension's folder in the same folder as the model that uses it.

Some extensions depend on additional files. These files will be in the extension's folder along with the JAR file. The folder may also contain other files such as documentation and example models.

Applets

Models saved as applets (using "Save as Applet" on NetLogo's File menu) can make use of extensions. The extension must be placed in the same directory holding the model file. However, applets still cannot use extensions that require additional external jars. (We plan on fixing this in a later release.)

Writing Extensions

We assume you have experience programming in Java.

Summary

A NetLogo extension consists of a folder with the following contents: Required:

Optional:

To build your extension, you must include NetLogo.jar in your class path.

Examples

Several sample extensions with full Java source code are included with NetLogo. Some others are available for download here.

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 0 through n - 1. (Of course, you could easily do this just in NetLogo; it's only an example.)

1. Create extension folder

Since an extension is a folder with several items, we first need to create our folder. In this example, it is called example. We will be doing all of our work in that folder. We will also want to create a src sub-folder to hold our Java code, and a classes sub-folder for the compiled classes.

2. Write primitives

The primitives are implemented as one or more Java classes. The .java files for these classes should be put in the src sub-folder.

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 src/IntegerList.java:

import org.nlogo.api.*;

public class IntegerList extends DefaultReporter
{
    // take one number as input, report 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();   
        
        int n ;
        // use typesafe helper method from 
        // org.nlogo.api.Argument to access argument
        try
        {
            n = args[0].getIntValue();  
        }
        catch( LogoException e )
        {
            throw new ExtensionException( e.getMessage() ) ;
        }
        
        if (n < 0) {
            // signals a NetLogo runtime error to the modeler
            throw new ExtensionException
              ("input must be positive");
        }
        
        // populate the list
        // note that we use Double objects; NetLogo numbers
        // are always doubles
        for (int i = 0; i < n; i++) {
            list.add(new Double(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, 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() 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:

Manifest-Version: 1.0
Extension-Name: example
Class-Manager: SampleExtension
NetLogo-Extension-API-Version: 4.0

The NetLogo-Extension-API-Version line should match the actual version of NetLogo Extension API you are using.

Make sure even the last line ends with a newline character.

4. Create a JAR

To create an extension's JAR file, first compile your classes as usual, either from the command line or using an IDE.

Important: You must add NetLogo.jar (from the NetLogo distribution) to your classpath when compiling.

Here's an example of how compiling your extension might look from the command line:

$ mkdir -p classes     # create the classes subfolder if it does not exist
$ javac -classpath NetLogo.jar -d classes src/IntegerList.java src/SampleExtension.java

You will need to change the classpath argument to point to the NetLogo.jar file from your NetLogo installation. This command line will compile the .java and put the .class files in the classes subfolder.

Then create a JAR containing the resulting class files and the manifest. For example:

$ jar cvfm example.jar manifest.txt -C classes .

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 example folder 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]

Now you can use example:first-n-integers just like it was a built-in NetLogo reporter. For example, select the Interface tab and type in the Command Center:

observer> show example:first-n-integers 5
observer: [0 1 2 3 4]

Extension development tips

Instantiation

Your class manager is instantiated at the time a model using the extension is loaded.

Command and reporter objects are instantiated whenever NetLogo code is compiled that uses your commands and reporters.

Classpath

Don't forget to include NetLogo.jar in your class path when compiling. This is the most common mistake made by new extension authors. (If the compiler can't find NetLogo.jar, you'll get error messages about classes in the org.nlogo.api package not being found.)

Debugging extensions

There are special NetLogo primitives to help you as you develop and debug your extension. These are considered experimental and may 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 extension's directory. Whenever an extension is imported, NetLogo makes all the JARs in its folder available to the extension.

If you plan to distribute your extension to other NetLogo users, make sure to provide installation instructions.

Supporting old Java versions

NetLogo works with Java versions 1.4.1 and later. If you want your extension to be usable by all NetLogo users, your extension should support Java 1.4.1.

The easiest way is to accomplish this is do all your development with the 1.4.1 JDK.

It's also possible to develop for Java 1.4 using the Java 1.5 or 1.6 compiler, but you need to do two things:

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 not yet complete. The API doesn't include everything you might expect to be present. 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.