View Javadoc

1   /*
2    * Copyright (c) 2011.  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  package org.apache.hadoop.hbase.hbql.filter;
21  
22  import org.apache.commons.logging.Log;
23  import org.apache.commons.logging.LogFactory;
24  import org.apache.hadoop.conf.Configuration;
25  import org.apache.hadoop.hbase.HBaseConfiguration;
26  import org.apache.hadoop.hbase.KeyValue;
27  import org.apache.hadoop.hbase.filter.Filter;
28  import org.apache.hadoop.hbase.filter.FilterBase;
29  import org.apache.hadoop.hbase.io.HbaseObjectWritable;
30  import org.apache.hadoop.io.Writable;
31  
32  import java.io.DataInput;
33  import java.io.DataOutput;
34  import java.io.IOException;
35  import java.util.ArrayList;
36  import java.util.List;
37  
38  /**
39   * Implementation of {@link Filter} that represents an ordered List of Filters
40   * which will be evaluated with a specified boolean operator {@link Operator#MUST_PASS_ALL}
41   * (<code>!AND</code>) or {@link Operator#MUST_PASS_ONE} (<code>!OR</code>).
42   * Since you can use Filter Lists as children of Filter Lists, you can create a
43   * hierarchy of filters to be evaluated.
44   * Defaults to {@link Operator#MUST_PASS_ALL}.
45   * <p>TODO: Fix creation of Configuration on serialization and deserialization.
46   */
47  public class RecordFilterList extends FilterBase {
48  
49      private static final Log LOG = LogFactory.getLog(RecordFilterList.class);
50  
51      /**
52       * set operator
53       */
54      public static enum Operator {
55          /**
56           * !AND
57           */
58          MUST_PASS_ALL,
59          /**
60           * !OR
61           */
62          MUST_PASS_ONE
63      }
64  
65      private Operator     operator = Operator.MUST_PASS_ALL;
66      private List<Filter> filters  = new ArrayList<Filter>();
67  
68      /**
69       * Default constructor, filters nothing. Required though for RPC
70       * deserialization.
71       */
72      public RecordFilterList() {
73          super();
74      }
75  
76      /**
77       * Constructor that takes a set of {@link Filter}s. The default operator
78       * MUST_PASS_ALL is assumed.
79       *
80       * @param rowFilters
81       */
82      public RecordFilterList(final List<Filter> rowFilters) {
83          this.filters = rowFilters;
84      }
85  
86      /**
87       * Constructor that takes an operator.
88       *
89       * @param operator Operator to process filter set with.
90       */
91      public RecordFilterList(final Operator operator) {
92          this.operator = operator;
93      }
94  
95      /**
96       * Constructor that takes a set of {@link Filter}s and an operator.
97       *
98       * @param operator   Operator to process filter set with.
99       * @param rowFilters Set of row filters.
100      */
101     public RecordFilterList(final Operator operator, final List<Filter> rowFilters) {
102         this.filters = rowFilters;
103         this.operator = operator;
104     }
105 
106     /**
107      * Get the operator.
108      *
109      * @return operator
110      */
111     public Operator getOperator() {
112         return operator;
113     }
114 
115     /**
116      * Get the filters.
117      *
118      * @return filters
119      */
120     public List<Filter> getFilters() {
121         return filters;
122     }
123 
124     /**
125      * Add a filter.
126      *
127      * @param filter
128      */
129     public void addFilter(Filter filter) {
130         this.filters.add(filter);
131     }
132 
133     public void reset() {
134         for (Filter filter : filters) {
135             filter.reset();
136         }
137     }
138 
139     public boolean filterRowKey(byte[] rowKey, int offset, int length) {
140         for (Filter filter : filters) {
141             if (this.operator == Operator.MUST_PASS_ALL) {
142                 if (filter.filterAllRemaining() ||
143                     filter.filterRowKey(rowKey, offset, length)) {
144                     return true;
145                 }
146             }
147             else if (this.operator == Operator.MUST_PASS_ONE) {
148                 if (!filter.filterAllRemaining() &&
149                     !filter.filterRowKey(rowKey, offset, length)) {
150                     return false;
151                 }
152             }
153         }
154         return this.operator == Operator.MUST_PASS_ONE;
155     }
156 
157     public boolean filterAllRemaining() {
158         for (Filter filter : filters) {
159             if (filter.filterAllRemaining()) {
160                 if (operator == Operator.MUST_PASS_ALL) {
161                     return true;
162                 }
163             }
164             else {
165                 if (operator == Operator.MUST_PASS_ONE) {
166                     return false;
167                 }
168             }
169         }
170         return operator == Operator.MUST_PASS_ONE;
171     }
172 
173     public ReturnCode filterKeyValue(KeyValue v) {
174 
175         for (Filter filter : filters) {
176             if (operator == Operator.MUST_PASS_ALL) {
177                 if (filter.filterAllRemaining()) {
178                     return ReturnCode.NEXT_ROW;
179                 }
180                 switch (filter.filterKeyValue(v)) {
181                     case INCLUDE:
182                         continue;
183                     case NEXT_ROW:
184                         return ReturnCode.NEXT_ROW;  /* DIFF */
185                     case SKIP:
186                         return ReturnCode.SKIP;
187                 }
188             }
189             else if (operator == Operator.MUST_PASS_ONE) {
190                 if (filter.filterAllRemaining()) {
191                     continue;
192                 }
193 
194                 switch (filter.filterKeyValue(v)) {
195                     case INCLUDE:
196                         /* DIFF return ReturnCode.INCLUDE; */
197                     case NEXT_ROW:
198                     case SKIP:
199                         continue;
200                 }
201             }
202         }
203         return /* DIFF operator == Operator.MUST_PASS_ONE ? ReturnCode.SKIP :*/ ReturnCode.INCLUDE;
204     }
205 
206     public boolean filterRow() {
207         for (Filter filter : filters) {
208             if (operator == Operator.MUST_PASS_ALL) {
209                 if (filter.filterAllRemaining() || filter.filterRow()) {
210                     return true;
211                 }
212             }
213             else if (operator == Operator.MUST_PASS_ONE) {
214                 if (!filter.filterAllRemaining()
215                     && !filter.filterRow()) {
216                     return false;
217                 }
218             }
219         }
220         return operator == Operator.MUST_PASS_ONE;
221     }
222 
223     public void readFields(final DataInput in) throws IOException {
224         Configuration conf = HBaseConfiguration.create();
225         byte opByte = in.readByte();
226         operator = Operator.values()[opByte];
227         int size = in.readInt();
228         if (size > 0) {
229             filters = new ArrayList<Filter>(size);
230             for (int i = 0; i < size; i++) {
231                 Filter filter = (Filter)HbaseObjectWritable.readObject(in, conf);
232                 filters.add(filter);
233             }
234         }
235     }
236 
237     public void write(final DataOutput out) throws IOException {
238         Configuration conf = HBaseConfiguration.create();
239         out.writeByte(operator.ordinal());
240         out.writeInt(filters.size());
241         for (Filter filter : filters) {
242             HbaseObjectWritable.writeObject(out, filter, Writable.class, conf);
243         }
244     }
245 }