Files
gerrit/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchSuggestOracle.java
Edwin Kempin 10b49dce9c Support 'conflicts:<change>' operator to find changes with same files
The 'conflicts=<change>' search operator finds all changes that touch at
least one file that was also touched by the given change. If this
operator is combined with 'status:open' all changes that potentially
conflict with the given change are returned. In future this result may
be displayed on the change screen in some kind of change dashboard. In
future we may also test for the returned changes whether they actually
conflict with the given change, taking the 'automatically resolve
conflicts' setting of the project into account. Then it would be
possible to show all conflicting changes on the change screen.

Change-Id: I637255b131466bac09338e08039d5fd171f71431
Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
2013-11-05 07:46:28 +01:00

267 lines
9.1 KiB
Java

// Copyright (C) 2012 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.client;
import com.google.gerrit.client.ui.AccountGroupSuggestOracle;
import com.google.gerrit.client.ui.AccountSuggestOracle;
import com.google.gerrit.client.ui.ProjectNameSuggestOracle;
import com.google.gwt.user.client.ui.SuggestOracle;
import com.google.gwtexpui.safehtml.client.HighlightSuggestOracle;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.TreeSet;
public class SearchSuggestOracle extends HighlightSuggestOracle {
private static final List<ParamSuggester> paramSuggester = Arrays.asList(
new ParamSuggester("project:", new ProjectNameSuggestOracle()),
new ParamSuggester(Arrays.asList("owner:", "reviewer:"),
new AccountSuggestOracle() {
@Override
public void onRequestSuggestions(final Request request, final Callback done) {
super.onRequestSuggestions(request, new Callback() {
@Override
public void onSuggestionsReady(final Request request,
final Response response) {
if ("self".startsWith(request.getQuery())) {
final ArrayList<SuggestOracle.Suggestion> r =
new ArrayList<SuggestOracle.Suggestion>(response
.getSuggestions().size() + 1);
r.addAll(response.getSuggestions());
r.add(new SuggestOracle.Suggestion() {
@Override
public String getDisplayString() {
return getReplacementString();
}
@Override
public String getReplacementString() {
return "self";
}
});
response.setSuggestions(r);
}
done.onSuggestionsReady(request, response);
}
});
}
}),
new ParamSuggester(Arrays.asList("ownerin:", "reviewerin:"),
new AccountGroupSuggestOracle()));
private static final TreeSet<String> suggestions = new TreeSet<String>();
static {
suggestions.add("age:");
suggestions.add("age:1week"); // Give an example age
suggestions.add("change:");
suggestions.add("owner:");
suggestions.add("owner:self");
suggestions.add("ownerin:");
suggestions.add("reviewer:");
suggestions.add("reviewer:self");
suggestions.add("reviewerin:");
suggestions.add("commit:");
suggestions.add("comment:");
suggestions.add("conflicts:");
suggestions.add("project:");
suggestions.add("branch:");
suggestions.add("topic:");
suggestions.add("ref:");
suggestions.add("tr:");
suggestions.add("bug:");
suggestions.add("label:");
suggestions.add("message:");
suggestions.add("file:");
suggestions.add("has:");
suggestions.add("has:draft");
suggestions.add("has:star");
suggestions.add("is:");
suggestions.add("is:starred");
suggestions.add("is:watched");
suggestions.add("is:reviewed");
suggestions.add("is:owner");
suggestions.add("is:reviewer");
suggestions.add("is:open");
suggestions.add("is:draft");
suggestions.add("is:closed");
suggestions.add("is:submitted");
suggestions.add("is:merged");
suggestions.add("is:abandoned");
suggestions.add("status:");
suggestions.add("status:open");
suggestions.add("status:reviewed");
suggestions.add("status:submitted");
suggestions.add("status:closed");
suggestions.add("status:merged");
suggestions.add("status:abandoned");
suggestions.add("AND");
suggestions.add("OR");
suggestions.add("NOT");
}
@Override
public void requestDefaultSuggestions(Request request, Callback done) {
final ArrayList<SearchSuggestion> r = new ArrayList<SearchSuggestOracle.SearchSuggestion>();
// No text - show some default suggestions.
r.add(new SearchSuggestion("status:open", "status:open"));
r.add(new SearchSuggestion("age:1week", "age:1week"));
if (Gerrit.isSignedIn()) {
r.add(new SearchSuggestion("owner:self", "owner:self"));
}
done.onSuggestionsReady(request, new Response(r));
}
@Override
protected void onRequestSuggestions(Request request, Callback done) {
final String query = request.getQuery();
final String lastWord = getLastWord(query);
if (lastWord == null) {
// Starting a new word - don't show suggestions yet.
done.onSuggestionsReady(request, null);
return;
}
for (final ParamSuggester ps : paramSuggester) {
if (ps.applicable(lastWord)) {
ps.suggest(lastWord, request, done);
return;
}
}
final ArrayList<SearchSuggestion> r = new ArrayList<SearchSuggestOracle.SearchSuggestion>();
for (String suggestion : suggestions.tailSet(lastWord)) {
if ((lastWord.length() < suggestion.length()) && suggestion.startsWith(lastWord)) {
if (suggestion.contains("self") && !Gerrit.isSignedIn()) {
continue;
}
r.add(new SearchSuggestion(suggestion, query + suggestion.substring(lastWord.length())));
}
}
done.onSuggestionsReady(request, new Response(r));
}
private String getLastWord(final String query) {
final int lastSpace = query.lastIndexOf(' ');
if (lastSpace == query.length() - 1) {
return null;
}
if (lastSpace == -1) {
return query;
}
return query.substring(lastSpace + 1);
}
@Override
protected String getQueryPattern(final String query) {
return super.getQueryPattern(getLastWord(query));
}
@Override
protected boolean isHTML() {
return true;
}
private static class SearchSuggestion implements SuggestOracle.Suggestion {
private final String suggestion;
private final String fullQuery;
public SearchSuggestion(String suggestion, String fullQuery) {
this.suggestion = suggestion;
// Add a space to the query if it is a complete operation (e.g.
// "status:open") so the user can keep on typing.
this.fullQuery = fullQuery.endsWith(":") ? fullQuery : fullQuery + " ";
}
@Override
public String getDisplayString() {
return suggestion;
}
@Override
public String getReplacementString() {
return fullQuery;
}
}
private static class ParamSuggester {
private final List<String> operators;
private final SuggestOracle parameterSuggestionOracle;
ParamSuggester(final String operator,
final SuggestOracle parameterSuggestionOracle) {
this(Collections.singletonList(operator), parameterSuggestionOracle);
}
ParamSuggester(final List<String> operators,
final SuggestOracle parameterSuggestionOracle) {
this.operators = operators;
this.parameterSuggestionOracle = parameterSuggestionOracle;
}
boolean applicable(final String query) {
final String operator = getApplicableOperator(query, operators);
return operator != null && query.length() > operator.length();
}
private String getApplicableOperator(final String lastWord,
final List<String> operators) {
for (final String operator : operators) {
if (lastWord.startsWith(operator)) {
return operator;
}
}
return null;
}
void suggest(final String lastWord, final Request request, final Callback done) {
final String operator = getApplicableOperator(lastWord, operators);
parameterSuggestionOracle.requestSuggestions(
new Request(lastWord.substring(operator.length()), request.getLimit()),
new Callback() {
@Override
public void onSuggestionsReady(final Request req,
final Response response) {
final String query = request.getQuery();
final List<SearchSuggestOracle.Suggestion> r =
new ArrayList<SuggestOracle.Suggestion>(response
.getSuggestions().size());
for (final SearchSuggestOracle.Suggestion s : response
.getSuggestions()) {
r.add(new SearchSuggestion(s.getDisplayString(),
query.substring(0, query.length() - lastWord.length()) +
operator + quoteIfNeeded(s.getReplacementString())));
}
done.onSuggestionsReady(request, new Response(r));
}
private String quoteIfNeeded(final String s) {
if (!s.matches("^\\S*$")) {
return "\"" + s + "\"";
}
return s;
}
});
}
}
}