blob: f5f30bd097c2f30310b1316bdc699f784aad622e [file] [log] [blame]
// Copyright (C) 2016 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.index.query;
import static com.google.common.base.Preconditions.checkArgument;
import com.google.common.collect.ImmutableList;
import com.google.gerrit.index.IndexConfig;
import java.util.Collection;
import java.util.List;
public class AndSource<T> extends AndPredicate<T> implements DataSource<T> {
protected final DataSource<T> source;
private final IsVisibleToPredicate<T> isVisibleToPredicate;
private final int start;
private final int cardinality;
private final IndexConfig indexConfig;
public AndSource(Collection<? extends Predicate<T>> that, IndexConfig indexConfig) {
this(that, null, 0, indexConfig);
}
public AndSource(
Predicate<T> that, IsVisibleToPredicate<T> isVisibleToPredicate, IndexConfig indexConfig) {
this(that, isVisibleToPredicate, 0, indexConfig);
}
public AndSource(
Predicate<T> that,
IsVisibleToPredicate<T> isVisibleToPredicate,
int start,
IndexConfig indexConfig) {
this(ImmutableList.of(that), isVisibleToPredicate, start, indexConfig);
}
public AndSource(
Collection<? extends Predicate<T>> that,
IsVisibleToPredicate<T> isVisibleToPredicate,
int start,
IndexConfig indexConfig) {
super(that);
checkArgument(start >= 0, "negative start: %s", start);
this.isVisibleToPredicate = isVisibleToPredicate;
this.start = start;
this.indexConfig = indexConfig;
int c = Integer.MAX_VALUE;
Predicate<T> selectedSource = null;
int minCardinality = Integer.MAX_VALUE;
for (Predicate<T> p : getChildren()) {
if (p instanceof DataSource) {
DataSource<?> source = (DataSource<?>) p;
int cardinality = source.getCardinality();
c = Math.min(c, source.getCardinality());
if (selectedSource == null
|| cardinality < minCardinality
|| (cardinality == minCardinality
&& p.estimateCost() < selectedSource.estimateCost())) {
selectedSource = p;
minCardinality = cardinality;
}
}
}
if (selectedSource == null) {
throw new IllegalArgumentException("No DataSource Found");
}
this.source = toPaginatingSource(selectedSource);
this.cardinality = c;
}
@Override
public ResultSet<T> read() {
return source.read();
}
@Override
public ResultSet<FieldBundle> readRaw() {
return source.readRaw();
}
@Override
public boolean isMatchable() {
return isVisibleToPredicate != null || super.isMatchable();
}
@Override
public boolean match(T object) {
if (isVisibleToPredicate != null && !isVisibleToPredicate.match(object)) {
return false;
}
if (super.isMatchable() && !super.match(object)) {
return false;
}
return true;
}
protected List<T> transformBuffer(List<T> buffer) {
return buffer;
}
@Override
public int getCardinality() {
return cardinality;
}
@SuppressWarnings("unchecked")
private PaginatingSource<T> toPaginatingSource(Predicate<T> pred) {
return new PaginatingSource<>((DataSource<T>) pred, start, indexConfig) {
@Override
protected boolean match(T object) {
return AndSource.this.match(object);
}
@Override
protected boolean isMatchable() {
return AndSource.this.isMatchable();
}
};
}
}