View Javadoc

1   /**
2    * Copyright 2010 The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  
21  package org.apache.hadoop.hbase.filter;
22  
23  import org.apache.hadoop.hbase.io.HbaseObjectWritable;
24  import org.apache.hadoop.hbase.util.Bytes;
25  
26  import java.io.DataInput;
27  import java.io.DataOutput;
28  import java.io.IOException;
29  import java.util.ArrayList;
30  
31  import com.google.common.base.Preconditions;
32  /**
33   * This is a generic filter to be used to filter by comparison.  It takes an
34   * operator (equal, greater, not equal, etc) and a byte [] comparator.
35   * <p>
36   * To filter by row key, use {@link RowFilter}.
37   * <p>
38   * To filter by column qualifier, use {@link QualifierFilter}.
39   * <p>
40   * To filter by value, use {@link SingleColumnValueFilter}.
41   * <p>
42   * These filters can be wrapped with {@link SkipFilter} and {@link WhileMatchFilter}
43   * to add more control.
44   * <p>
45   * Multiple filters can be combined using {@link FilterList}.
46   */
47  public abstract class CompareFilter extends FilterBase {
48  
49    /** Comparison operators. */
50    public enum CompareOp {
51      /** less than */
52      LESS,
53      /** less than or equal to */
54      LESS_OR_EQUAL,
55      /** equals */
56      EQUAL,
57      /** not equal */
58      NOT_EQUAL,
59      /** greater than or equal to */
60      GREATER_OR_EQUAL,
61      /** greater than */
62      GREATER,
63      /** no operation */
64      NO_OP,
65    }
66  
67    protected CompareOp compareOp;
68    protected WritableByteArrayComparable comparator;
69  
70    /**
71     * Writable constructor, do not use.
72     */
73    public CompareFilter() {
74    }
75  
76    /**
77     * Constructor.
78     * @param compareOp the compare op for row matching
79     * @param comparator the comparator for row matching
80     */
81    public CompareFilter(final CompareOp compareOp,
82        final WritableByteArrayComparable comparator) {
83      this.compareOp = compareOp;
84      this.comparator = comparator;
85    }
86  
87    /**
88     * @return operator
89     */
90    public CompareOp getOperator() {
91      return compareOp;
92    }
93  
94    /**
95     * @return the comparator
96     */
97    public WritableByteArrayComparable getComparator() {
98      return comparator;
99    }
100 
101   protected boolean doCompare(final CompareOp compareOp,
102       final WritableByteArrayComparable comparator, final byte [] data,
103       final int offset, final int length) {
104     if (compareOp == CompareOp.NO_OP) {
105       return true;
106     }
107     int compareResult = comparator.compareTo(data, offset, length);
108     switch (compareOp) {
109       case LESS:
110         return compareResult <= 0;
111       case LESS_OR_EQUAL:
112         return compareResult < 0;
113       case EQUAL:
114         return compareResult != 0;
115       case NOT_EQUAL:
116         return compareResult == 0;
117       case GREATER_OR_EQUAL:
118         return compareResult > 0;
119       case GREATER:
120         return compareResult >= 0;
121       default:
122         throw new RuntimeException("Unknown Compare op " +
123           compareOp.name());
124     }
125   }
126 
127   public static ArrayList extractArguments(ArrayList<byte []> filterArguments) {
128     Preconditions.checkArgument(filterArguments.size() == 2,
129                                 "Expected 2 but got: %s", filterArguments.size());
130     CompareOp compareOp = ParseFilter.createCompareOp(filterArguments.get(0));
131     WritableByteArrayComparable comparator = ParseFilter.createComparator(
132       ParseFilter.removeQuotesFromByteArray(filterArguments.get(1)));
133 
134     if (comparator instanceof RegexStringComparator ||
135         comparator instanceof SubstringComparator) {
136       if (compareOp != CompareOp.EQUAL &&
137           compareOp != CompareOp.NOT_EQUAL) {
138         throw new IllegalArgumentException ("A regexstring comparator and substring comparator" +
139                                             " can only be used with EQUAL and NOT_EQUAL");
140       }
141     }
142     ArrayList arguments = new ArrayList();
143     arguments.add(compareOp);
144     arguments.add(comparator);
145     return arguments;
146   }
147 
148   public void readFields(DataInput in) throws IOException {
149     compareOp = CompareOp.valueOf(in.readUTF());
150     comparator = (WritableByteArrayComparable)
151       HbaseObjectWritable.readObject(in, null);
152   }
153 
154   public void write(DataOutput out) throws IOException {
155     out.writeUTF(compareOp.name());
156     HbaseObjectWritable.writeObject(out, comparator,
157       WritableByteArrayComparable.class, null);
158   }
159 
160   @Override
161   public String toString() {
162     return String.format("%s (%s, %s)",
163         this.getClass().getSimpleName(),
164         this.compareOp.name(),
165         Bytes.toStringBinary(this.comparator.getValue()));
166   }
167 }