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