cox.jmatt.java.MathToolsapplication is a Java utility designed to assist in the development, formatting, and presentation of math questions
for printed tests. It consists of ten packages: the core tools, seven packages of classes designed to support, demonstrate, and utilize them, and three specific
implementations of the
MathXMLclass exists to help generate MathML Presentation markup.
svg.*classes provide a way to generate simple SVG markup.
* For some Java installations scripting or XML processing might require an external JAR.
These are the core tools; the classes that do the work of presenting, manipulating, and generating test content.
parseMathML(), which can make MathML-sense of most raw math content.
.test.* package provides a container for things that might appear on a math test. Specifically, questions, answers, and additional text or
toXML(). Only classes implementing this interface (
MTFI) can be added to a MTest.
java.sql.ResultSets queried from databases and capture groups from regular expressions.
These are utility classes. They provide support services for the core tools or for applications using them.
mathLog()is the logging method,
mathPrintln()is a non-logging print method, and
processMathObject()is a generic two-way communication method.
MathPrinterimplementation with a place to display output and level filtering for log messages. It also has a button to clear the 'screen' and a pre-defined extension method.
BasicMathPrinterimplements the MathPrinter interface but it also has methods for generating instances of MathTools classes.
GraphHandler. Implements XML handler interfaces and directs SAX and XSLT reports to CapCom logging. Can also be used as a handler to check (parse) an XML document.
javax.xml.transformcapability this class will require them externally. If not, it will not function, however the other tools will not be affected.)
MathFileIOcan also create and return a
javax.sql.DataSourceobject. The class itself revolves around generating
MathEngine.parseRPN(). It is a quick and easy calculator, embeddable as-is for any application requiring such a thing.
demo package contains classes designed to demonstrate the capabilities of the other MathTools classes. Every method of every class is not shown,
but enough is presented to give a good idea of what's in the class and how it works. The demos are organized by class, and most are
The star of the package is
ScriptPanel and it is explained in more detail than the rest.
BasicMathPrinterand the actual demonstration Panels. It initially shows a
QuickRPNCalculator. The 'View' menu allows selection of a specific demo and the Forward and Back buttons, [|>>] and [<<|], allow the demos to be viewed sequentially.
ScriptPanel. In fact, every demo class with 'Pizza' in its name uses
PizzaPanel. It consists of a TextArea with user-editable parameters, each of which can be interpreted as boolean, long, int, double, or String. Each demo also has a selector for the specific method to test along with a [Go!] button to trigger the demo. Each selection specifies the parameter number and type required for the demonstration, and the Javadoc for each Panel explains the demos in more detail.
ScriptPanelbut was factored out and added as an independent class. In use,it presents a GUI front-end for constructing an URLClassLoader. URLs can be 'picked' from a
FileDialogor a list of them can be loaded.
ScriptPanel provides a complete, if minimal, scripting environment. It uses the
javax.script package. The GUI itself consists of four Panels
plus a Forward and Back button to switch between them. The individual panels, and their functions, are:
ScriptEnginelookup method, clipboard usage, optional return Object processing, and the [Clear] buttons for the Script and Pizza areas. Since user implementations of
ScriptPanelmight not be constructed around a
Frame, the clear buttons are placed away from accidental clicks, and they are LOCKED.
The MathDBC & SQL demo runs SQL commands against any JDBC-compliant database. It can be used to build a database or manipulate an existing one, with
SQL! SQL commands can be entered manually or loaded from a file. If the last command executed generates a
ResultSet it can be formatted: there is
a field for entering a row template. This plus the
ResultSet are sent to
MathTestFormatter and the result printed and optionally sent
to the clipboard.
The MTFormatter demo provides access to the
MathTestFormatter apart from the scripting environment. A template can be entered manually or
loaded from a file. Template data can be loaded from a properties file, loaded from a properties panel, or both. Or a regular expression can be entered, applied
to data from the RegEx data panel and its capture groups row-formatted.
The GPGenerator demo utility uses the SVG classes to generate graph paper. It has built-in generators for square-grid, polar, log and semilog, and a specialized chart usable for tracking blood pressure or blood sugar. There is also a generator for ledger-style sheets: multiple columns of differing widths and optional column headers. The class itself pre-defines a plethora of different pens (CSS styles) for rendering lines and text, and the generators themselves offer many configuration options. (The SVG output is sent to the clipboard where it can be pasted into a document and transcoded into a print- or graphic format.)
The graphing base package consists of interfaces and concrete classes required for graphing implementations. They are:
render()method is responsible for rendering both itself and all the Renderables it contains. It is THE graph-generator; once the GraphPaper is rendered MathTools is done with the graph.
Renderablerepresents an axis drawn on a graph. In most cases it will be the X-axis or Y-axis but this is NOT mandatory! Broadly, an
Axisrepresents an entity against which graphs are drawn, measured, or compared.
GraphEngineclass to create the other graph-generating elements.
The helper classes in the base package are:
Renderableinterface. In fact it defines all methods except
render(), handles parameter-setting with some intelligence, handles the
setType()method, and even provides an empty
testCondition()method (that always returns false!).
org.xml.sax.DefaultHandlersubclass consumes the XML generated by the
graphing.xml.*implementation and turns it into a
GraphPaperinstance, ready to render. (The method to do this is in
markup.* package provides the basic tools needed to build a fully scriptable CSS-styled XML markup language. It consists of two base classes,
with one of them abstract, and two implementation classes. Two of these are designed around tag construction and manipulation and the others are for building
CSS rules or 'style=' attributes.
Tagand provides a concrete tool for building any XML tag. It is similar to
MathXML.wrapTag()but more powerful and featureful. Enough so to be used in its own right to generate any XML markup. This might not be the optimal way to do that, but it is possible! One of these instances is exposed to scripts as the 'SimpleTag' tool.
StyleInfoand un-protects some of its methods. As a rule subclasses should extend
StyleInfoas this class is designed more for end-use.
SimpleTagImplhas methods to generate instances of this class.
markup.* subpackage implements the machinery to generate SVG markup. It consists of tag classes which correspond exactly with SVG tags,
and pen classes which are used for the CSS styling germane to SVG. The
MathDrawSVG class rounds out the package: it provides methods to
generate instances of the others along with methods to set their default values.
Tag classes based on
DrawableContainerTag are tags capable of containing other SVG tags: <g>, <symbol> and <svg> to name three.
The 'drawable' means they also have methods to create, intialize and add other (drawing) tags directly, without requiring separate instantiation. This
makes quick work of adding lots of drawing primitives (lines, circles, paths, etc.) without a lot of work.
This package also serves as an example of how the
markup.* classes can be extended into a markup language implementation.
This package makes (X)HTML document generation scriptable just like the SVG package does for graphics. The
BaseHTag is the superclass of all
the tag classes in this package. It is a
Tag sublcass so HTML-document scripting works much as does SVG.
Not all scripting engines expose static methods to their scripts. All MathTools core classes have some static methods, and some classes have ALL static methods.
SCROBs exist to alleviate this situation. A SCROB, or scriptable object is a class whose instance methods exactly duplicate and reflect to the
same static method in the class SCROBbed. All-static MathTools classes do have ONE instance method:
getSCROB(). If a script can't find a static
getSCROB() on that tool and use the SCROB in its place. SCROB Documentation: SCROBs don't have documentation. They duplicate
static classes that DO.
Classes with fewer static methods have instance methods that 'shadow' them.
The MathTools logging and communication structure includes two components:
CapCom and the
MathPrinter interface. The MathTools classes
report error and program flow information to CapCom. CapCom then relays this to the Global Printer, if one is set. Any class can be the Global Printer, as long
as it implements the
MathPrinter interface. The metaphor used is that the Global Printer has some method to display such logging information. Its
processMathObject() method exists for subclass extension: none of the MathTools classes use it. It accepts an Object as a parameter and returns
an Object; past that MathTools does not specify any aspect of it.
MathConsole class exists to provide access to MathTools logging and communication. Though primarily meant for scripts, any class can make use
of it. It and
CapCom provide two logging methods for each level: Debug, Info and Error. One method accepts a String message and the other takes
a String and a Throwable. Scripts needing to print a Debug-level message and Exception call
Console.debug('Message', Exception) and Java applications
using MathTools would call
For non-logging messages MathPrinter defines
mathPrintln() which accepts a String. CapCom and MathConsole both define
along with a plain
println() method that aliases to it. MathPrinter is bi-directional via the
processMathObject() method, which scripts
can use to interact with user-defined MathPrinters.
CapCom makes provision for setting and retrieval of the Global Pizza. This is simply a
java.util.Properties object. The
application sets it before executing a script or using MathTools and it can be retrieved at need later. MathConsole provides read-only access to the Global
ScriptPanel sets it from the Script Pizza Panel before a script is executed.
The Shelf is the metaphor used for a
java.util.Hashtable<String, Object>. Scripts or applications can store arbitrary things there.
MathConsole allows scripts to store and retrieve things; applictions use
Graphing is an essential part of mathematics and no math package would be complete without at least a nod toward it. The graphing.* package is MathTools' nod. Since MathTools is primarily geared toward text output, its graphing package is designed with that in mind. It is meant to generate text capable of being consumed by some external application which will generate the actual graph.
The metaphor used here is of a student or teacher looking at (or creating) a problem that starts 'Graph the following...' with a blank sheet of graph paper and
a pen. MathTools provides the graph paper (
graphing.* package) and the pen (a script or application). It is up to the specific implementation to
provide the actual machinery to change this math-problem-oriented data into a consumable format to generate the graph itself.
MathTools provides three implementations of the graphing package. The first,
cox.jmatt.java.MathTools.java.graphing.xml is the XML implementation.
The XML implementation is geared toward demonstrating how an implementation should behave and usable for persistent storage. It takes a script- or
application-generated graph and turns it into simple XML markup that can be parsed and manipulated (DOM) or transformed (XSLT).
cox.jmatt.java.MathTools.graphing.Graph implementation is built around the wonderful open-source Graph
program. It can generate a basic .grf file which Graph can then load, edit, and convert to an image format.
The final implementation is the
graphing.noop classes. These provide concrete classes implementing all
Renderable interfaces but they
do nothing! The no-op implementation is provided for extension by other implementations that don't need all the stuff the core interfaces mandate. (This
is mostly because
GraphHandler doesn't like
GraphEngines that return null!)
Since the original posting of this page many things have changed. Foremost among them: MathTools now has a dedicated scripting tutorial!! Grab it from the download area and go to town with it. I'll leave the original stuff here, just because, but until whenever...
MathTools was designed for scripting. The tools themselves, even the all-static ones, have zero-argument constructors along with plenty of ways to generate
more of themselves. All exposed tools also have SCROBs or shadow methods to ensure all methods are scriptable. Any scripting language can be used. All
that is required is a
javax.script.*-compliant API and a JAR file containing it.
ScriptPanel was designed to allow maximum flexibility and ease-of-use, right 'out of the JAR.' Everything required to get a script up and running can be configured from the Script Config panel. An URLClassLoader can be used to locate resources, both for MathTools and for any scripts. After the script ends, whatever Object it returns is displayed as a String and, if not-null, is copied to the clipboard. Thus, the MathTools JAR provides a complete scripting environment, capable of use with maximum flexibility and without the necessity of building a separate application just to access it.
The best source of MathTools documentation is its
javadoc. Every class and public method is documented and described there. Arguments, return
values, possible errors, and even program flow is detailed. This document serves as a 'quick-start' guide and tutorial. Several sample scripts are included
inside the MathTools JAR in the docs/SampleScripts folder. (This document is also there!)
While the MathTools are exposed to scripts, NOTHING says scripts must use them! One of ScriptPanel's greatest advantages is that it provides a place to experiment with a scripting language before even thinking about using MathTools! Albeit bare-bones and minimal, ScriptPanel offers a no-frills quick and easy place to actually learn a scripting language.
other things as well.
GraphEngineFactory both have the capacity to use it.
To change the scripting language simply put the JAR somewhere close to the MathTools JAR and put its URL into the URLLoaderPanel. Then enable the classloader
and the scripting language will be available. This does require a
javax.script.*-compliant package but those are many and more. The classloader
set becomes CapCom's MathClassLoader, so custom XML parsers (SAX and DOM), XSLT transformers, and other
graphing.* implementations can also be
For operating systems that recognize executable JAR files, double-click the MathTools JAR file. The demo should fire up after a moment to initialize. If the
operating system doesn't recognize executable JARs, open a command line, navigate to where the JAR file is and type the command:
java -jar MathTools_J6.jar
Once MathTools executes you will see the following:
From here all of the demos are available. The back and forward buttons ('[<|]' and '[|>]') can flip through the panels sequentially or a specific demo can be selected from the View menu. Select (or flip through to) the ScriptPanel demo.
Note that the Script demo also has forward and back buttons. Its individual panels are the Script Source panel (initially visible), the Script Pizza panel, the Script Config panel, and the URLLoader panel.
To expose String properties to the script, select the Script Pizza panel. Enter any properties you want the script to know. They must be of the form:
PropertyName = Property value as a String
If the properties are to be available to multiple scripts, or multiple executions of the same script, consider saving them to a text file. This can then be loaded using the [Load] button.
The [Send to Global Pizza] button forces the properties to be parsed and set as the Global Pizza.
ScriptPanel does this automatically, so that
is not needed now. The button is there for applications that don't call ScriptPanel's
Once the properties are set, select other options on the Script Configuration panel. The pre-configured options are at reasonable defaults for most scripting
applications. The only thing that might need changing is the scripting language. ScriptPanel can instantiate an engine by name, by extension, or by its
The 'processMathObject(result)' checkbox is present for user-defined
MathPrinters used with ScriptPanel. If checked, ScriptPanel calls
CapCom.processMathObject() on the Object returned by the script's execution.
BasicMathPrinter simply returns the object so checking
this box has no result at all. Finally, if for some reason you do not want the return Object's
toString() copied to the clipboard, uncheck
that option here.
Once the URLs are entered, click the [Check URLs] button. This checks the URLs. If all goes well an Info-level message appears reporting the number of URLs parsed. If this is less than the number entered, enable Error-level logging and click the button again. Any malformed URLs are reported at this level.
The [Set MTCL] button parses the URLs entered, builds an URLClassLoader around them and sets it as
CapCom's MathClassLoader. Again, this button
is there for custom classes using MathTools; ScriptPanel does this automatically. In fact, ScriptPanel sets the MathClassLoader regardless of whether or not
it itself is using it.
IF your scripting language is different, make sure the URLLoader knows where it is and enable the 'Enable URLClassLoader' box on the Script Config panel.
The easiest way to do this is to fire up your favorite text editor, enter and edit the script there, and load it into the script panel. Once it's there, click the [Run Script] button. If it doesn't work enable the Debug level and Stack Trace and try again. Work out the bugs (in the text editor, then re-load) and presto!
Don't be afraid to experiment! Fire up your web browser (Firefox, ideally!), load the javadoc and play with the tools. Then, once you're comfortable with the overall application you can start scripting in earnest. Good luck!
The MathTools JAR also has a few sample scripts. They are in the docs/SampleScripts folder along with a copy of this web page. As a matter of interest, the version.txt file contains some version information. Specifically, the project name, the 'Stable Release' version number and the 'Build Code' number. These are displayed when MathTools is run from the JAR and the BasicMathPrinter's [Go!] button is clicked. Other than these, the rest of the content is MathTools!
Not a difficult process at all! Even simpler with the proper tools. I use jEdit to create/edit my program and script files. It's open-source, easy to use, written in Java, and does NOT impose a lot of 'overhead' common with other editors and IDEs. For managing the build process I use Ant from the Apache Software Foundation. The MathTools Ant script is build.xml located in the src directory of the download.
The steps for building MathTools are:
MathToolshas NO external dependencies whatsoever. All of its source code is contained within Java itself. Most
importstatements start out java.something and the ones that don't are still included within Java! (Example: org.sax.stuff.) The only non-java dependencies are within the MathTools classes themselves, so no exotic includes are required.
Using Ant simplifies the process. If you don't have it but want to use it, download it and follow the installation instructions. After completing step #2 above you should have a folder in your (otherwise empty) project directory called src. Copy build.xml into the project directory itself. For the rest of the steps this will be the 'Project Directory' or 'Project Root Directory.'
Open a command prompt (Windows users) or equivalent (others) and navigate to the project root directory. Enter the command ant prepare and Ant will create the directory structure required for building and deployment. THIS IS IMPORTANT!! The MathTools build script expects a certain directory structure and this task creates it! Executing 'prepare' multiple times will NOT hurt anything, so don't worry if it happens.
Once the proper structure is in place, the two commands you'll use most often are ant compile and ant run. The former compiles any files that have changed and reports any errors it finds. The latter compiles and then executes the result. If there are no errors, MTDemo should pop open after a few seconds.
The command ant help displays a brief description of the defined tasks and what they do. The ant clean task erases ALL compiled classes and other residue from the build directory. If Ant gets confused over missing or changed items that SHOULD be found, run clean and re-compile. The ant javadoc task generates the MathTools javadoc; the folder appears in the project directory. Similarly, ant makejar creates the MathTools JAR file, again in the project root directory. The ant fulljar task does the same thing but includes the javadoc inside the MathTools JAR. The showpaths task displays all the relevant paths Ant uses in compiling MathTools.
This is where customization can begin! Part of the 'prepare' task is creating the include directory. This directory is for anything that should be included in the JAR file itself. Any classes or other resources that should be distributed within the JAR should be placed here. (Like the sample scripts and this document are!) This directory is also a part of the CLASSPATH used for compiling, so any JARs placed here will be used. To use a JAR during the compilation process without having it appear in the MathTools JAR, place it in the lib folder. Anything here is a part of the CLASSPATH when ant compiles and runs, but is NOT copied when making a JAR.
Speaking of JARs, the MathTools JAR must have a manifest. prepare 'touches' the file manifest.txt (yes, dot-TXT. Easier to edit that way and it still works!) but doesn't put anything there. To execute MathTools from its JAR, put this as the first line in the manifest file: Main-Class: cox.jmatt.java.MathTools.demo.MTDemo. (If you are customizing something, this may be different, but if that's the case you probably don't need to be reading this!)
The final task is an exercise in convenience (or pure laziness!). To compile the classes, turn them into a JAR, generate the javadoc, and copy the entire thing to a specific place: ant deploy. This task is useful but requires editing the build script. If this is desirable:
Since we are discussiong customization, DO NOT be afraid to experiment with the Ant script! The original version, from which this one descended, was written to be a very broad 'standard' build script. For those reading between the lines, YES! Ant frustrated me greatly when I first began using it! It still does on occasion, but it mostly does what I want it to do now. So if you can benefit from my mistakes, PLEASE DO SO!
(For those of you reading this who have progressed far past this point, please show patience! When I first began programming Java, the words '... To build this from source...' frightened me into clicking the 'back' button immediately! Then, after I tried it a few times, I still ended up 'clicking the back button' by deleting the source code and just downloading the binaries. The reason: most of the writers of those instructions assumed that all who read them would be of a similar - and very high - level of expertise. I make no such assumption! And to those readers who may yet be afraid of 'compiling from source,' please do not hesitate to try it on MathTools!)