package com.googlecode.objectify.impl.translate.opt;
import com.googlecode.objectify.impl.Path;
import com.googlecode.objectify.impl.translate.CreateContext;
import com.googlecode.objectify.impl.translate.LoadContext;
import com.googlecode.objectify.impl.translate.SaveContext;
import com.googlecode.objectify.impl.translate.SkipException;
import com.googlecode.objectify.impl.translate.TypeKey;
import com.googlecode.objectify.impl.translate.ValueTranslator;
import com.googlecode.objectify.impl.translate.ValueTranslatorFactory;
import java.math.BigDecimal;
/**
* <p>This a simple strategy for storing BigDecimal in the datastore. BigDecimalLongConverter multiplies
* by a fixed factor and stores the result as a Long. This is appropriate for monetary and other (relatively)
* small values with fixed decimal precision.</p>
*
* <p>This is one possible strategy and not appropriate for all uses of BigDecimal - especially very large
* values which cannot fit in a Long. For this reason, the converter is not installed by default. You can
* Install this converter at the same time you perform registration:</p>
*
* <pre>ObjectifyService.factory().getTranslators().add(new BigDecimalLongTranslatorFactory());</pre>
*
* <p>The default factor of 1,000 is good for currency, which usually has 0-3 digits of precision past
* the decimal point. But you can pick any other factor appropriate to your application.</p>
*
* <p>All custom translators must be registered *before* entity classes are registered.</p>
*
* @author Jeff Schnitzer <jeff@infohazard.org>
*/
public class BigDecimalLongTranslatorFactory extends ValueTranslatorFactory<BigDecimal, Long>
{
/** Default factor is 1000, which gives you three digits of precision past the decimal point */
public static final long DEFAULT_FACTOR = 1000;
/** */
private BigDecimal factor;
/**
* Construct this converter with the default factor (1000), which can store three points of
* precision past the decimal point.
*/
public BigDecimalLongTranslatorFactory()
{
this(DEFAULT_FACTOR);
}
/**
* Construct this with an arbitrary factor. Powers of ten are highly recommended if you want to
* be able to interpret the numbers in the datastore viewer.
*
* @param factor number multiplied by before storage and divided by on retrieval.
*/
public BigDecimalLongTranslatorFactory(long factor) {
super(BigDecimal.class);
this.factor = new BigDecimal(factor);
}
@Override
protected ValueTranslator<BigDecimal, Long> createValueTranslator(TypeKey<BigDecimal> tk, CreateContext ctx, Path path) {
return new ValueTranslator<BigDecimal, Long>(Long.class) {
@Override
protected BigDecimal loadValue(Long value, LoadContext ctx, Path path) throws SkipException {
return new BigDecimal(value).divide(factor);
}
@Override
protected Long saveValue(BigDecimal value, boolean index, SaveContext ctx, Path path) throws SkipException {
return value.multiply(factor).longValueExact();
}
};
}
}