View Javadoc

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