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.filter;
020
021import java.io.IOException;
022import java.util.ArrayList;
023
024import org.apache.hadoop.hbase.Cell;
025import org.apache.hadoop.hbase.CompareOperator;
026import org.apache.yetus.audience.InterfaceAudience;
027import org.apache.hadoop.hbase.exceptions.DeserializationException;
028import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
029import org.apache.hadoop.hbase.shaded.protobuf.generated.FilterProtos;
030import org.apache.hbase.thirdparty.com.google.protobuf.InvalidProtocolBufferException;
031
032/**
033 * This filter is used to filter based on the key. It takes an operator
034 * (equal, greater, not equal, etc) and a byte [] comparator for the row,
035 * and column qualifier portions of a key.
036 * <p>
037 * This filter can be wrapped with {@link WhileMatchFilter} to add more control.
038 * <p>
039 * Multiple filters can be combined using {@link FilterList}.
040 * <p>
041 * If an already known row range needs to be scanned, 
042 * use {@link org.apache.hadoop.hbase.CellScanner} start
043 * and stop rows directly rather than a filter.
044 */
045@InterfaceAudience.Public
046public class RowFilter extends CompareFilter {
047  private boolean filterOutRow = false;
048
049  /**
050   * Constructor.
051   * @param op the compare op for row matching
052   * @param rowComparator the comparator for row matching
053   */
054  public RowFilter(final CompareOperator op,
055                   final ByteArrayComparable rowComparator) {
056    super(op, rowComparator);
057  }
058
059  @Override
060  public void reset() {
061    this.filterOutRow = false;
062  }
063
064  @Override
065  public ReturnCode filterCell(final Cell v) {
066    if(this.filterOutRow) {
067      return ReturnCode.NEXT_ROW;
068    }
069    return ReturnCode.INCLUDE;
070  }
071
072  @Override
073  public boolean filterRowKey(Cell firstRowCell) {
074    if (compareRow(getCompareOperator(), this.comparator, firstRowCell)) {
075      this.filterOutRow = true;
076    }
077    return this.filterOutRow;
078  }
079
080  @Override
081  public boolean filterRow() {
082    return this.filterOutRow;
083  }
084
085  public static Filter createFilterFromArguments(ArrayList<byte []> filterArguments) {
086    @SuppressWarnings("rawtypes") // for arguments
087    ArrayList arguments = CompareFilter.extractArguments(filterArguments);
088    CompareOperator compareOp = (CompareOperator)arguments.get(0);
089    ByteArrayComparable comparator = (ByteArrayComparable)arguments.get(1);
090    return new RowFilter(compareOp, comparator);
091  }
092
093 /**
094  * @return The filter serialized using pb
095  */
096  @Override
097  public byte [] toByteArray() {
098    FilterProtos.RowFilter.Builder builder =
099      FilterProtos.RowFilter.newBuilder();
100    builder.setCompareFilter(super.convert());
101    return builder.build().toByteArray();
102  }
103
104  /**
105   * @param pbBytes A pb serialized {@link RowFilter} instance
106   * @return An instance of {@link RowFilter} made from <code>bytes</code>
107   * @throws DeserializationException
108   * @see #toByteArray
109   */
110  public static RowFilter parseFrom(final byte [] pbBytes)
111  throws DeserializationException {
112    FilterProtos.RowFilter proto;
113    try {
114      proto = FilterProtos.RowFilter.parseFrom(pbBytes);
115    } catch (InvalidProtocolBufferException e) {
116      throw new DeserializationException(e);
117    }
118    final CompareOperator valueCompareOp =
119      CompareOperator.valueOf(proto.getCompareFilter().getCompareOp().name());
120    ByteArrayComparable valueComparator = null;
121    try {
122      if (proto.getCompareFilter().hasComparator()) {
123        valueComparator = ProtobufUtil.toComparator(proto.getCompareFilter().getComparator());
124      }
125    } catch (IOException ioe) {
126      throw new DeserializationException(ioe);
127    }
128    return new RowFilter(valueCompareOp,valueComparator);
129  }
130
131  /**
132   * @return true if and only if the fields of the filter that are serialized
133   * are equal to the corresponding fields in other.  Used for testing.
134   */
135  @Override
136  boolean areSerializedFieldsEqual(Filter o) {
137    if (o == this) return true;
138    if (!(o instanceof RowFilter)) return false;
139
140    return super.areSerializedFieldsEqual(o);
141  }
142
143  @Override
144  public boolean equals(Object obj) {
145    return obj instanceof Filter && areSerializedFieldsEqual((Filter) obj);
146  }
147
148  @Override
149  public int hashCode() {
150    return super.hashCode();
151  }
152}