org.springframework.data.simpledb.attributeutil.AmazonSimpleDBUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of spring-data-simpledb Show documentation
Show all versions of spring-data-simpledb Show documentation
Provides a POJO centric model as per Spring Data interfaces to interact with Amazon SimpleDB, a non-relational datastore
package org.springframework.data.simpledb.attributeutil;
/**
* *****************************************************************************
* Copyright 2007 Amazon Technologies, Inc. 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://aws.amazon.com/apache2.0 This file 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.
* ***************************************************************************** __ _ _ ___ ( )( \/\/ )/ __) /__\ \ / \__ \ (_)(_) \/\/ (___/
*
* Amazon Simple DB Java Library API Version: 2007-11-07 Generated: Fri Jan 18 01:13:17 PST 2008
*
*/
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import org.apache.commons.codec.binary.Base64;
import org.springframework.data.mapping.model.MappingException;
/**
* Provides collection of static functions for conversion of various values into strings that may be compared
* lexicographically.
*
*/
public final class AmazonSimpleDBUtil {
private static final String UTC_TZ_ID = "UTC";
/**
* static value hardcoding date format used for conversation of Date into String
*/
private static String dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
private static final int LONG_DIGITS = 20;
private static final BigDecimal OFFSET_VALUE = new BigDecimal(Long.MIN_VALUE).negate();
private static final String UTF8_ENCODING = "UTF-8";
private static final int BASE = 10;
private static final int ENCODE_DATE_COLONS_INDEX = 2;
private static final int DECODE_DATE_COLONS_INDEX = 3;
private AmazonSimpleDBUtil() {
/* utility class */
}
/**
* Unsed to encode an Integer {@link Number}.
*/
public static String encodeAsIntegerNumber(Object ob) {
BigDecimal integerBigDecimal = AmazonSimpleDBUtil.tryToStoreAsIntegerBigDecimal(ob);
if(integerBigDecimal != null) {
return AmazonSimpleDBUtil.encodeRealNumberRange(integerBigDecimal, AmazonSimpleDBUtil.LONG_DIGITS,
OFFSET_VALUE);
}
return null;
}
public static BigDecimal decodeIntegerNumber(String value) {
return AmazonSimpleDBUtil.decodeRealNumberRange(value, OFFSET_VALUE);
}
/**
* Unsed to encode a Not Integer {@link Number}.
*/
public static String encodeAsRealNumber(Object ob) {
if(AmazonSimpleDBUtil.isNaN(ob) || AmazonSimpleDBUtil.isInfinite(ob)) {
throw new MappingException("Could not serialize NaN or Infinity values");
}
BigDecimal realBigDecimal = AmazonSimpleDBUtil.tryToStoreAsRealBigDecimal(ob);
if(realBigDecimal != null) {
return AmazonSimpleDBUtil.encodeRealNumberRange(realBigDecimal, AmazonSimpleDBUtil.LONG_DIGITS,
AmazonSimpleDBUtil.LONG_DIGITS, OFFSET_VALUE);
}
return null;
}
public static BigDecimal decodeRealNumber(String value) {
if(value.matches(".*Infinity|NaN")) {
throw new MappingException("Could not serialize NaN or Infinity values");
}
return AmazonSimpleDBUtil.decodeRealNumberRange(value, AmazonSimpleDBUtil.LONG_DIGITS, OFFSET_VALUE);
}
public static String encodeRealNumberRange(BigDecimal number, int maxNumDigits, BigDecimal offsetValue) {
final BigDecimal offsetNumber = number.add(offsetValue);
final String longString = offsetNumber.toString();
final int numZeroes = maxNumDigits - longString.length();
final int paddedSize = numZeroes + longString.length();
final StringBuilder strBuffer = new StringBuilder(paddedSize);
for(int i = 0; i < numZeroes; i++) {
strBuffer.insert(i, '0');
}
strBuffer.append(longString);
return strBuffer.toString();
}
public static String encodeRealNumberRange(BigDecimal number, int maxDigitsLeft, int maxDigitsRight,
BigDecimal offsetValue) {
BigDecimal shiftMultiplier = new BigDecimal(Math.pow(BASE, maxDigitsRight));
BigDecimal shiftedNumber = number.multiply(shiftMultiplier);
shiftedNumber = shiftedNumber.setScale(0, BigDecimal.ROUND_HALF_UP);
final BigDecimal shiftedOffset = offsetValue.multiply(shiftMultiplier);
final BigDecimal offsetNumber = shiftedNumber.add(shiftedOffset);
String longString = offsetNumber.toString();
final int numBeforeDecimal = longString.length();
final int numZeroes = maxDigitsLeft + maxDigitsRight - numBeforeDecimal;
final int paddedSize = numZeroes + longString.length();
final StringBuilder strBuffer = new StringBuilder(paddedSize);
for(int i = 0; i < numZeroes; i++) {
strBuffer.insert(i, '0');
}
strBuffer.append(longString);
return strBuffer.toString();
}
public static BigDecimal decodeRealNumberRange(String value, BigDecimal offsetValue) {
BigDecimal offsetNumber = new BigDecimal(value);
return (offsetNumber.subtract(offsetValue));
}
public static BigDecimal decodeRealNumberRange(String value, int maxDigitsRight, BigDecimal offsetValue) {
BigDecimal offsetNumber = new BigDecimal(value);
BigDecimal shiftMultiplier = new BigDecimal(Math.pow(BASE, maxDigitsRight));
BigDecimal tempVal0 = offsetValue.multiply(shiftMultiplier);
BigDecimal tempVal = (offsetNumber.subtract(tempVal0));
return (tempVal.divide(shiftMultiplier));
}
/**
* Encodes date value into string format that can be compared lexicographically
*
* @param date
* date value to be encoded
* @return string representation of the date value
*/
public static String encodeDate(Date date) {
SimpleDateFormat dateFormatter = new SimpleDateFormat(dateFormat);
dateFormatter.setTimeZone(TimeZone.getTimeZone(UTC_TZ_ID));
/* Java doesn't handle ISO8601 nicely: need to add ':' manually */
String result = dateFormatter.format(date);
return result.substring(0, result.length() - ENCODE_DATE_COLONS_INDEX) + ":"
+ result.substring(result.length() - ENCODE_DATE_COLONS_INDEX);
}
/**
* Decodes date value from the string representation created using encodeDate(..) function.
*
* @param value
* string representation of the date value
* @return original date value
*/
public static Date decodeDate(String value) throws ParseException {
String javaValue = value.substring(0, value.length() - DECODE_DATE_COLONS_INDEX)
+ value.substring(value.length() - ENCODE_DATE_COLONS_INDEX);
SimpleDateFormat dateFormatter = new SimpleDateFormat(dateFormat);
dateFormatter.setTimeZone(TimeZone.getTimeZone(UTC_TZ_ID));
return dateFormatter.parse(javaValue);
}
/**
* Encodes byteArray value into a base64-encoded string.
*
* @return string representation of the date value
*/
public static String encodeByteArray(byte[] byteArray) {
try {
return new String(Base64.encodeBase64(byteArray), UTF8_ENCODING);
} catch(UnsupportedEncodingException e) {
throw new MappingException("Could not encode byteArray to UTF8 encoding", e);
}
}
/**
* Decodes byte[] value from the string representation created using encodeDate(..) function.
*
* @param value
* string representation of the date value
* @return original byte[] value
*/
public static byte[] decodeByteArray(String value) throws ParseException {
try {
return Base64.decodeBase64(value.getBytes(UTF8_ENCODING));
} catch(UnsupportedEncodingException e) {
throw new MappingException("Could not decode byteArray to UTF8 encoding", e);
}
}
private static BigDecimal tryToStoreAsRealBigDecimal(Object ob) {
BigDecimal bigDecimal = null;
if(canBeStoredAsRealBigDecimal(ob)) {
bigDecimal = new BigDecimal(ob.toString());
} else if(ob instanceof BigDecimal) {
bigDecimal = (BigDecimal) ob;
}
return bigDecimal;
}
private static BigDecimal tryToStoreAsIntegerBigDecimal(Object ob) {
BigDecimal bigDecimal = null;
if(canBeStoredAsIntegerBigDecimal(ob)) {
bigDecimal = new BigDecimal(ob.toString());
}
return bigDecimal;
}
private static boolean canBeStoredAsRealBigDecimal(Object ob) {
if(isNaN(ob) || isInfinite(ob)) {
return false;
}
return ob instanceof Double || ob instanceof Float;
}
private static boolean canBeStoredAsIntegerBigDecimal(Object ob) {
return ob instanceof Number && !(ob instanceof Float || ob instanceof Double);
}
public static boolean isNaN(Object ob) {
return (ob instanceof Double && ((Double) ob).isNaN()) || (ob instanceof Float && ((Float) ob).isNaN());
}
public static boolean isInfinite(Object ob) {
return (ob instanceof Double && ((Double) ob).isInfinite())
|| (ob instanceof Float && ((Float) ob).isInfinite());
}
}