001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.types; 019 020import java.math.BigDecimal; 021import java.math.BigInteger; 022import org.apache.hadoop.hbase.util.Order; 023import org.apache.hadoop.hbase.util.OrderedBytes; 024import org.apache.hadoop.hbase.util.PositionedByteRange; 025import org.apache.hadoop.hbase.util.SimplePositionedMutableByteRange; 026import org.apache.yetus.audience.InterfaceAudience; 027 028/** 029 * An {@link Number} of arbitrary precision and variable-length encoding. The resulting length of 030 * encoded values is determined by the numerical (base 100) precision, not absolute value. Use this 031 * data type anywhere you would expect to use a {@code DECIMAL} type, a {@link BigDecimal}, a 032 * {@link BigInteger}, or any time you've parsed floating precision values from text. Built on 033 * {@link OrderedBytes#encodeNumeric(PositionedByteRange, BigDecimal, Order)}. 034 */ 035@InterfaceAudience.Public 036public class OrderedNumeric extends OrderedBytesBase<Number> { 037 038 public static final OrderedNumeric ASCENDING = new OrderedNumeric(Order.ASCENDING); 039 public static final OrderedNumeric DESCENDING = new OrderedNumeric(Order.DESCENDING); 040 041 protected OrderedNumeric(Order order) { 042 super(order); 043 } 044 045 @Override 046 public int encodedLength(Number val) { 047 // TODO: this could be done better. 048 PositionedByteRange buff = new SimplePositionedMutableByteRange(100); 049 return encode(buff, val); 050 } 051 052 @Override 053 public Class<Number> encodedClass() { 054 return Number.class; 055 } 056 057 @Override 058 public Number decode(PositionedByteRange src) { 059 if (OrderedBytes.isNumericInfinite(src) || OrderedBytes.isNumericNaN(src)) { 060 return OrderedBytes.decodeNumericAsDouble(src); 061 } 062 return OrderedBytes.decodeNumericAsBigDecimal(src); 063 } 064 065 @Override 066 public int encode(PositionedByteRange dst, Number val) { 067 if (null == val) { 068 return OrderedBytes.encodeNull(dst, order); 069 } else if (val instanceof BigDecimal) { 070 return OrderedBytes.encodeNumeric(dst, (BigDecimal) val, order); 071 } else if (val instanceof BigInteger) { 072 return OrderedBytes.encodeNumeric(dst, new BigDecimal((BigInteger) val), order); 073 } else if (val instanceof Double || val instanceof Float) { 074 return OrderedBytes.encodeNumeric(dst, val.doubleValue(), order); 075 } else { 076 // TODO: other instances of Numeric to consider? 077 return OrderedBytes.encodeNumeric(dst, val.longValue(), order); 078 } 079 } 080 081 /** 082 * Read a {@code long} value from the buffer {@code src}. 083 */ 084 public long decodeLong(PositionedByteRange src) { 085 return OrderedBytes.decodeNumericAsLong(src); 086 } 087 088 /** 089 * Write instance {@code val} into buffer {@code dst}. 090 */ 091 public int encodeLong(PositionedByteRange dst, long val) { 092 return OrderedBytes.encodeNumeric(dst, val, order); 093 } 094 095 /** 096 * Read a {@code double} value from the buffer {@code src}. 097 */ 098 public double decodeDouble(PositionedByteRange src) { 099 return OrderedBytes.decodeNumericAsLong(src); 100 } 101 102 /** 103 * Write instance {@code val} into buffer {@code dst}. 104 */ 105 public int encodeDouble(PositionedByteRange dst, double val) { 106 return OrderedBytes.encodeNumeric(dst, val, order); 107 } 108}