diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/GroupListScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/GroupListScreen.java index c2cce8ac9a..8c54b580c8 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/GroupListScreen.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/GroupListScreen.java @@ -18,6 +18,8 @@ import com.google.gerrit.client.Gerrit; import com.google.gerrit.client.groups.GroupMap; import com.google.gerrit.client.rpc.ScreenLoadCallback; import com.google.gerrit.client.ui.AccountScreen; +import com.google.gerrit.client.ui.FilteredUserInterface; +import com.google.gerrit.client.ui.IgnoreOutdatedFilterResultsCallbackWrapper; import com.google.gerrit.common.PageLinks; import com.google.gwt.event.dom.client.KeyUpEvent; import com.google.gwt.event.dom.client.KeyUpHandler; @@ -25,7 +27,7 @@ import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwtexpui.globalkey.client.NpTextBox; -public class GroupListScreen extends AccountScreen { +public class GroupListScreen extends AccountScreen implements FilteredUserInterface { private GroupTable groups; private NpTextBox filterTxt; private String subname; @@ -37,25 +39,20 @@ public class GroupListScreen extends AccountScreen { } private void refresh() { - final String mySubname = subname; - GroupMap.match(subname, new ScreenLoadCallback(this) { - @Override - protected void preDisplay(final GroupMap result) { - if ((mySubname == null && subname == null) - || (mySubname != null && mySubname.equals(subname))) { - display(result); - } - // Else ignore the result, the user has already changed subname and - // the result is not relevant anymore. If multiple RPC's are fired - // the results may come back out-of-order and a non-relevant result - // could overwrite the correct result if not ignored. - } - }); + GroupMap.match(subname, + new IgnoreOutdatedFilterResultsCallbackWrapper(this, + new ScreenLoadCallback(this) { + @Override + protected void preDisplay(final GroupMap result) { + groups.display(result, subname); + groups.finishDisplay(); + } + })); } - private void display(final GroupMap result) { - groups.display(result, subname); - groups.finishDisplay(); + @Override + public String getCurrentFilter() { + return subname; } @Override diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectListScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectListScreen.java index 331a642000..4795bdae7f 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectListScreen.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectListScreen.java @@ -20,7 +20,9 @@ import com.google.gerrit.client.GitwebLink; import com.google.gerrit.client.projects.ProjectInfo; import com.google.gerrit.client.projects.ProjectMap; import com.google.gerrit.client.rpc.ScreenLoadCallback; +import com.google.gerrit.client.ui.FilteredUserInterface; import com.google.gerrit.client.ui.HighlightingInlineHyperlink; +import com.google.gerrit.client.ui.IgnoreOutdatedFilterResultsCallbackWrapper; import com.google.gerrit.client.ui.ProjectSearchLink; import com.google.gerrit.client.ui.ProjectsTable; import com.google.gerrit.client.ui.Screen; @@ -34,7 +36,7 @@ import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwtexpui.globalkey.client.NpTextBox; -public class ProjectListScreen extends Screen { +public class ProjectListScreen extends Screen implements FilteredUserInterface { private ProjectsTable projects; private NpTextBox filterTxt; private String subname; @@ -46,20 +48,19 @@ public class ProjectListScreen extends Screen { } private void refresh() { - final String mySubname = subname; - ProjectMap.match(subname, new ScreenLoadCallback(this) { - @Override - protected void preDisplay(final ProjectMap result) { - if ((mySubname == null && subname == null) - || (mySubname != null && mySubname.equals(subname))) { - projects.display(result); - } - // Else ignore the result, the user has already changed subname and - // the result is not relevant anymore. If multiple RPC's are fired - // the results may come back out-of-order and a non-relevant result - // could overwrite the correct result if not ignored. - } - }); + ProjectMap.match(subname, + new IgnoreOutdatedFilterResultsCallbackWrapper(this, + new ScreenLoadCallback(this) { + @Override + protected void preDisplay(final ProjectMap result) { + projects.display(result); + } + })); + } + + @Override + public String getCurrentFilter() { + return subname; } @Override diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/FilteredUserInterface.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/FilteredUserInterface.java new file mode 100644 index 0000000000..02244d011b --- /dev/null +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/FilteredUserInterface.java @@ -0,0 +1,25 @@ +// Copyright (C) 2013 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.ui; + +public interface FilteredUserInterface { + /** + * Return the value by which the user interface is currently filtered. + * + * @return value by which the user interface is currently filtered, + * null or empty String if currently no filter is applied + */ + public String getCurrentFilter(); +} diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/IgnoreOutdatedFilterResultsCallbackWrapper.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/IgnoreOutdatedFilterResultsCallbackWrapper.java new file mode 100644 index 0000000000..c9cadccc75 --- /dev/null +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/IgnoreOutdatedFilterResultsCallbackWrapper.java @@ -0,0 +1,50 @@ +// Copyright (C) 2013 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.ui; + +import com.google.gerrit.client.rpc.GerritCallback; + +/** + * GerritCallback to be used on user interfaces that allow filtering to handle + * RPC's that request filtering. The user may change the filter quickly so that + * a response may be outdated when the client receives it. In this case the + * response must be ignored because the responses to RCP's may come out-of-order + * and an outdated response would overwrite the correct result which was + * received before. + */ +public class IgnoreOutdatedFilterResultsCallbackWrapper extends GerritCallback { + private final FilteredUserInterface filteredUI; + private final String myFilter; + private final GerritCallback cb; + + public IgnoreOutdatedFilterResultsCallbackWrapper( + final FilteredUserInterface filteredUI, final GerritCallback cb) { + this.filteredUI = filteredUI; + this.myFilter = filteredUI.getCurrentFilter(); + this.cb = cb; + } + + @Override + public void onSuccess(final T result) { + if ((myFilter == null && filteredUI.getCurrentFilter() == null) + || (myFilter != null && myFilter.equals(filteredUI.getCurrentFilter()))) { + cb.onSuccess(result); + } + // Else ignore the result, the user has already changed the filter + // and the result is not relevant anymore. If multiple RPC's are + // fired the results may come back out-of-order and a non-relevant + // result could overwrite the correct result if not ignored. + } +} diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectListPopup.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectListPopup.java index 9f0d6afc9e..cac766794e 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectListPopup.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectListPopup.java @@ -36,7 +36,7 @@ import com.google.gwtexpui.globalkey.client.NpTextBox; import com.google.gwtexpui.user.client.PluginSafeDialogBox; /** It creates a popup containing all the projects. */ -public class ProjectListPopup { +public class ProjectListPopup implements FilteredUserInterface { private HighlightingProjectsTable projectsTab; private PluginSafeDialogBox popup; private NpTextBox filterTxt; @@ -174,27 +174,22 @@ public class ProjectListPopup { } protected void populateProjects() { - final String mySubname = subname; - ProjectMap.match(subname, new GerritCallback() { - @Override - public void onSuccess(final ProjectMap result) { - if ((mySubname == null && subname == null) - || (mySubname != null && mySubname.equals(subname))) { - display(result); - } - // Else ignore the result, the user has already changed subname and - // the result is not relevant anymore. If multiple RPC's are fired - // the results may come back out-of-order and a non-relevant result - // could overwrite the correct result if not ignored. - } - }); + ProjectMap.match(subname, + new IgnoreOutdatedFilterResultsCallbackWrapper(this, + new GerritCallback() { + @Override + public void onSuccess(final ProjectMap result) { + projectsTab.display(result, subname); + if (firstPopupLoad) { // Display was delayed until table was loaded + firstPopupLoad = false; + displayPopup(); + } + } + })); } - private void display(final ProjectMap result) { - projectsTab.display(result, subname); - if (firstPopupLoad) { // Display was delayed until table was loaded - firstPopupLoad = false; - displayPopup(); - } + @Override + public String getCurrentFilter() { + return subname; } }