java/code/src/com/redhat/rhn/frontend/action/channel/PackageSearchAction.java | 115 ++++++++--
java/code/src/com/redhat/rhn/frontend/strings/java/StringResource_en_US.xml | 2
java/code/src/com/redhat/rhn/frontend/strings/jsp/StringResource_en_US.xml | 14 +
java/code/webapp/WEB-INF/pages/channel/packagesearch.jsp | 46 ++--
java/code/webapp/WEB-INF/struts-config.xml | 1
5 files changed, 145 insertions(+), 33 deletions(-)
New commits:
commit 1db3377621dd1cd8950ed6f850760f04431b5df7
Author: Jason Dobies <jason.dobies(a)redhat.com>
Date: Fri May 29 16:58:06 2009 -0400
457316 - Added search for packages in a particular channel.
Restructured the page to be a radio-button based selection of which criteria to use (relevant channel, specific channel, specific architecture).
diff --git a/java/code/src/com/redhat/rhn/frontend/action/channel/PackageSearchAction.java b/java/code/src/com/redhat/rhn/frontend/action/channel/PackageSearchAction.java
index 419a18a..cccb13e 100644
--- a/java/code/src/com/redhat/rhn/frontend/action/channel/PackageSearchAction.java
+++ b/java/code/src/com/redhat/rhn/frontend/action/channel/PackageSearchAction.java
@@ -18,7 +18,10 @@ package com.redhat.rhn.frontend.action.channel;
import com.redhat.rhn.common.localization.LocalizationService;
import com.redhat.rhn.common.validator.ValidatorException;
import com.redhat.rhn.domain.channel.ChannelArch;
+import com.redhat.rhn.domain.channel.Channel;
+import com.redhat.rhn.domain.user.User;
import com.redhat.rhn.frontend.dto.PackageOverview;
+import com.redhat.rhn.frontend.dto.PackageDto;
import com.redhat.rhn.frontend.struts.RequestContext;
import com.redhat.rhn.frontend.struts.RhnAction;
import com.redhat.rhn.frontend.taglibs.list.ListTagHelper;
@@ -158,16 +161,36 @@ public class PackageSearchAction extends RhnAction {
RequestContext ctx = new RequestContext(request);
String searchString = form.getString("search_string");
String viewmode = form.getString("view_mode");
- String relevant = StringUtils.defaultString(
- request.getParameter("relevant"));
- String[] selectedArches = form.getStrings("channel_arch");
-
- if (selectedArches.length < 1) {
- relevant = "yes";
+ String searchCriteria = request.getParameter("whereCriteria");
+ String[] selectedArches = null;
+ Long filterChannelId = null;
+ boolean relevantFlag = false;
+
+ // Default to relevant channels if no search criteria was specified
+ if (searchCriteria == null || searchCriteria.equals("")) {
+ searchCriteria = "relevant";
}
-
+
+ // Handle the radio button selection for channel filtering
+ if (searchCriteria.equals("relevant")) {
+ relevantFlag = true;
+ }
+ if (searchCriteria.equals("architecture")) {
+ /* The search call will function as being scoped to architectures if the arch
+ list isn't null. In order to actually get radio-button-like functionality
+ we can't rely on the arch list coming in from the form to be null; the
+ user may have selected an arch but *not* the radio button for arch. If we
+ push off retrieving the arches until we know we want to use them, we can
+ get the desired functionality described by the UI.
+ */
+ selectedArches = form.getStrings("channel_arch");
+ }
+ else if (searchCriteria.equals("channel")) {
+ String sChannelId = form.getString("channel_filter");
+ filterChannelId = Long.parseLong(sChannelId);
+ }
+
if (viewmode.equals("")) { //first time viewing page
- relevant = "yes";
viewmode = PackageSearchHelper.OPT_NAME_AND_SUMMARY;
}
@@ -201,21 +224,36 @@ public class PackageSearchAction extends RhnAction {
!archLabels.contains(arch.getLabel()));
}
}
-
+
+ // Load list of available channels to select as filter
+ List allChannels =
+ ChannelManager.allChannelsTree(ctx.getLoggedInUser());
+
request.setAttribute("search_string", searchString);
request.setAttribute("view_mode", viewmode);
- request.setAttribute("relevant", relevant);
request.setAttribute("searchOptions", searchOptions);
request.setAttribute("channelArches", channelArches);
request.setAttribute("channel_arch", selectedArches);
+ request.setAttribute("allChannels", allChannels);
+
+ // Default where to search criteria
+ request.setAttribute("whereCriteria", searchCriteria);
if (!StringUtils.isBlank(searchString)) {
List<PackageOverview> results =
PackageSearchHelper.performSearch(ctx.getWebSession().getId(),
searchString,
viewmode,
- selectedArches);
+ selectedArches, relevantFlag);
+
+ // Perform any post-search logic that wasn't done by the search server
results = removeDuplicateNames(results);
+
+ if (filterChannelId != null) {
+ User user = ctx.getLoggedInUser();
+ results = filterByChannel(user, filterChannelId, results);
+ }
+
log.warn("GET search: " + results);
request.setAttribute("pageList",
results != null ? results : Collections.EMPTY_LIST);
@@ -224,12 +262,18 @@ public class PackageSearchAction extends RhnAction {
request.setAttribute("pageList", Collections.EMPTY_LIST);
}
}
-
+
+ /**
+ * Package Search returns a list of all matching packages, this will likely
+ * include multiple packages with the same name but different version, release,
+ * epoch. WebUI only wants a list of unique package names, so we need
+ * to strip the duplicate names while preserving order.
+ *
+ * @param pkgs packages returned from search that should be cleaned
+ * @return new list object with duplicates removed; does not change the list in place
+ */
private List<PackageOverview> removeDuplicateNames(List<PackageOverview> pkgs) {
- // Package Search returns a list of all matching packages, this will likely
- // include multiple packages with the same name but different version, release,
- // epoch. WebUI only wants a list of unique package names, so we need
- // to strip the duplicate names while preserving order.
+
List<PackageOverview> result = new ArrayList<PackageOverview>();
for (PackageOverview pkgOver : pkgs) {
boolean addPkg = true;
@@ -246,6 +290,45 @@ public class PackageSearchAction extends RhnAction {
return result;
}
+ /**
+ * Since the search server does not carry channel information, we do any channel
+ * filtering in the Java stack. This method will return a new list of packages that
+ * containing packages that are present in the given channel; others returned from
+ * the search will be removed.
+ *
+ * @param user user making the request
+ * @param channelId channel against which the filter should be run
+ * @param pkgs list of packages returned from the search query that should be
+ * filtered
+ * @return new list object with duplicates removed; does not change the list in place
+ */
+ private List<PackageOverview> filterByChannel(User user, Long channelId,
+ List<PackageOverview> pkgs) {
+
+ Channel channel = ChannelManager.lookupByIdAndUser(channelId, user);
+ List<PackageDto> allPackagesList = ChannelManager.listAllPackages(channel);
+
+ // Convert the package list into a map for quicker lookup
+ Map<String, String> packageNamesMap =
+ new HashMap<String, String>(allPackagesList.size());
+
+ for (PackageDto dto : allPackagesList) {
+ String name = dto.getName();
+ packageNamesMap.put(name, name);
+ }
+
+ // Iterate results and remove if not in the channel
+ List<PackageOverview> newResult = new ArrayList<PackageOverview>();
+ for (PackageOverview pkg : pkgs) {
+ String packageName = pkg.getPackageName();
+ if (packageNamesMap.get(packageName) != null) {
+ newResult.add(pkg);
+ }
+ }
+
+ return newResult;
+ }
+
private void addOption(List options, String key, String value) {
addOption(options, key, value, false);
}
diff --git a/java/code/src/com/redhat/rhn/frontend/strings/java/StringResource_en_US.xml b/java/code/src/com/redhat/rhn/frontend/strings/java/StringResource_en_US.xml
index 4f6af70..eefc958 100644
--- a/java/code/src/com/redhat/rhn/frontend/strings/java/StringResource_en_US.xml
+++ b/java/code/src/com/redhat/rhn/frontend/strings/java/StringResource_en_US.xml
@@ -2668,7 +2668,7 @@ available for this kickstart profile to function properly.
</context-group>
</trans-unit>
<trans-unit id="searchserver.index_out_of_sync_with_db">
- <source>SearchServer index and database entries appear to be out of sync. Please run '/sbin/service rhn-search cleanindex; /sbin/service rhn-search start'</source>
+ <source>SearchServer index and database entries appear to be out of sync. Please run '/sbin/service rhn-search cleanindex'</source>
<context-group name="ctx">
<context context-type="sourcefile">/rhn/channels/Search</context>
</context-group>
diff --git a/java/code/src/com/redhat/rhn/frontend/strings/jsp/StringResource_en_US.xml b/java/code/src/com/redhat/rhn/frontend/strings/jsp/StringResource_en_US.xml
index 30ebc1d..2470475 100644
--- a/java/code/src/com/redhat/rhn/frontend/strings/jsp/StringResource_en_US.xml
+++ b/java/code/src/com/redhat/rhn/frontend/strings/jsp/StringResource_en_US.xml
@@ -5162,7 +5162,19 @@ value for this entitlement.</source>
</context-group>
</trans-unit>
<trans-unit id="packagesearch.jsp.relevant">
-<source>Channels relevant to your systems</source>
+<source>Only channels relevant to your systems</source>
+ <context-group name="ctx">
+ <context context-type="sourcefile">/rhn/channels/software/Search</context>
+ </context-group>
+ </trans-unit>
+ <trans-unit id="packagesearch.jsp.specificchannel">
+<source>Specific channel you have access to</source>
+ <context-group name="ctx">
+ <context context-type="sourcefile">/rhn/channels/software/Search</context>
+ </context-group>
+ </trans-unit>
+ <trans-unit id="packagesearch.jsp.specificarch">
+<source>Packages of a specific architecture in any channel you have access to</source>
<context-group name="ctx">
<context context-type="sourcefile">/rhn/channels/software/Search</context>
</context-group>
diff --git a/java/code/webapp/WEB-INF/pages/channel/packagesearch.jsp b/java/code/webapp/WEB-INF/pages/channel/packagesearch.jsp
index bc1a13f..ed50a22 100644
--- a/java/code/webapp/WEB-INF/pages/channel/packagesearch.jsp
+++ b/java/code/webapp/WEB-INF/pages/channel/packagesearch.jsp
@@ -53,20 +53,34 @@
</tr>
<tr><th><bean:message key="packagesearch.jsp.wheresearch"/></th>
<td rowspan="2">
- <div style="text-align: center">
- <input type="checkbox" name="relevant" value="yes" onclick="javascript:highlander(this);"
- <c:if test="${not empty relevant}">checked="checked"</c:if> />
- <bean:message key="packagesearch.jsp.relevant"/></div>
- <div style="font-weight: bold; text-align: center">-or-</div>
- <div style="text-align: center">
- <html:select property="channel_arch" multiple="multiple" size="5" onclick="javascript:highlander(this);">
- <html:options collection="channelArches"
- property="value"
- labelProperty="display" />
- </html:select><br/>
-
- </div>
- <div style="text-align: center"><bean:message key="packagesearch.jsp.searchwherelegend"/></div>
+
+ <div style="text-align: left;">
+ <input type="radio" name="whereCriteria" value="relevant" <c:if test="${whereCriteria eq 'relevant'}">checked</c:if> /><bean:message key="packagesearch.jsp.relevant"/>
+ </div>
+ <div style="text-align: left;">
+ <input type="radio" name="whereCriteria" value="channel" <c:if test="${whereCriteria eq 'channel'}">checked</c:if> /><bean:message key="packagesearch.jsp.specificchannel"/><br/>
+ <div style="margin-left: 30px; margin-top: 5px;">
+ <html:select property="channel_filter">
+ <html:options collection="allChannels"
+ property="id"
+ labelProperty="name" />
+ </html:select><br/>
+ </div>
+ </div>
+ <div style="text-align: left;">
+ <input type="radio" name="whereCriteria" value="architecture" <c:if test="${whereCriteria eq 'architecture'}">checked</c:if> /><bean:message key="packagesearch.jsp.specificarch"/><br/>
+ <div style="margin-left: 30px; margin-top: 5px;">
+ <html:select property="channel_arch" multiple="multiple"
+ size="5" onclick="javascript:highlander(this);">
+ <html:options collection="channelArches"
+ property="value"
+ labelProperty="display" />
+ </html:select><br/>
+
+ <bean:message key="packagesearch.jsp.searchwherelegend"/>
+ </div>
+ </div>
+
</td>
</tr>
</table>
@@ -118,7 +132,9 @@
<input type="hidden" name="submitted" value="true" />
<input type="hidden" name="search_string" value="${search_string}" />
<input type="hidden" name="view_mode" value="${view_mode}" />
- <input type="hidden" name="relevant" value="${relevant}" />
+ <input type="hidden" name="whereCriteria" value="${whereCriteria}" />
+ <input type="hidden" name="channel_filter" value="${channel_filter}" />
+
<c:forEach items="${requestScope.channel_arch}" var="item">
<input type="hidden" name="channel_arch" value="${item}" />
</c:forEach>
diff --git a/java/code/webapp/WEB-INF/struts-config.xml b/java/code/webapp/WEB-INF/struts-config.xml
index 4b2160a..31c416e 100644
--- a/java/code/webapp/WEB-INF/struts-config.xml
+++ b/java/code/webapp/WEB-INF/struts-config.xml
@@ -255,6 +255,7 @@
<form-property name="search_string" type="java.lang.String"/>
<form-property name="view_mode" type="java.lang.String"/>
<form-property name="channel_arch" type="java.lang.String[]"/>
+ <form-property name="channel_filter" type="java.lang.String"/>
<form-property name="filter_value" type="java.lang.String"/>
<form-property name="prev_filter_value" type="java.lang.String"/>
<form-property name="relevant" type="java.lang.String" />