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         ReturnCode code = filter.filterKeyValue(v);
172         switch (code) {
173         case INCLUDE:
174           continue;
175         case NEXT_ROW:
176         case SKIP:
177           return ReturnCode.SKIP;
178         default:
179           return code;
180         }
181       } else if (operator == Operator.MUST_PASS_ONE) {
182         if (filter.filterAllRemaining()) {
183           continue;
184         }
185 
186         switch (filter.filterKeyValue(v)) {
187         case INCLUDE:
188           rc = ReturnCode.INCLUDE;
189           // must continue here to evaluate all filters
190         case NEXT_ROW:
191         case SKIP:
192           // continue;
193         }
194       }
195     }
196     return rc;
197   }
198 
199   @Override
200   public void filterRow(List<KeyValue> kvs) {
201     for (Filter filter : filters) {
202       filter.filterRow(kvs);
203     }
204   }
205 
206   @Override
207   public boolean hasFilterRow() {
208     for (Filter filter : filters) {
209       if(filter.hasFilterRow()) {
210     	return true;
211       }
212     }
213     return false;
214   }
215 
216   @Override
217   public boolean filterRow() {
218     for (Filter filter : filters) {
219       if (operator == Operator.MUST_PASS_ALL) {
220         if (filter.filterAllRemaining() || filter.filterRow()) {
221           return true;
222         }
223       } else if (operator == Operator.MUST_PASS_ONE) {
224         if (!filter.filterAllRemaining()
225             && !filter.filterRow()) {
226           return false;
227         }
228       }
229     }
230     return  operator == Operator.MUST_PASS_ONE;
231   }
232 
233   public void readFields(final DataInput in) throws IOException {
234     byte opByte = in.readByte();
235     operator = Operator.values()[opByte];
236     int size = in.readInt();
237     if (size > 0) {
238       filters = new ArrayList<Filter>(size);
239       for (int i = 0; i < size; i++) {
240         Filter filter = (Filter)HbaseObjectWritable.readObject(in, conf);
241         filters.add(filter);
242       }
243     }
244   }
245 
246   public void write(final DataOutput out) throws IOException {
247     out.writeByte(operator.ordinal());
248     out.writeInt(filters.size());
249     for (Filter filter : filters) {
250       HbaseObjectWritable.writeObject(out, filter, Writable.class, conf);
251     }
252   }
253 
254   @Override
255   public KeyValue getNextKeyHint(KeyValue currentKV) {
256     return null;
257   }
258 }