Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Drools BigDecimal accumulator
package uk.co.scattercode.drools.accumulators;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.Serializable;
import java.math.BigDecimal;
import org.drools.runtime.rule.TypedAccumulateFunction;
/**
* This is a 'sum' accumulator for a collection of {@link BigDecimal}.
* Out-of-the-box Drools has sum accumulators which are able to add up
* BigDecimals, but do so by converting them to doubles. So the number you get
* out at the end is not good if your application is doing anything
* financial.
*
* To use this, create a package builder configuration file:
* <pre>
* META-INF/drools.packagebuilder.conf
* </pre>
* Put the following in it:
* <pre>
* drools.accumulate.function.sumbd = uk.co.scattercode.drools.accumulators.BigDecimalAccumulator
* </pre>
* And you can now do things like:
* <pre>
* accumulate(
* CurrencyExposure( currency in ("GBP", "EUR", "NOK"),
* $exp : exposure
* ),
* $sumGbpEurNok : sumbd( $exp )
* )
* </pre>
*
* @author Stephen Masters
*/
public class BigDecimalAccumulator implements TypedAccumulateFunction {
/**
* Session-specific data required by the accumulator is stored in a
* {@link BigDecimalSum} context, which is instantiated by this
* method.
*/
@Override
public Serializable createContext() {
return new BigDecimalSum();
}
/**
* Initializes the accumulator with an empty list of {@link BigDecimal}.
*/
@Override
public void init(Serializable context) throws Exception {
BigDecimalSum accumulator = (BigDecimalSum) context;
accumulator.init();
}
/**
* Adds the value to the accumulator sum.
*/
@Override
public void accumulate(Serializable context, Object value) {
BigDecimalSum accumulator = (BigDecimalSum) context;
accumulator.add((BigDecimal) value);
}
/**
* Subtracts the value from the accumulator sum.
*/
@Override
public void reverse(Serializable context, Object value) throws Exception {
BigDecimalSum accumulator = (BigDecimalSum) context;
accumulator.subtract((BigDecimal) value);
}
/**
* Yes, this accumulator does implement the reverse method..
*/
@Override
public boolean supportsReverse() {
return true;
}
/**
* Returns the current 'sum' held in the accumulator.
*/
@Override
public Object getResult(Serializable context) throws Exception {
BigDecimalSum accumulator = (BigDecimalSum) context;
return accumulator.sum;
}
/**
* Returns the class of the object returned by getResult.
*/
@Override
public Class<BigDecimal> getResultType() {
return BigDecimal.class;
}
/**
* Required to support {@link Externalizable} interface so that data can be
* shared across sessions. However, we don't need to do that, so this method
* is empty.
*/
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
}
/**
* Required to support {@link Externalizable} interface so that data can be
* shared across sessions. However, we don't need to do that, so this method
* is empty.
*/
@Override
public void writeExternal(ObjectOutput out) throws IOException {
}
/**
* Session-specific data required by the accumulator is stored in a
* an instance of this class.
*/
private static class BigDecimalSum implements Serializable {
/** Generated serialVersionUID */
private static final long serialVersionUID = -3852330030144129793L;
BigDecimal sum = BigDecimal.ZERO;
void init() {
this.sum = BigDecimal.ZERO;
}
void add(BigDecimal augend) {
this.sum = sum.add(augend);
}
void subtract(BigDecimal subtrahend) {
this.sum = sum.subtract(subtrahend);
}
}
}
@stephen-masters

This comment has been minimized.

Copy link
Owner Author

@stephen-masters stephen-masters commented Nov 16, 2012

Kinda puzzled that I'm not finding examples of doing this all over the place. It seems like an obvious thing that anybody using Drools for financial rules and calculations would probably need at some point. Maybe there are loads of private repositories out there, each with their own implementations? :)

Anyway, this seems to work reasonably well so far. Thoughts on improvements welcomed as always!

@ge0ffrey

This comment has been minimized.

Copy link

@ge0ffrey ge0ffrey commented Jan 11, 2013

@stephen-masters

This comment has been minimized.

Copy link
Owner Author

@stephen-masters stephen-masters commented Jan 15, 2013

Hi Geoffrey - It looks like you have been pushing to get that fixed for a long time!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment