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