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 * @deprecated since 3.0.0 and will be removed in 4.0.0 039 */ 040 @Deprecated 041 public static final OrderedNumeric ASCENDING = new OrderedNumeric(Order.ASCENDING); 042 /** 043 * @deprecated since 3.0.0 and will be removed in 4.0.0 044 */ 045 @Deprecated 046 public static final OrderedNumeric DESCENDING = new OrderedNumeric(Order.DESCENDING); 047 048 /** 049 * Creates a new {@link Number} of arbitrary precision and variable-length encoding. 050 * @param order the {@link Order} to use 051 */ 052 public OrderedNumeric(Order order) { 053 super(order); 054 } 055 056 @Override 057 public int encodedLength(Number val) { 058 // TODO: this could be done better. 059 PositionedByteRange buff = new SimplePositionedMutableByteRange(100); 060 return encode(buff, val); 061 } 062 063 @Override 064 public Class<Number> encodedClass() { 065 return Number.class; 066 } 067 068 @Override 069 public Number decode(PositionedByteRange src) { 070 if (OrderedBytes.isNumericInfinite(src) || OrderedBytes.isNumericNaN(src)) { 071 return OrderedBytes.decodeNumericAsDouble(src); 072 } 073 return OrderedBytes.decodeNumericAsBigDecimal(src); 074 } 075 076 @Override 077 public int encode(PositionedByteRange dst, Number val) { 078 if (null == val) { 079 return OrderedBytes.encodeNull(dst, order); 080 } else if (val instanceof BigDecimal) { 081 return OrderedBytes.encodeNumeric(dst, (BigDecimal) val, order); 082 } else if (val instanceof BigInteger) { 083 return OrderedBytes.encodeNumeric(dst, new BigDecimal((BigInteger) val), order); 084 } else if (val instanceof Double || val instanceof Float) { 085 return OrderedBytes.encodeNumeric(dst, val.doubleValue(), order); 086 } else { 087 // TODO: other instances of Numeric to consider? 088 return OrderedBytes.encodeNumeric(dst, val.longValue(), order); 089 } 090 } 091 092 /** 093 * Read a {@code long} value from the buffer {@code src}. 094 * @param src the {@link PositionedByteRange} to read the {@code long} from 095 * @return the {@code long} read from the buffer 096 */ 097 public long decodeLong(PositionedByteRange src) { 098 return OrderedBytes.decodeNumericAsLong(src); 099 } 100 101 /** 102 * Write instance {@code val} into buffer {@code dst}. 103 * @param dst the {@link PositionedByteRange} to write to 104 * @param val the value to write to {@code dst} 105 * @return the number of bytes written 106 */ 107 public int encodeLong(PositionedByteRange dst, long val) { 108 return OrderedBytes.encodeNumeric(dst, val, order); 109 } 110 111 /** 112 * Read a {@code double} value from the buffer {@code src}. 113 * @param src the {@link PositionedByteRange} to read the {@code double} from 114 * @return the {@code double} read from the buffer 115 */ 116 public double decodeDouble(PositionedByteRange src) { 117 return OrderedBytes.decodeNumericAsLong(src); 118 } 119 120 /** 121 * Write instance {@code val} into buffer {@code dst}. 122 * @param dst the {@link PositionedByteRange} to write to 123 * @param val the value to write to {@code dst} 124 * @return the number of bytes written 125 */ 126 public int encodeDouble(PositionedByteRange dst, double val) { 127 return OrderedBytes.encodeNumeric(dst, val, order); 128 } 129}