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