001/*
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements.  See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership.  The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License.  You may obtain a copy of the License at
010 *
011 *     http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 */
019package org.apache.hadoop.hbase.client.coprocessor;
020
021import java.io.IOException;
022import java.math.BigDecimal;
023import java.math.RoundingMode;
024
025import org.apache.hadoop.hbase.Cell;
026import org.apache.hadoop.hbase.CellUtil;
027import org.apache.hadoop.hbase.HBaseInterfaceAudience;
028import org.apache.hadoop.hbase.PrivateCellUtil;
029import org.apache.yetus.audience.InterfaceAudience;
030import org.apache.yetus.audience.InterfaceStability;
031import org.apache.hadoop.hbase.coprocessor.ColumnInterpreter;
032import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.BigDecimalMsg;
033import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.EmptyMsg;
034import org.apache.hadoop.hbase.util.ByteStringer;
035import org.apache.hadoop.hbase.util.Bytes;
036
037/**
038 * ColumnInterpreter for doing Aggregation's with BigDecimal columns. This class
039 * is required at the RegionServer also.
040 *
041 */
042@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC)
043@InterfaceStability.Evolving
044public class BigDecimalColumnInterpreter extends ColumnInterpreter<BigDecimal, BigDecimal,
045  EmptyMsg, BigDecimalMsg, BigDecimalMsg> {
046
047  @Override
048  public BigDecimal getValue(byte[] colFamily, byte[] colQualifier, Cell kv)
049      throws IOException {
050    if (kv == null || CellUtil.cloneValue(kv) == null) {
051      return null;
052    }
053    return PrivateCellUtil.getValueAsBigDecimal(kv).setScale(2, RoundingMode.HALF_EVEN);
054  }
055
056  @Override
057  public BigDecimal add(BigDecimal bd1, BigDecimal bd2) {
058    if (bd1 == null ^ bd2 == null) {
059      return (bd1 == null) ? bd2 : bd1; // either of one is null.
060    }
061    if (bd1 == null) {
062      return null;
063    }
064    return bd1.add(bd2);
065  }
066
067  @Override
068  public int compare(final BigDecimal bd1, final BigDecimal bd2) {
069    if (bd1 == null ^ bd2 == null) {
070      return bd1 == null ? -1 : 1; // either of one is null.
071    }
072    if (bd1 == null) {
073      return 0; // both are null
074    }
075    return bd1.compareTo(bd2); // natural ordering.
076  }
077
078  @Override
079  public BigDecimal getMaxValue() {
080    return BigDecimal.valueOf(Double.MAX_VALUE);
081  }
082
083  @Override
084  public BigDecimal increment(BigDecimal bd) {
085    return bd == null ? null : (bd.add(BigDecimal.ONE));
086  }
087
088  @Override
089  public BigDecimal multiply(BigDecimal bd1, BigDecimal bd2) {
090    return (bd1 == null || bd2 == null) ? null : bd1.multiply(bd2)
091        .setScale(2,RoundingMode.HALF_EVEN);
092  }
093
094  @Override
095  public BigDecimal getMinValue() {
096    return BigDecimal.valueOf(Double.MIN_VALUE);
097  }
098
099  @Override
100  public double divideForAvg(BigDecimal bd1, Long l2) {
101    return (l2 == null || bd1 == null) ? Double.NaN : (bd1.doubleValue() / l2
102        .doubleValue());
103  }
104
105  @Override
106  public BigDecimal castToReturnType(BigDecimal bd) {
107    return bd;
108  }
109
110  @Override
111  public BigDecimal castToCellType(BigDecimal bd) {
112    return bd;
113  }
114
115  @Override
116  public EmptyMsg getRequestData() {
117    return EmptyMsg.getDefaultInstance();
118  }
119
120  @Override
121  public void initialize(EmptyMsg msg) {
122    //nothing
123  }
124
125  private BigDecimalMsg getProtoForType(BigDecimal t) {
126    BigDecimalMsg.Builder builder = BigDecimalMsg.newBuilder();
127    return builder.setBigdecimalMsg(ByteStringer.wrap(Bytes.toBytes(t))).build();
128  }
129
130  @Override
131  public BigDecimalMsg getProtoForCellType(BigDecimal t) {
132    return getProtoForType(t);
133  }
134
135  @Override
136  public BigDecimalMsg getProtoForPromotedType(BigDecimal s) {
137    return getProtoForType(s);
138  }
139
140  @Override
141  public BigDecimal getPromotedValueFromProto(BigDecimalMsg r) {
142    return Bytes.toBigDecimal(r.getBigdecimalMsg().toByteArray());
143  }
144
145  @Override
146  public BigDecimal getCellValueFromProto(BigDecimalMsg q) {
147    return Bytes.toBigDecimal(q.getBigdecimalMsg().toByteArray());
148  }
149}