305 lines
14 KiB
Plaintext
305 lines
14 KiB
Plaintext
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta name="generator" content="HTML Tidy for HTML5 for Apple macOS version 5.8.0">
|
|
<title>JMRI: Introduction to JMRI Library Structure</title>
|
|
<meta name="author" content="Bob Jacobsen">
|
|
<meta name="keywords" content="JMRI technical code"><!--#include virtual="/help/en/parts/Style.shtml" -->
|
|
</head>
|
|
<body>
|
|
<!--#include virtual="/help/en/parts/Header.shtml" -->
|
|
|
|
<div id="mBody">
|
|
<!--#include virtual="Sidebar.shtml" -->
|
|
|
|
<div id="mainContent">
|
|
<h1>JMRI Code: Introduction to JMRI Library Structure</h1>
|
|
|
|
<p>This page is the top-level introduction to how the JMRI software is organized.</p>
|
|
|
|
<h2>Static Structure</h2>
|
|
|
|
<p>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.</p>
|
|
|
|
<p>In addition to the source code, JMRI expects to find directories within the current
|
|
directory:</p>
|
|
|
|
<dl>
|
|
<dt>
|
|
<a href="https://github.com/JMRI/JMRI/tree/master/help">help/</a>
|
|
</dt>
|
|
|
|
<dd>
|
|
The <a href="Help.shtml">in-program help files</a>
|
|
</dd>
|
|
|
|
<dt>
|
|
<a href="https://github.com/JMRI/JMRI/tree/master/jython/">jython/</a>
|
|
</dt>
|
|
|
|
<dd>
|
|
Various <a href="https://www.jmri.org/jython/">sample</a> and <a href=
|
|
"https://www.jmri.org/jython/test/">test</a> scripts.
|
|
</dd>
|
|
|
|
<dt>
|
|
<a href="https://github.com/JMRI/JMRI/tree/master/lib">lib/</a>
|
|
</dt>
|
|
|
|
<dd>Jar files and linkable libraries that JMRI relies on.</dd>
|
|
|
|
<dt>
|
|
<a href="https://github.com/JMRI/JMRI/tree/master/resources">resources/</a>
|
|
</dt>
|
|
|
|
<dd>
|
|
Image and sound resources used by the library, and available for user selection. These
|
|
can be <a href="https://www.jmri.org/resources/">directly browsed</a>.
|
|
</dd>
|
|
|
|
<dt>
|
|
<a href="https://github.com/JMRI/JMRI/tree/master/web">web/</a>
|
|
</dt>
|
|
|
|
<dd>Files for JMRI's built-in web servers</dd>
|
|
|
|
<dt>
|
|
<a href="https://github.com/JMRI/JMRI/tree/master/xml">xml/</a>
|
|
</dt>
|
|
|
|
<dd>
|
|
XML files for decoder and programmer definitions, <a href=
|
|
"../../tools/signaling/AspectSignaling.shtml">signal system definitions</a>, <a href=
|
|
"XmlSchema.shtml">Schema</a> and DTDs used to validate JMRI's <a href=
|
|
"XmlPersistance.shtml">XML persistance</a>, and others.
|
|
</dd>
|
|
</dl>
|
|
<p>plus specific files used by the <a href="Ant.shtml">build process</a>, to <a href=
|
|
"Logging.shtml">control logging</a>, and containing the <a href="https://www.jmri.org/copyright.shtml">JMRI
|
|
license</a>.</p>
|
|
|
|
<h3>Static Package and Class Structure</h3>
|
|
|
|
<p>For interfaces in the <code>jmri</code> package, which might be implemented by lots of
|
|
different layout hardware types,
|
|
<a href="https://www.jmri.org/JavaDoc/doc/jmri/InstanceManager.html">jmri.InstanceManager</a>
|
|
satisfies requests for implemented objects by providing access to a hardware-specific
|
|
<a href="https://www.jmri.org/JavaDoc/doc/jmri/Manager.html">Manager</a>,
|
|
from which you can get the
|
|
hardware-specific items that represent what you want to access on the layout.</p>
|
|
<a href="images/OverallPackageStructure.png"><img src="images/OverallPackageStructure.png"
|
|
alt="package structure"></a>
|
|
<p>Because we have different hardware implementations in subpackages of the
|
|
<code>jmrix</code> package, those are also accessed via the
|
|
<a href="https://www.jmri.org/JavaDoc/doc/jmri/SystemConnectionMemo.html">SystemConnectionMemo</a>
|
|
classes, which provide access to generally-defined objects.</p>
|
|
|
|
<p>Other code should, in general, not reference those specific implementations directly.</p>
|
|
|
|
<p>(The <a href="https://www.jmri.org/help/en/package/">help/en/package</a>
|
|
section of the in-program help files are also organized this way)</p>
|
|
|
|
<a href="images/OverallImplementationStructure.png"><img src=
|
|
"images/OverallImplementationStructure.png" class="floatRight" alt="implementation structure"></a>
|
|
<p>More specifically:</p>
|
|
|
|
<dl>
|
|
<dt>jmri</dt>
|
|
|
|
<dd>Contains interfaces and base class implementations for the common JMRI objects. This is
|
|
the basic interface to the overall JMRI library and its capabilities.<br>
|
|
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.</dd>
|
|
|
|
<dt>jmrit</dt>
|
|
|
|
<dd>
|
|
Contains commonly useful <strong>t</strong>ools and extensions.<br>
|
|
It can depend on <code>jmri.*</code> and externals. It must not depend on
|
|
<code>jmrix.*</code>
|
|
</dd>
|
|
|
|
<dt>jmrix</dt>
|
|
|
|
<dd>Contains code that is specific to a particular e<strong>x</strong>ternal 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).<br>
|
|
jmrix can depend on jmri and externals, but not jmrit.<br>
|
|
Only system-specific code should access within the jmrix subpackages.</dd>
|
|
|
|
<dt>jmris</dt>
|
|
|
|
<dd>contains all the code for the server implementation for the JMRI interfaces.</dd>
|
|
|
|
<dt>managers</dt>
|
|
|
|
<dd>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.</dd>
|
|
|
|
<dt>implementations</dt>
|
|
|
|
<dd>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.</dd>
|
|
|
|
<dt>util</dt>
|
|
|
|
<dd>
|
|
General service classes that are <em>not</em> user level tools. Should not depend on
|
|
jmri.jmrit or jmri.jmrix packages. The jmri.util.swing subpackage provides Swing
|
|
utilities.
|
|
<p>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.</p>
|
|
</dd>
|
|
|
|
<dt>apps</dt>
|
|
|
|
<dd>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)</dd>
|
|
</dl>
|
|
|
|
<a href="images/OverallAppDependencies.png"><img src="images/OverallAppDependencies.png"
|
|
class="floatRight" alt="dependencies"></a>
|
|
|
|
<p>Although it's not always honored, the tree structure here is important: Packages should
|
|
<em>not</em> reference across the tree. Code in <code>jmri.jmrit</code> is welcome to
|
|
reference classes in the <code>jmri</code> package, but should not reference directly to
|
|
classes in <code>jmri.jmrix</code>. Classes should reference the interfaces in
|
|
<code>jmri</code>, not the specific details of classes in <code>jmri.managers</code> and
|
|
<code>jmri.implementations</code>. 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 <a href=
|
|
"https://www.archunit.org">ArchUnit</a> tests for this which can be run via
|
|
<code>./runtest.csh jmri.ArchitectureCheck</code> as part of <a href="JUnit.shtml">developer
|
|
unit testing</a> (there is also a PowerShell script available, see the <a href=
|
|
"JUnit.shtml">developer unit testing</a> 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 <code>jmri.ArchitectureTest</code> which is run as part of
|
|
our <a href="ContinuousIntegration.shtml">CI tests</a>, and catches new violations of a
|
|
subset of the constraints.</p>
|
|
<p>Similarly, we have conventions for where to locate <a href="Swing.shtml">Swing GUI
|
|
code</a> and <a href="XmlPersistance.shtml">persistance (store/load) code</a> that limits how
|
|
embedded in them main code they become.</p>
|
|
|
|
<h4>Example: Implementing a Turnout</h4>
|
|
Turnouts involve multiple classes:
|
|
<ul>
|
|
<li><a href="https://www.jmri.org/JavaDoc/doc/jmri/Turnout.html">Turnout</a>
|
|
- the basic interface. This is what you should expect to deal with when writing
|
|
your layout automation code; it's what you get when you make a request from the
|
|
TurnoutManager, etc.</li>
|
|
|
|
<li><a href="https://www.jmri.org/JavaDoc/doc/jmri/implementation/AbstractTurnout.html">AbstractTurnout</a>
|
|
- provided for convenience when implementing the Turnout interface for
|
|
specific hardware, this provides the basic implementation.</li>
|
|
|
|
<li><a href="https://www.jmri.org/JavaDoc/doc/jmri/jmrix/loconet/LnTurnout.html">LnTurnout</a>
|
|
- a specific implementation for LocoNet-connected turnouts. There are many
|
|
other implementations for different layout connections.</li>
|
|
</ul>
|
|
|
|
<h2>Dynamic (Object) Structure</h2>
|
|
|
|
<p>For many JMRI objects, once they have been created they can be accessed either by type,
|
|
i.e. "The default configuration manager" via the InstanceManager,
|
|
or by name, i.e. "The East Yard Entrance turnout" via a type-specific Manager.
|
|
More information on how things (e.g. objects representing items on the layout) are named
|
|
<a href="Names.shtml">is available on a separate page</a>.</p>
|
|
|
|
<p>The <a href="https://www.jmri.org/JavaDoc/doc/jmri/InstanceManager.html">"InstanceManager"</a>
|
|
is a key central point for this navigation.</p>
|
|
|
|
<ul>
|
|
<li>It provides access to key objects, particularly the Managers that mediate access to
|
|
Turnouts, Sensors, etc.</li>
|
|
|
|
<li>It automatically handles initialization of many parts of JMRI via several mechanisms:
|
|
<ul>
|
|
<li>
|
|
<a href=
|
|
"https://www.jmri.org/JavaDoc/doc/jmri/InstanceManagerAutoDefault.html">InstanceManagerAutoDefault</a>
|
|
</li>
|
|
|
|
<li>
|
|
<a href=
|
|
"https://www.jmri.org/JavaDoc/doc/jmri/InstanceInitializer.html">InstanceInitializer</a>
|
|
</li>
|
|
</ul>
|
|
and, when needed, provides for their <a href=
|
|
"https://www.jmri.org/JavaDoc/doc/jmri/InstanceManagerAutoInitialize.html">post-creation
|
|
initialization</a>.
|
|
</li>
|
|
|
|
<li>It <a href=
|
|
"https://www.jmri.org/JavaDoc/doc/jmri/InstanceManager.html#dispose-jmri.Disposable-">disposes</a>
|
|
of <a href="https://www.jmri.org/JavaDoc/doc/jmri/Disposable.html">suitable objects</a> at the
|
|
end of their lifespan when the InstanceManager (or a particular collection in it) is
|
|
cleared.
|
|
</li>
|
|
</ul>
|
|
|
|
<p>JMRI makes extensive use of the Factory pattern via objects we call "Manager" objects.</p>
|
|
|
|
<h4>Example: Accessing a Turnout</h4>
|
|
|
|
<p>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 got that TurnoutManager from the InstanceManager.</p>
|
|
<div class="wide">
|
|
<pre style="font-family: monospace;">
|
|
TurnoutManager manager = InstanceManager.getDefault(TurnoutManager.class);
|
|
Turnout turnout = manager.getTurnout("IT12");
|
|
</pre>
|
|
</div>
|
|
<p>The generic <a href="https://www.jmri.org/JavaDoc/doc/jmri/Manager.html">Manager<T></a> class provides the basic interface.
|
|
which is then extended for specifics i.e.
|
|
<a href="https://www.jmri.org/JavaDoc/doc/jmri/TurnoutManager.html">TurnoutManager</a>.
|
|
That then has specific implementations.</p>
|
|
|
|
<p>In many cases, there's one underlying implementation for a manager.
|
|
For example, there's one
|
|
<a href="https://www.jmri.org/JavaDoc/doc/jmri/LogixManager.html">LogixManager</a>, one
|
|
<a href="https://www.jmri.org/JavaDoc/doc/jmri/MemoryManager.html">MemoryManager</a>, etc.
|
|
<p>
|
|
In other cases, you might have multiple system-specific managers:
|
|
LnTurnoutManager for a LocoNet connection, NceTurnoutManager for an NCE
|
|
connection, and an InternalTurnoutManager for the internal turnouts.
|
|
These are handled by making them clients to a single
|
|
<a href="https://www.jmri.org/JavaDoc/doc/jmri/ProxyManager.html">ProxyManager</a>,
|
|
subclass i.e.
|
|
<a href="https://www.jmri.org/JavaDoc/doc/jmri/managers/ProxyTurnoutManager.html">ProxyTurnoutManager</a>
|
|
which uses name lookup to work with the individual managers.
|
|
|
|
<h2>Object Referencing</h2>
|
|
|
|
<p>Code can hold a direct java reference to a specific object.
|
|
In some cases, typically GUIs or
|
|
<a href="XmlPersistance.shtml">persistance</a>,
|
|
you'll want to refer to an object by its name. JMRI NamedBean objects
|
|
have both system names that can't change and user names that can.
|
|
For example, the user name "East Yard" for a turnout might refer to
|
|
"LI1" at some point and later refer to "NT12". The
|
|
<a href="https://www.jmri.org/JavaDoc/doc/jmri/NamedBeanHandle.html">NamedBeanHandle</a>
|
|
class takes care of this by remembering
|
|
which name is being used for an object, and keeping track of how
|
|
that name might be moved from one object to another.
|
|
For more information, see the description on the
|
|
<a href="Patterns.shtml">Patterns page</a>.
|
|
|
|
<!--#include virtual="/help/en/parts/Footer.shtml" -->
|
|
</div>
|
|
<!-- closes #mainContent-->
|
|
</div>
|
|
<!-- closes #mBody-->
|
|
<script src="/js/help.js"></script>
|
|
</body>
|
|
</html>
|