JMRI: Introduction to JMRI Library Structure
Author: Bob Jacobsen
Keywords: JMRI technical code

# JMRI Code: Introduction to JMRI Library Structure

This page is the top-level introduction to how the JMRI software is organized.

## Static Structure

At the highest level, we separate test source code from distributed source code by putting both in separate directories within the development directory: "java/test" and "java/src". This makes it easy to compile a version without test code, to apply different tools to the two types of code, etc.

In addition to the source code, JMRI expects to find directories within the current directory:

help/
  The in-program help files
jython/
  Various sample and test scripts.
lib/
  Jar files and linkable libraries that JMRI relies on.
resources/
  Image and sound resources used by the library, and available for user selection. These can be directly browsed.
web/
  Files for JMRI's built-in web servers
xml/
  XML files for decoder and programmer definitions, signal system definitions, Schema and DTDs used to validate JMRI's XML persistance, and others.

plus specific files used by the build process, to control logging, and containing the JMRI license.

### Static Package and Class Structure

For interfaces in the `jmri` package, which might be implemented by lots of different layout hardware types, `jmri.InstanceManager` satisfies these requests by providing access to hardware-specific `Managers`, from which you can get the hardware-specific items that represent what you want to access on the layout.

Because we have different hardware implementations in subpackages of the `jmrix` package, those are also accessed via the `ConnectionManager`classes, which provide access to generally-defined objects.

Other code should, in general, not reference those specific implementations directly.

(The help/en/packages section of the in-program help files are also organized this way)

More specifically:

jmri
  Contains interfaces and base class implementations for the common JMRI objects. This is the basic interface to the overall JMRI library and its capabilities.
  Code in the jmri package should depend on no other JMRI code, though it may depend on externals (log4j, etc.) There should be no AWT or Swing code here.
jmrit
  Contains commonly useful tools and extensions.
  It can depend on jmri.* and externals. It must not depend on jmrix.*
jmrix
  Contains code that is specific to a particular external system. This includes implementations of jmri interfaces that are specific to a system, plus system-specific tools (in the long run, those could certainly be separated).
  jmrix can depend on jmri and externals, but not jmrit.
  Only system-specific code should access within the jmrix subpackages.
jmris
  contains all the code for the server implementation for the JMRI interfaces.
managers
  Abstract and default implementations of the various JMRI type managers, e.g. the concrete classes from the InstanceManager. It's a historical accident that these have a package of their own, rather than being rolled into jmri.implementations.
implementations
  Abstract and default implementations of the jmri objects; no system specific or Swing code allowed here. These are in a separate package, rather than in jmri itself, to make the jmri package simpler to understand for people who just want to use the library.
util
  General service classes that are not user level tools. Should not depend on jmri.jmrit or jmri.jmrix packages. The jmri.util.swing subpackage provides Swing utilities.

  This is an exception to the idea that packages should not directly reference classes across the tree: these utility classes are generally available for use.

apps
  Separate from the jmri package tree, this contains application classes and base classes that can use jmri, jmrit, and jmrix classes, along with anything else. By having this here, we break the dependency between jmrix and jmrit classes (somebody has to create the general and system-specific tool objects for an application; that dependency is from the apps package)

Although it's not always honored, the tree structure here is important: Packages should not reference across the tree. Code in `jmri.jmrit` is welcome to reference classes in the `jmri` package, but should not reference directly to classes in `jmri.jmrix`. Classes should reference the interfaces in `jmri`, not the specific details of classes in `jmri.managers` and `jmri.implementations`. It can be tempting to violate this rule in the interest of expediency, but in the long run it makes it much harder for JMRI to be maintained and improved by a large group of people. We just can't allow lots of tiny little special cases to make the code impossible to understand. We're developing ArchUnit tests for this which can be run via `./runtest.csh jmri.ArchitectureCheck` as part of developer unit testing (there is also a PowerShell script available, see the developer unit testing page for more information). This will highlight many existing structure violations in addition to new ones because we haven't yet cleaned up some historical issues. There's also `jmri.ArchitectureTest` which is run as part of our CI tests, and catches new violations of a subset of the constraints.

Similarly, we have conventions for where to locate Swing GUI code and persistance (store/load) code that limits how embedded in them main code they become.

### Example: a Turnout

Turnouts involve multiple classes:

- Turnout - the basic interface. This is what you should expect to deal with when writing your layout automation code; its what you get when you make a request from the TurnoutManager, etc.
- AbstractTurnout - provided for convenience when implementing the Turnout interface for specific hardware, this provides the basic implementation.
- LnTurnout - a specific implementation for LocoNet-connected turnouts. There are many other implementations for different layout connections.

## Dynamic (Object) Structure

For many JMRI objects, once they have been created they can be accessed either by type, i.e. "The default configuration manager", or by name, i.e. "The East Yard Entrance turnout". More information on how things (e.g. objects representing items on the layout) are named is available on a separate page.

The "InstanceManager" as a key central point for this navigation.

- It provides access to key objects, particularly the Managers that mediate access to Turnouts, Sensors, etc.
- It automatically handles creation of many parts of JMRI via several mechanisms:
  - InstanceManagerAutoDefault
  - InstanceInitializer
  and, when needed, provides for their post-creation initialization.
- It disposes of suitable objects at the end of their lifespan when the InstanceManager (or a particular collection in it) is cleared.

Extensive use of Factory pattern via objects we call "Manager" objects.

### Example: a Turnout

To get a specific Turnout instance that represents something on the layout, you make a request of a TurnoutManager. This is also an interface, with a similar implementation pattern. In turn, you get that TurnoutManager from the InstanceManager.

The role of the generic Manager<T> class

NamedBean and addressing as part of the Manager's role.

The role of NamedBeanHandle and the NamedBeanHandleManager.