Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
Copyright (C) 2013-2014 Sappenin Inc. (developers@sappenin.com) Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
 
 package com.sappenin.objectify.translate;
 
 import  com.google.appengine.api.datastore.EmbeddedEntity;
 

This a more advanced strategy for storing java.math.BigDecimal in the datastore than the standard Objectify translators. This implementation encodes the java.math.BigDecimal value and stores the result as a String. This is appropriate for monetary and other values of ~475 digits (the end encoded value length is number dependent). This strategy offers the following advantages over encoding a java.math.BigDecimal as a Long:

  • Offers support for arbitrary precision numbers
  • Supports very large numbers (~475 digits long)
  • Encodes numbers in lexigraphical order, which allows for native sorting in Datastore queries.

For more details, read this blog entry: "http://softwareblog.sappenin.com/2014/05/best-practices-for-storing-bigdecimal.html"

This translator is not installed by default, but can be installed as follows:

 ObjectifyService.factory().getTranslators().add(new BigDecimalStringTranslatorFactory());
 

Author(s):
David Fuelling
 
 public class BigDecimalEmbeddedEntityTranslatorFactory implements TranslatorFactory<BigDecimal, EmbeddedEntity>
 {
 
 	public Translator<BigDecimal, EmbeddedEntity> create(TypeKey<BigDecimaltkCreateContext ctxPath path)
 	{
 
 		if (java.math.BigDecimal.class.isAssignableFrom(GenericTypeReflector.erase(tk.getType())))
 		{
 			return new BigDecimalTranslator(tkctxpath);
 		}
 		else
 		{
 			return null;
 		}
 	}

Translator which knows what to do with a java.math.BigDecimal.

This class utilizes an optional com.sappenin.objectify.annotation.BigDecimal annotation which allows for fine-grained control over the field names used to store the java.math.BigDecimal information, as well as indexing of each sub-field. See the Javadoc of that annotation for more details.

Author(s):
David Fuelling
 
 	static class BigDecimalTranslator extends NullSafeTranslator<BigDecimal, EmbeddedEntity>
 	{
 
 		private boolean storeDisplayableAmount;
 
 		private boolean indexDisplayableAmount;
 
 		private boolean indexAmount;
 
 		private String encodedAmountFieldName = "encodedAmount";
 
 		private String displayableAmountFieldName = "displayableAmount";

Required Args Constructor.

Parameters:
tk
ctx
path
 
		public BigDecimalTranslator(TypeKey<BigDecimaltkfinal CreateContext ctxfinal Path path)
		{
			// Look for an @BigDecimal Annotation, if present.
			com.sappenin.objectify.annotation.BigDecimal bigDecimalAnnotation = TypeUtils
			Type componentType = GenericUtils.getMapValueType(tk.getType());
			 = ctx.getFactory().getTranslators().get(new TypeKey<>(componentTypetk), ctxpath);
			if (bigDecimalAnnotation != null)
			{
				 = bigDecimalAnnotation.indexEncodedAmount();
			}
		}
		protected BigDecimal loadSafe(EmbeddedEntity nodeLoadContext ctxPath paththrows SkipException
		{
			BigDecimal returnable = null;
			// Get the amount as a java.math.BigDecimal
			if (node.hasProperty())
			{
				Object encodedAmountFieldValue = node.getProperty();
				// Object amountValue = amountNode.getPropertyValue();
				if ((encodedAmountFieldValue != null) && (encodedAmountFieldValue.toString().length() > 0))
				{
					// //////////
					// Get the CurrencyUnit, defaulting to USD
					// //////////
					BigDecimal bdValue = null;
					try
					{
						bdValue = BigDecimalCodec.decodeAsBigDecimal(encodedAmountFieldValue.toString());
					}
					catch (Exception e)
					{
						..print("Unable to Decode java.math.BigDecimal from encoded string \""
encodedAmountFieldValue + "\"");
					}
					returnable = bdValue;
				}
			}
			return returnable;
		}
		protected EmbeddedEntity saveSafe(BigDecimal pojoboolean indexSaveContext ctxPath path)
		{
			if (pojo == null)
			{
				throw new SkipException();
			}
			else
			{
				EmbeddedEntity emb = new EmbeddedEntity();
				// /////////////////////////
				// Handle the EncodedAmount
				// /////////////////////////
				// Path encodedAmountPath = path.extend(encodedAmountFieldName);
				// Encode the Amount value as a String
				{
					String encodedAmountValue = BigDecimalCodec.encode(pojo);
					Path propPath = path.extend();
					Object value = .save(encodedAmountValuectxpropPath);
					DatastoreUtils.setContainerProperty(embvaluectx,
							propPath);
				}
				// /////////////////////////
				// Handle the DisplayableAmount
				// /////////////////////////
				// DisplayableAmountPath (This is never loaded)
				{
					String displayableValue = pojo.toString();
					Object value = .save(displayableValuectxpropPath);
					DatastoreUtils
									propPath);
				}
				return emb;
			}
		}
	}
New to GrepCode? Check out our FAQ X