| // Copyright (C) 2021 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.server.query.change; |
| |
| import com.google.gerrit.index.query.NotPredicate; |
| import com.google.gerrit.index.query.Predicate; |
| import com.google.gerrit.server.index.change.ChangeField; |
| |
| public class IsSubmittablePredicate extends BooleanPredicate { |
| public IsSubmittablePredicate() { |
| super(ChangeField.IS_SUBMITTABLE_SPEC); |
| } |
| |
| /** |
| * Rewrite the is:submittable predicate. |
| * |
| * <p>If we run a query with "is:submittable OR -is:submittable" the result should match all |
| * changes. In Lucene, we keep separate sub-indexes for open and closed changes. The Lucene |
| * backend inspects the input predicate and depending on all its child predicates decides if the |
| * query should run against the open sub-index, closed sub-index or both. |
| * |
| * <p>The "is:submittable" operator is implemented as: |
| * |
| * <p>issubmittable:1 |
| * |
| * <p>But we want to exclude closed changes from being matched by this query. For the normal case, |
| * we rewrite the query as: |
| * |
| * <p>issubmittable:1 AND status:new |
| * |
| * <p>Hence Lucene will match the query against the open sub-index. For the negated case (i.e. |
| * "-is:submittable"), we cannot just negate the previous query because it would result in: |
| * |
| * <p>-(issubmittable:1 AND status:new) |
| * |
| * <p>Lucene will conclude that it should look for changes that are <b>not</b> new and hence will |
| * run the query against the closed sub-index, not matching with changes that are open but not |
| * submittable. For this case, we need to rewrite the query to match with closed changes <b>or</b> |
| * changes that are not submittable. |
| */ |
| public static Predicate<ChangeData> rewrite(Predicate<ChangeData> in) { |
| if (in instanceof IsSubmittablePredicate) { |
| return Predicate.and( |
| new BooleanPredicate(ChangeField.IS_SUBMITTABLE_SPEC), ChangeStatusPredicate.open()); |
| } |
| if (in instanceof NotPredicate && in.getChild(0) instanceof IsSubmittablePredicate) { |
| return Predicate.or( |
| Predicate.not(new BooleanPredicate(ChangeField.IS_SUBMITTABLE_SPEC)), |
| ChangeStatusPredicate.closed()); |
| } |
| return in; |
| } |
| } |