001/** 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019package org.apache.hadoop.hbase.filter; 020 021import java.io.IOException; 022import java.util.ArrayList; 023import java.util.Arrays; 024import java.util.Collections; 025import java.util.List; 026 027import org.apache.hadoop.hbase.Cell; 028import org.apache.yetus.audience.InterfaceAudience; 029import org.apache.hadoop.hbase.exceptions.DeserializationException; 030 031import org.apache.hbase.thirdparty.com.google.protobuf.InvalidProtocolBufferException; 032import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; 033import org.apache.hadoop.hbase.shaded.protobuf.generated.FilterProtos; 034 035/** 036 * Implementation of {@link Filter} that represents an ordered List of Filters which will be 037 * evaluated with a specified boolean operator {@link Operator#MUST_PASS_ALL} (<code>AND</code>) or 038 * {@link Operator#MUST_PASS_ONE} (<code>OR</code>). Since you can use Filter Lists as children of 039 * Filter Lists, you can create a hierarchy of filters to be evaluated. <br> 040 * {@link Operator#MUST_PASS_ALL} evaluates lazily: evaluation stops as soon as one filter does not 041 * include the Cell. <br> 042 * {@link Operator#MUST_PASS_ONE} evaluates non-lazily: all filters are always evaluated. <br> 043 * Defaults to {@link Operator#MUST_PASS_ALL}. 044 */ 045@InterfaceAudience.Public 046final public class FilterList extends FilterBase { 047 048 /** set operator */ 049 @InterfaceAudience.Public 050 public enum Operator { 051 /** !AND */ 052 MUST_PASS_ALL, 053 /** !OR */ 054 MUST_PASS_ONE 055 } 056 057 private Operator operator; 058 private FilterListBase filterListBase; 059 060 /** 061 * Constructor that takes a set of {@link Filter}s and an operator. 062 * @param operator Operator to process filter set with. 063 * @param filters Set of row filters. 064 */ 065 public FilterList(final Operator operator, final List<Filter> filters) { 066 if (operator == Operator.MUST_PASS_ALL) { 067 filterListBase = new FilterListWithAND(filters); 068 } else if (operator == Operator.MUST_PASS_ONE) { 069 filterListBase = new FilterListWithOR(filters); 070 } else { 071 throw new IllegalArgumentException("Invalid operator: " + operator); 072 } 073 this.operator = operator; 074 } 075 076 /** 077 * Constructor that takes a set of {@link Filter}s. The default operator MUST_PASS_ALL is assumed. 078 * All filters are cloned to internal list. 079 * @param filters list of filters 080 */ 081 public FilterList(final List<Filter> filters) { 082 this(Operator.MUST_PASS_ALL, filters); 083 } 084 085 /** 086 * Constructor that takes a var arg number of {@link Filter}s. The default operator MUST_PASS_ALL 087 * is assumed. 088 * @param filters 089 */ 090 public FilterList(final Filter... filters) { 091 this(Operator.MUST_PASS_ALL, Arrays.asList(filters)); 092 } 093 094 /** 095 * Constructor that takes an operator. 096 * @param operator Operator to process filter set with. 097 */ 098 public FilterList(final Operator operator) { 099 this(operator, new ArrayList<>()); 100 } 101 102 /** 103 * Constructor that takes a var arg number of {@link Filter}s and an operator. 104 * @param operator Operator to process filter set with. 105 * @param filters Filters to use 106 */ 107 public FilterList(final Operator operator, final Filter... filters) { 108 this(operator, Arrays.asList(filters)); 109 } 110 111 /** 112 * Get the operator. 113 * @return operator 114 */ 115 public Operator getOperator() { 116 return operator; 117 } 118 119 /** 120 * Get the filters. 121 * @return filters 122 */ 123 public List<Filter> getFilters() { 124 return filterListBase.getFilters(); 125 } 126 127 public int size() { 128 return filterListBase.size(); 129 } 130 131 public void addFilter(List<Filter> filters) { 132 filterListBase.addFilterLists(filters); 133 } 134 135 /** 136 * Add a filter. 137 * @param filter another filter 138 */ 139 public void addFilter(Filter filter) { 140 addFilter(Collections.singletonList(filter)); 141 } 142 143 @Override 144 public void reset() throws IOException { 145 filterListBase.reset(); 146 } 147 148 @Override 149 public boolean filterRowKey(byte[] rowKey, int offset, int length) throws IOException { 150 return filterListBase.filterRowKey(rowKey, offset, length); 151 } 152 153 @Override 154 public boolean filterRowKey(Cell firstRowCell) throws IOException { 155 return filterListBase.filterRowKey(firstRowCell); 156 } 157 158 @Override 159 public boolean filterAllRemaining() throws IOException { 160 return filterListBase.filterAllRemaining(); 161 } 162 163 @Override 164 public Cell transformCell(Cell c) throws IOException { 165 return filterListBase.transformCell(c); 166 } 167 168 @Override 169 @Deprecated 170 public ReturnCode filterKeyValue(final Cell c) throws IOException { 171 return filterCell(c); 172 } 173 174 @Override 175 public ReturnCode filterCell(final Cell c) throws IOException { 176 return filterListBase.filterCell(c); 177 } 178 179 /** 180 * Filters that never filter by modifying the returned List of Cells can inherit this 181 * implementation that does nothing. {@inheritDoc} 182 */ 183 @Override 184 public void filterRowCells(List<Cell> cells) throws IOException { 185 filterListBase.filterRowCells(cells); 186 } 187 188 @Override 189 public boolean hasFilterRow() { 190 return filterListBase.hasFilterRow(); 191 } 192 193 @Override 194 public boolean filterRow() throws IOException { 195 return filterListBase.filterRow(); 196 } 197 198 /** 199 * @return The filter serialized using pb 200 */ 201 @Override 202 public byte[] toByteArray() throws IOException { 203 FilterProtos.FilterList.Builder builder = FilterProtos.FilterList.newBuilder(); 204 builder.setOperator(FilterProtos.FilterList.Operator.valueOf(operator.name())); 205 ArrayList<Filter> filters = filterListBase.getFilters(); 206 for (int i = 0, n = filters.size(); i < n; i++) { 207 builder.addFilters(ProtobufUtil.toFilter(filters.get(i))); 208 } 209 return builder.build().toByteArray(); 210 } 211 212 /** 213 * @param pbBytes A pb serialized {@link FilterList} instance 214 * @return An instance of {@link FilterList} made from <code>bytes</code> 215 * @throws DeserializationException 216 * @see #toByteArray 217 */ 218 public static FilterList parseFrom(final byte[] pbBytes) throws DeserializationException { 219 FilterProtos.FilterList proto; 220 try { 221 proto = FilterProtos.FilterList.parseFrom(pbBytes); 222 } catch (InvalidProtocolBufferException e) { 223 throw new DeserializationException(e); 224 } 225 226 List<Filter> rowFilters = new ArrayList<>(proto.getFiltersCount()); 227 try { 228 List<FilterProtos.Filter> filtersList = proto.getFiltersList(); 229 for (int i = 0, n = filtersList.size(); i < n; i++) { 230 rowFilters.add(ProtobufUtil.toFilter(filtersList.get(i))); 231 } 232 } catch (IOException ioe) { 233 throw new DeserializationException(ioe); 234 } 235 return new FilterList(Operator.valueOf(proto.getOperator().name()), rowFilters); 236 } 237 238 /** 239 * @param other 240 * @return true if and only if the fields of the filter that are serialized are equal to the 241 * corresponding fields in other. Used for testing. 242 */ 243 @Override 244 boolean areSerializedFieldsEqual(Filter other) { 245 if (other == this) return true; 246 if (!(other instanceof FilterList)) return false; 247 248 FilterList o = (FilterList) other; 249 return this.getOperator().equals(o.getOperator()) 250 && ((this.getFilters() == o.getFilters()) || this.getFilters().equals(o.getFilters())); 251 } 252 253 @Override 254 public Cell getNextCellHint(Cell currentCell) throws IOException { 255 return this.filterListBase.getNextCellHint(currentCell); 256 } 257 258 @Override 259 public boolean isFamilyEssential(byte[] name) throws IOException { 260 return this.filterListBase.isFamilyEssential(name); 261 } 262 263 @Override 264 public void setReversed(boolean reversed) { 265 this.reversed = reversed; 266 this.filterListBase.setReversed(reversed); 267 } 268 269 @Override 270 public boolean isReversed() { 271 assert this.reversed == this.filterListBase.isReversed(); 272 return this.reversed; 273 } 274 275 @Override 276 public String toString() { 277 return this.filterListBase.toString(); 278 } 279}