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; 022 023import org.apache.hadoop.hbase.util.Order; 024import org.apache.hadoop.hbase.util.OrderedBytes; 025import org.apache.hadoop.hbase.util.PositionedByteRange; 026import org.apache.hadoop.hbase.util.SimplePositionedMutableByteRange; 027import org.apache.yetus.audience.InterfaceAudience; 028 029/** 030 * An {@link Number} of arbitrary precision and variable-length encoding. The 031 * resulting length of encoded values is determined by the numerical (base 032 * 100) precision, not absolute value. Use this data type anywhere you would 033 * expect to use a {@code DECIMAL} type, a {@link BigDecimal}, a 034 * {@link BigInteger}, or any time you've parsed floating precision values 035 * from text. Built on {@link OrderedBytes#encodeNumeric(PositionedByteRange, BigDecimal, Order)}. 036 */ 037@InterfaceAudience.Public 038public class OrderedNumeric extends OrderedBytesBase<Number> { 039 040 public static final OrderedNumeric ASCENDING = new OrderedNumeric(Order.ASCENDING); 041 public static final OrderedNumeric DESCENDING = new OrderedNumeric(Order.DESCENDING); 042 043 protected OrderedNumeric(Order order) { 044 super(order); 045 } 046 047 @Override 048 public int encodedLength(Number val) { 049 // TODO: this could be done better. 050 PositionedByteRange buff = new SimplePositionedMutableByteRange(100); 051 return encode(buff, val); 052 } 053 054 @Override 055 public Class<Number> encodedClass() { 056 return Number.class; 057 } 058 059 @Override 060 public Number decode(PositionedByteRange src) { 061 if (OrderedBytes.isNumericInfinite(src) || OrderedBytes.isNumericNaN(src)) { 062 return OrderedBytes.decodeNumericAsDouble(src); 063 } 064 return OrderedBytes.decodeNumericAsBigDecimal(src); 065 } 066 067 @Override 068 public int encode(PositionedByteRange dst, Number val) { 069 if (null == val) { 070 return OrderedBytes.encodeNull(dst, order); 071 } else if (val instanceof BigDecimal) { 072 return OrderedBytes.encodeNumeric(dst, (BigDecimal) val, order); 073 } else if (val instanceof BigInteger) { 074 return OrderedBytes.encodeNumeric(dst, new BigDecimal((BigInteger) val), order); 075 } else if (val instanceof Double || val instanceof Float) { 076 return OrderedBytes.encodeNumeric(dst, val.doubleValue(), order); 077 } else { 078 // TODO: other instances of Numeric to consider? 079 return OrderedBytes.encodeNumeric(dst, val.longValue(), order); 080 } 081 } 082 083 /** 084 * Read a {@code long} value from the buffer {@code src}. 085 */ 086 public long decodeLong(PositionedByteRange src) { 087 return OrderedBytes.decodeNumericAsLong(src); 088 } 089 090 /** 091 * Write instance {@code val} into buffer {@code dst}. 092 */ 093 public int encodeLong(PositionedByteRange dst, long val) { 094 return OrderedBytes.encodeNumeric(dst, val, order); 095 } 096 097 /** 098 * Read a {@code double} value from the buffer {@code src}. 099 */ 100 public double decodeDouble(PositionedByteRange src) { 101 return OrderedBytes.decodeNumericAsLong(src); 102 } 103 104 /** 105 * Write instance {@code val} into buffer {@code dst}. 106 */ 107 public int encodeDouble(PositionedByteRange dst, double val) { 108 return OrderedBytes.encodeNumeric(dst, val, order); 109 } 110}