AFC - Abacus Formula Compiler for Java


This is the tutorial for the Abacus Formula Compiler (AFC). It is organized as a collection of examples and reference topics, which are best read in the order presented here. You might also want to have a look at the Function Reference and the API Reference.


The Reason
To demonstrate why AFC was built, I introduce a simple example: an order entry application where the line item rebate is made customizable. The shortcomings of this solution are overcome in the topic below, which introduces AFC.
The Basics
Line item pricing revisited: a simple case study that introduces the main concepts of AFC.
Numeric Type
AFC normally does all numeric calculations using the double type. This is often not acceptable for financial applications. This topic shows how to make an engine use one of the precise types BigDecimal and scaled long for all numeric computations.
Computation Mode
Different spreadsheet applications calculate some expressions slightly differently. The computation mode tells AFC which particular spreadsheet application to emulate.
Type Conversions
Your input and output interfaces should ideally not be tailored to AFC. AFC therefore can convert a variety of numeric input and output data types from/to its internal numeric type.
Locale and Time Zone
There are a few spreadsheet functions that need to take a user’s locale and time zone into account. While the default is to use the current settings, server-side applications might want to override them.
Dates, Times, Durations and Time Zones
The proper handling of time zones can be more complex than just setting the user’s time zone correctly.
Caching Of Values and Reusing Computations
Many computations can be sped up by turning on internal caching of cell values. And some functions (NOW and MATCH, for example), or repeating sections, always use internal caches. Caches, however, introduce state. You need to reset this state when reusing computations on modified inputs.
Exceptions Thrown By Computations
Computations that result in #VALUE!, #DIV/0! or some such in Excel throw exceptions in AFC.

Repeating Sections

Define repeating sections which are like ranges in Excel, but their width or height may vary with each use of the computation.

Variable-length Data Series
Sometimes you need to pass a data series of variable length to a computation. For example, the dates and totals of all orders in the last 3 months. This is what AFC’s repeating sections are for.
Variable Number of Computations
To go one step further, sometimes you need AFC to compute distinct output values for each of the elements of a variable-length data series. For example, the bonus amount for each employee, given the total bonus for the company. Doing the loop over the series yourself can be severely limiting the range of computations your users can formulate because they cannot aggregate over the whole series. AFC therefore supports per-element outputs in repeating sections.

Binding in Detail

Advanced use cases concerning the binding of the input and output cells of a spreadsheet to the methods of your Java interfaces or classes.

Binding Cells
How to explicitly bind specific input and output cells of a spreadsheet to methods of plain Java interfaces or classes.
Binding To Parametrized Methods
If you have a generic system where the set of possible input and/or output values cannot be determined at compile-time, you have to resort to some sort of binding to parametrized methods.
Binding To Multiple Interfaces
AFC only allows you to set a single interface to provide inputs to or obtain outputs from a computation. How can you work around this?
Binding To Multiple Instances
What if you need to provide multiple separate instances of source interfaces as input providers, or need AFC to implement multiple separate instances of output interfaces?


Decompiling An Engine
If you want to know what kind of code AFC generates, looking at the resulting JVM byte code is not everyone’s thing. To simplify this, you can ask AFC to decompile the generated byte code to Java source code (this feature uses the JODE library).
Logging intermediate values
If you want to know how the result is computed (e.g. for debugging purposes), you can use logging to watch intermediate values in a computation.
Using AFC Without A Spreadsheet File
Some applications may wish to use AFC to compile computation engines, but want users to be able to specify simple computations without having to setup a spreadsheet file. These can use a builder to dynamically construct a spreadsheet model as input to AFC.
Generating An Initial Spreadsheet File
Allows you to generate initial spreadsheet files that, for instance, already define cells for the most typically used inputs and outputs. Or, when you are using AFC without a spreadsheet file, you can let users switch to using one transparently by generating a file for their existing formula definition.
Using A Custom ClassLoader
Some companies use a custom ClassLoader to, for example, speed up class loading. If you don’t replace Java’s default class loader (ClassLoader.getSystemClassLoader()), you may have to make sure that the engines generated by AFC use your custom implementation.
Compiler Errors
See what happens when something goes wrong, and find hints on what to do.

Note On The Sample Code

To ensure its correctness, all the sample code in this tutorial has been cited from automated tests that are run with every release build (unless stated otherwise). The tests and data can be found in in the source distribution of AFC in

  • components/system/src/test/java
  • components/system/src/test/data