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;
024import org.apache.hadoop.hbase.Cell;
025import org.apache.hadoop.hbase.CellUtil;
026import org.apache.hadoop.hbase.HBaseInterfaceAudience;
027import org.apache.hadoop.hbase.PrivateCellUtil;
028import org.apache.hadoop.hbase.coprocessor.ColumnInterpreter;
029import org.apache.hadoop.hbase.util.Bytes;
030import org.apache.yetus.audience.InterfaceAudience;
031import org.apache.yetus.audience.InterfaceStability;
032
033import org.apache.hbase.thirdparty.com.google.protobuf.UnsafeByteOperations;
034
035import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.BigDecimalMsg;
036import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.EmptyMsg;
037
038/**
039 * ColumnInterpreter for doing Aggregation's with BigDecimal columns. This class
040 * is required at the RegionServer also.
041 *
042 */
043@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC)
044@InterfaceStability.Evolving
045public class BigDecimalColumnInterpreter extends ColumnInterpreter<BigDecimal, BigDecimal,
046  EmptyMsg, BigDecimalMsg, BigDecimalMsg> {
047
048  @Override
049  public BigDecimal getValue(byte[] colFamily, byte[] colQualifier, Cell kv)
050      throws IOException {
051    if (kv == null || CellUtil.cloneValue(kv) == null) {
052      return null;
053    }
054    return PrivateCellUtil.getValueAsBigDecimal(kv).setScale(2, RoundingMode.HALF_EVEN);
055  }
056
057  @Override
058  public BigDecimal add(BigDecimal bd1, BigDecimal bd2) {
059    if (bd1 == null ^ bd2 == null) {
060      return (bd1 == null) ? bd2 : bd1; // either of one is null.
061    }
062    if (bd1 == null) {
063      return null;
064    }
065    return bd1.add(bd2);
066  }
067
068  @Override
069  public int compare(final BigDecimal bd1, final BigDecimal bd2) {
070    if (bd1 == null ^ bd2 == null) {
071      return bd1 == null ? -1 : 1; // either of one is null.
072    }
073    if (bd1 == null) {
074      return 0; // both are null
075    }
076    return bd1.compareTo(bd2); // natural ordering.
077  }
078
079  @Override
080  public BigDecimal getMaxValue() {
081    return BigDecimal.valueOf(Double.MAX_VALUE);
082  }
083
084  @Override
085  public BigDecimal increment(BigDecimal bd) {
086    return bd == null ? null : (bd.add(BigDecimal.ONE));
087  }
088
089  @Override
090  public BigDecimal multiply(BigDecimal bd1, BigDecimal bd2) {
091    return (bd1 == null || bd2 == null) ? null : bd1.multiply(bd2)
092        .setScale(2,RoundingMode.HALF_EVEN);
093  }
094
095  @Override
096  public BigDecimal getMinValue() {
097    return BigDecimal.valueOf(Double.MIN_VALUE);
098  }
099
100  @Override
101  public double divideForAvg(BigDecimal bd1, Long l2) {
102    return (l2 == null || bd1 == null) ? Double.NaN : (bd1.doubleValue() / l2
103        .doubleValue());
104  }
105
106  @Override
107  public BigDecimal castToReturnType(BigDecimal bd) {
108    return bd;
109  }
110
111  @Override
112  public BigDecimal castToCellType(BigDecimal bd) {
113    return bd;
114  }
115
116  @Override
117  public EmptyMsg getRequestData() {
118    return EmptyMsg.getDefaultInstance();
119  }
120
121  @Override
122  public void initialize(EmptyMsg msg) {
123    //nothing
124  }
125
126  private BigDecimalMsg getProtoForType(BigDecimal t) {
127    BigDecimalMsg.Builder builder = BigDecimalMsg.newBuilder();
128    return builder.setBigdecimalMsg(UnsafeByteOperations.unsafeWrap(Bytes.toBytes(t))).build();
129  }
130
131  @Override
132  public BigDecimalMsg getProtoForCellType(BigDecimal t) {
133    return getProtoForType(t);
134  }
135
136  @Override
137  public BigDecimalMsg getProtoForPromotedType(BigDecimal s) {
138    return getProtoForType(s);
139  }
140
141  @Override
142  public BigDecimal getPromotedValueFromProto(BigDecimalMsg r) {
143    return Bytes.toBigDecimal(r.getBigdecimalMsg().toByteArray());
144  }
145
146  @Override
147  public BigDecimal getCellValueFromProto(BigDecimalMsg q) {
148    return Bytes.toBigDecimal(q.getBigdecimalMsg().toByteArray());
149  }
150}