| /******************************************************************************* |
| * Copyright (c) 2000, 2015 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * Sebastian Davids <sdavids@gmx.de> - fix for Bug 182466 |
| * Holger Voormann - fix for bug 365549 (http://eclip.se/365549) |
| *******************************************************************************/ |
| package org.eclipse.help.internal.webapp.data; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import javax.servlet.ServletContext; |
| import javax.servlet.http.Cookie; |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletResponse; |
| |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.help.HelpSystem; |
| import org.eclipse.help.IHelpResource; |
| import org.eclipse.help.IToc; |
| import org.eclipse.help.ITopic; |
| import org.eclipse.help.base.AbstractHelpScope; |
| import org.eclipse.help.internal.HelpPlugin; |
| import org.eclipse.help.internal.base.BaseHelpSystem; |
| import org.eclipse.help.internal.base.HelpBasePlugin; |
| import org.eclipse.help.internal.base.IHelpBaseConstants; |
| import org.eclipse.help.internal.search.ISearchQuery; |
| import org.eclipse.help.internal.search.QueryTooComplexException; |
| import org.eclipse.help.internal.search.SearchHit; |
| import org.eclipse.help.internal.search.SearchManager; |
| import org.eclipse.help.internal.search.SearchProgressMonitor; |
| import org.eclipse.help.internal.search.SearchQuery; |
| import org.eclipse.help.internal.search.SearchResults; |
| import org.eclipse.help.internal.webapp.HelpWebappPlugin; |
| import org.eclipse.help.internal.webapp.servlet.WebappWorkingSetManager; |
| import org.eclipse.help.internal.workingset.AdaptableHelpResource; |
| import org.eclipse.help.internal.workingset.AdaptableSelectedToc; |
| import org.eclipse.help.internal.workingset.AdaptableSelectedTopic; |
| import org.eclipse.help.internal.workingset.AdaptableToc; |
| import org.eclipse.help.internal.workingset.AdaptableTopic; |
| import org.eclipse.help.internal.workingset.WorkingSet; |
| import org.eclipse.help.search.AbstractSearchProcessor; |
| import org.eclipse.help.search.ISearchEngineResult; |
| import org.eclipse.help.search.ISearchResult; |
| import org.eclipse.help.search.SearchProcessorInfo; |
| import org.eclipse.osgi.util.NLS; |
| |
| /** |
| * Helper class for searchView.jsp initialization |
| */ |
| public class SearchData extends ActivitiesData { |
| private static final String SHOW_CATEGORIES = "showSearchCategories"; //$NON-NLS-1$ |
| |
| private WebappWorkingSetManager wsmgr; |
| |
| // Request parameters |
| private String topicHref; |
| |
| private String selectedTopicId = ""; //$NON-NLS-1$ |
| |
| private String searchWord; |
| |
| private String workingSetName; |
| |
| // search results |
| SearchHit[] hits; |
| |
| // percentage of indexing completion |
| private int indexCompletion = 100; |
| |
| // QueryException if any |
| private QueryTooComplexException queryException = null; |
| |
| // List of alternate search terms |
| private List<String> altList = new ArrayList<String>(); |
| |
| private boolean showCategories = false; |
| |
| /** |
| * Constructs the xml data for the search results page. |
| * |
| * @param context |
| * @param request |
| */ |
| public SearchData(ServletContext context, HttpServletRequest request, |
| HttpServletResponse response) { |
| super(context, request, response); |
| wsmgr = new WebappWorkingSetManager(request, response, getLocale()); |
| this.topicHref = request.getParameter("topic"); //$NON-NLS-1$ |
| if (topicHref != null && topicHref.length() == 0) |
| topicHref = null; |
| |
| searchWord = request.getParameter("searchWord"); //$NON-NLS-1$ |
| readDisplayFlags(request, response); |
| |
| if (isScopeRequest()) { |
| workingSetName = request.getParameter("workingSet"); //$NON-NLS-1$ |
| if ( canSaveScope() ) { |
| saveWorkingSet(workingSetName); |
| } |
| } |
| |
| // try loading search results or get the indexing progress info. |
| readSearchResults(); |
| } |
| |
| protected boolean canSaveScope() { |
| // Scope is only saved from scopeState.jsp |
| // This prevents cookies from being saved with a /advanced path |
| return false; |
| } |
| |
| private void readDisplayFlags(HttpServletRequest request, HttpServletResponse response) { |
| String showCategoriesParam = request.getParameter(SHOW_CATEGORIES); |
| if (showCategoriesParam != null) { |
| showCategories = "true".equalsIgnoreCase(showCategoriesParam); //$NON-NLS-1$ |
| RequestScope.setFlag(request, response, SHOW_CATEGORIES, showCategories); |
| } else { |
| showCategories = RequestScope.getFlag(request, SHOW_CATEGORIES); |
| } |
| } |
| |
| public void readSearchResults() { |
| |
| // try loading search results or get the indexing progress info. |
| if (isSearchRequest() && !isScopeRequest()) { |
| |
| altList.clear(); |
| |
| AbstractSearchProcessor processors[] = SearchManager.getSearchProcessors(); |
| for (AbstractSearchProcessor processor : processors) { |
| SearchProcessorInfo result = |
| processor.preSearch(searchWord); |
| if (result!=null) |
| { |
| String alternates[] = result.getAlternateTerms(); |
| if (alternates!=null) |
| { |
| for (String alternate : alternates) { |
| String div = |
| "<div><a target=\"_self\" href=\"./searchView.jsp?searchWord="+alternate+"\">"+ //$NON-NLS-1$ //$NON-NLS-2$ |
| alternate+ |
| "</a></div>"; //$NON-NLS-1$ |
| |
| if (!altList.contains(div)) |
| altList.add(div); |
| } |
| } |
| String query = result.getQuery(); |
| if (query!=null) |
| searchWord = query; |
| } |
| } |
| Collections.sort(altList); |
| |
| loadSearchResults(); |
| if (queryException != null) { |
| return; |
| } |
| if (!isProgressRequest()) { |
| for (int i = 0; i < hits.length; i++) { |
| // the following assume topic numbering as in searchView.jsp |
| if (hits[i].getHref().equals(topicHref)) { |
| selectedTopicId = "a" + i; //$NON-NLS-1$ |
| break; |
| } |
| } |
| |
| ISearchResult results[] = SearchManager.convertHitsToResults(hits); |
| boolean reset= false; |
| for (AbstractSearchProcessor processor : processors) { |
| ISearchResult tmp[] = processor.postSearch(searchWord,results); |
| if (tmp!=null) |
| { |
| reset = true; |
| results = tmp; |
| } |
| } |
| if (reset) |
| hits = SearchManager.convertResultsToHits(results); |
| if (isShowCategories()) |
| primallySortByCategory(hits); |
| } |
| } |
| } |
| |
| /** |
| * Returns true when there is a search request |
| * |
| * @return boolean |
| */ |
| public boolean isSearchRequest() { |
| String searchWordParam = request.getParameter("searchWord"); //$NON-NLS-1$ |
| return (searchWordParam != null && searchWordParam.length() > 0); |
| } |
| |
| /** |
| * Return indexed completion percentage |
| */ |
| public boolean isProgressRequest() { |
| return (hits == null && indexCompletion != 100); |
| } |
| |
| /** |
| * Returns true when there is a request to change the scope (working set) |
| */ |
| public boolean isScopeRequest() { |
| return (request.getParameter("workingSet") != null); //$NON-NLS-1$ |
| } |
| |
| protected boolean isQuickSearch() { |
| return request.getParameterValues("quickSearch") != null; //$NON-NLS-1$ |
| } |
| |
| public boolean isSelectedTopicQuickSearchRequest() { |
| String quickSearchType = request.getParameter("quickSearchType"); //$NON-NLS-1$ |
| return (null != quickSearchType && "QuickSearchTopic".equalsIgnoreCase(quickSearchType)); //$NON-NLS-1$ |
| } |
| |
| public String getCategoryLabel(int i) { |
| IHelpResource cat = hits[i].getCategory(); |
| if (cat != null) { |
| return cat.getLabel(); |
| } |
| return null; |
| } |
| |
| public String getCategoryHref(int i) { |
| IHelpResource cat = hits[i].getCategory(); |
| if (cat != null) { |
| String tocHref = cat.getHref(); |
| IToc[] tocs = HelpSystem.getTocs(); |
| for (int j=0;j<tocs.length;++j) { |
| if (tocHref.equals(tocs[j].getHref())) { |
| ITopic topic = tocs[j].getTopic(null); |
| String topicHref = topic.getHref(); |
| if (topicHref != null) { |
| return UrlUtil.getHelpURL(topicHref); |
| } |
| return "../nav/" + j; //$NON-NLS-1$ |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Return the number of links |
| * |
| * @return int |
| */ |
| public int getResultsCount() { |
| return hits.length; |
| } |
| |
| public SearchHit[] getResults() { |
| return hits; |
| } |
| |
| public String getSelectedTopicId() { |
| return selectedTopicId; |
| } |
| |
| public String getTopicHref(int i) { |
| return UrlUtil.getHelpURL(hits[i].getHref()); |
| } |
| |
| public String getTopicLabel(int i) { |
| return UrlUtil.htmlEncode(hits[i].getLabel()); |
| } |
| |
| public String getTopicTocLabel(int i) { |
| if (hits[i].getToc() != null) |
| return UrlUtil.htmlEncode(hits[i].getToc().getLabel()); |
| return ""; //$NON-NLS-1$ |
| } |
| |
| public String getTopicDescription(int i) { |
| String description = hits[i].getDescription(); |
| if (description != null) { |
| return UrlUtil.htmlEncode(description); |
| } |
| return ""; //$NON-NLS-1$ |
| } |
| |
| /** |
| * @param i |
| * @return true of result belong to an enabled TOC |
| */ |
| public boolean isEnabled(int i) { |
| String href = hits[i].getHref(); |
| return HelpBasePlugin.getActivitySupport().isEnabledTopic(href, |
| getLocale()); |
| } |
| |
| /** |
| * Returns whether or not the ith hit is a potential hit. This means |
| * it may not be an actual hit (i.e. it found something in a filtered |
| * section of the document). |
| * |
| * @param i the index of the hit to check |
| * @return whether or not the hit is a potential hit |
| */ |
| public boolean isPotentialHit(int i) { |
| return ((getMode() != MODE_INFOCENTER) && hits[i].isPotentialHit()); |
| } |
| |
| public boolean isShowCategories() { |
| return showCategories; |
| } |
| |
| public boolean isShowDescriptions() { |
| Cookie[] cookies = request.getCookies(); |
| if (cookies != null) { |
| for (Cookie cookie : cookies) { |
| if ("showDescriptions".equals(cookie.getName())) { //$NON-NLS-1$ |
| return String.valueOf(true).equals(cookie.getValue()); |
| } |
| } |
| } |
| // get default from preferences |
| return Platform.getPreferencesService().getBoolean |
| (HelpBasePlugin.PLUGIN_ID, IHelpBaseConstants.P_KEY_SHOW_SEARCH_DESCRIPTION, true, null); |
| } |
| |
| /** |
| * Return indexed completion percentage |
| */ |
| public String getIndexedPercentage() { |
| return String.valueOf(indexCompletion); |
| } |
| |
| /** |
| * Returns the search query |
| */ |
| public String getSearchWord() { |
| if (searchWord == null) |
| return ""; //$NON-NLS-1$ |
| return searchWord; |
| } |
| |
| /** |
| * Returns the list of selected TOC's |
| */ |
| public String[] getSelectedTocs() { |
| String[] books = request.getParameterValues("scope"); //$NON-NLS-1$ |
| if (books == null) { |
| // select all books |
| TocData tocData = new TocData(context, request, response); |
| books = new String[tocData.getTocCount()]; |
| for (int i = 0; i < books.length; i++) |
| books[i] = tocData.getTocHref(i); |
| } |
| return books; |
| } |
| |
| /** |
| * Returns true if book is within a search scope |
| */ |
| public boolean isTocSelected(int toc) { |
| TocData tocData = new TocData(context, request, response); |
| String href = tocData.getTocHref(toc); |
| String[] books = request.getParameterValues("scope"); //$NON-NLS-1$ |
| if (books == null) |
| return false; |
| for (String book : books) { |
| if (book.equals(href)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Returns the working set selected. This is used to display the working set |
| * name in the search banner. |
| * |
| * @return String |
| */ |
| public String getScope() { |
| if (workingSetName != null && workingSetName.length() != 0) |
| return workingSetName; |
| |
| if (isSearchRequest()) { |
| workingSetName = request.getParameter("scope"); //$NON-NLS-1$ |
| // if we have already set the working set, then use it. |
| if (workingSetName == null) { |
| workingSetName = request.getParameter("workingSet"); //$NON-NLS-1$ |
| } |
| } else { |
| workingSetName = wsmgr.getCurrentWorkingSet(); |
| } |
| |
| if (workingSetName == null || workingSetName.length() == 0 |
| || getMode() == RequestData.MODE_INFOCENTER |
| && wsmgr.getWorkingSet(workingSetName) == null) |
| workingSetName = ServletResources.getString("All", request); //$NON-NLS-1$ |
| return workingSetName; |
| } |
| |
| private void saveWorkingSet(String workingSet) { |
| String lastWS = wsmgr.getCurrentWorkingSet(); |
| if (workingSet != null && !workingSet.equals(lastWS)) { |
| wsmgr.setCurrentWorkingSet(workingSet); |
| } else if (workingSet == null && lastWS != null && lastWS.length() > 0) { |
| wsmgr.setCurrentWorkingSet(""); //$NON-NLS-1$ |
| } |
| } |
| |
| /** |
| * Call the search engine, and get results or the percentage of indexed |
| * documents. |
| */ |
| private void loadSearchResults() { |
| try { |
| SearchProgressMonitor pm = SearchProgressMonitor |
| .getProgressMonitor(getLocale()); |
| if (pm.isDone()) { |
| this.indexCompletion = 100; |
| SearchResults results = createHitCollector(); |
| BaseHelpSystem.getSearchManager().search(createSearchQuery(), |
| results, pm); |
| hits = results.getSearchHits(); |
| if (hits == null) { |
| HelpWebappPlugin |
| .logWarning("No search results returned. Help index is in use."); //$NON-NLS-1$ |
| } |
| return; |
| } |
| // progress |
| indexCompletion = pm.getPercentage(); |
| if (indexCompletion >= 100) { |
| // 38573 We do not have results, so index cannot be 100 |
| indexCompletion = 100 - 1; |
| } |
| return; |
| } catch (QueryTooComplexException qe) { |
| queryException = qe; |
| } catch (Exception e) { |
| this.indexCompletion = 0; |
| } |
| |
| } |
| |
| private ISearchQuery createSearchQuery() { |
| String fieldSearchStr = request.getParameter("fieldSearch"); //$NON-NLS-1$ |
| boolean fieldSearch = fieldSearchStr != null ? new Boolean( |
| fieldSearchStr).booleanValue() : false; |
| return new SearchQuery(searchWord == null ? "" : searchWord, fieldSearch, new ArrayList<String>(), //$NON-NLS-1$ |
| getLocale()); |
| } |
| |
| private SearchResults createHitCollector() { |
| WorkingSet[] workingSets; |
| boolean isSearchSelectedAndChildren = false; |
| if (request.getParameterValues("scopedSearch") != null) { //$NON-NLS-1$ |
| // scopes are books (advanced search) |
| workingSets = createTempWorkingSets(); |
| } else if (isQuickSearch()) { |
| // scopes is just the selected toc or topic |
| if(isSelectedTopicQuickSearchRequest()){ |
| workingSets = createQuickSearchWorkingSetOnSelectedTopic(); |
| } else{ // scopes is a toc or topic and its children |
| workingSets = createQuickSearchWorkingSet(); |
| isSearchSelectedAndChildren = true; |
| } |
| } else { |
| // scopes are working set names |
| workingSets = getWorkingSets(); |
| } |
| |
| AbstractHelpScope filter = RequestScope.getScope(request, response, !isSearchSelectedAndChildren); |
| int maxHits = 500; |
| String maxHitsStr = request.getParameter("maxHits"); //$NON-NLS-1$ |
| if (maxHitsStr != null) { |
| try { |
| int clientmaxHits = Integer.parseInt(maxHitsStr); |
| if (0 < clientmaxHits && clientmaxHits < 500) { |
| maxHits = clientmaxHits; |
| } |
| } catch (NumberFormatException nfe) { |
| } |
| } |
| return new SearchResultFilter(workingSets, maxHits, getLocale(), filter, isQuickSearch()); |
| } |
| |
| /** |
| * @return WorkingSet[] or null |
| */ |
| private WorkingSet[] getWorkingSets() { |
| String[] scopes = request.getParameterValues("scope"); //$NON-NLS-1$ |
| if (scopes == null) { |
| return null; |
| } |
| // confirm working set exists and use it |
| ArrayList<WorkingSet> workingSetCol = new ArrayList<WorkingSet>(scopes.length); |
| for (String scope : scopes) { |
| WorkingSet ws = wsmgr.getWorkingSet(scope); |
| if (ws != null) { |
| workingSetCol.add(ws); |
| } |
| } |
| if (workingSetCol.size() == 0) { |
| return null; |
| } |
| return workingSetCol |
| .toArray(new WorkingSet[workingSetCol.size()]); |
| } |
| |
| /** |
| * @return WorkingSet[] or null |
| */ |
| private WorkingSet[] createTempWorkingSets() { |
| String[] scopes = request.getParameterValues("scope"); //$NON-NLS-1$ |
| if (scopes == null) { |
| // it is possible that filtering is used, but all books are |
| // deselected |
| return new WorkingSet[0]; |
| } |
| if (scopes.length == HelpPlugin.getTocManager().getTocs(getLocale()).length) { |
| // do not filter if all books are selected |
| return null; |
| } |
| // create working set from books |
| ArrayList<AdaptableToc> tocs = new ArrayList<AdaptableToc>(scopes.length); |
| for (String scope : scopes) { |
| AdaptableToc toc = wsmgr.getAdaptableToc(scope); |
| if (toc != null) { |
| tocs.add(toc); |
| } |
| } |
| AdaptableToc[] adaptableTocs = tocs |
| .toArray(new AdaptableToc[tocs.size()]); |
| WorkingSet[] workingSets = new WorkingSet[1]; |
| workingSets[0] = wsmgr.createWorkingSet("temp", adaptableTocs); //$NON-NLS-1$ |
| return workingSets; |
| } |
| |
| /** |
| * @return WorkingSet[] consisting of a single toc or topic or null |
| */ |
| private WorkingSet[] createQuickSearchWorkingSet() { |
| WorkingSet[] workingSets = new WorkingSet[1]; |
| TocData tocData = new TocData(context, request, response); |
| int selectedToc = tocData.getSelectedToc(); |
| if (selectedToc < 0) { |
| return new WorkingSet[0]; |
| } |
| IToc toc = tocData.getTocs()[selectedToc]; |
| ITopic[] topics = tocData.getTopicPathFromRootPath(toc); |
| List<AdaptableHelpResource> resources = new ArrayList<AdaptableHelpResource>(); |
| AdaptableToc adaptableToc = new AdaptableToc(toc); |
| if (topics != null) { |
| ITopic selectedTopic = topics[topics.length - 1]; |
| AdaptableTopic adaptableTopic = new AdaptableTopic(selectedTopic); |
| resources.add(adaptableTopic); |
| adaptableTopic.setParent(adaptableToc); |
| } else { |
| resources.add(adaptableToc); |
| } |
| workingSets[0] = new WorkingSet("quickSearch", resources); //$NON-NLS-1$ |
| return workingSets; |
| } |
| |
| /** |
| * @return WorkingSet[] consisting of a single selected toc or topic or null |
| */ |
| private WorkingSet[] createQuickSearchWorkingSetOnSelectedTopic() { |
| WorkingSet[] workingSets = new WorkingSet[1]; |
| TocData tocData = new TocData(context, request, response); |
| int selectedToc = tocData.getSelectedToc(); |
| if (selectedToc < 0) { |
| return new WorkingSet[0]; |
| } |
| IToc toc = tocData.getTocs()[selectedToc]; |
| ITopic[] topics = tocData.getTopicPathFromRootPath(toc); |
| List<AdaptableHelpResource> resources = new ArrayList<AdaptableHelpResource>(); |
| AdaptableSelectedToc adaptableSelectedToc = new AdaptableSelectedToc(toc); |
| if (topics != null) { |
| ITopic selectedTopic = topics[topics.length - 1]; |
| AdaptableSelectedTopic adaptableSelectedTopic = new AdaptableSelectedTopic(selectedTopic); |
| resources.add(adaptableSelectedTopic); |
| adaptableSelectedTopic.setParent(adaptableSelectedToc); |
| } else { |
| resources.add(adaptableSelectedToc); |
| } |
| workingSets[0] = new WorkingSet("quickSearch", resources); //$NON-NLS-1$ |
| return workingSets; |
| } |
| |
| public String getQueryExceptionMessage() { |
| if (queryException == null) { |
| return null; |
| } |
| return ServletResources.getString("searchTooComplex", request); //$NON-NLS-1$ |
| } |
| |
| public boolean isScopeActive() { |
| return ! getScope().equals(ServletResources.getString("All", request)); //$NON-NLS-1$ |
| } |
| |
| public String getNotFoundMessage() { |
| String scope = getScope(); |
| if (scope.equals(ServletResources.getString("All", request))) { //$NON-NLS-1$ |
| return ServletResources.getString("Nothing_found", request); //$NON-NLS-1$ |
| } else { |
| return NLS.bind(ServletResources.getString("Nothing_found_in_scope", request), scope); //$NON-NLS-1$ |
| } |
| } |
| |
| public String getScopeActiveMessage() { |
| String scope = getScope(); |
| return NLS.bind(ServletResources.getString("activeScope", request), scope); //$NON-NLS-1$ |
| } |
| |
| public String getMatchesInScopeMessage() { |
| String scope = getScope(); |
| return NLS.bind(ServletResources.getString("matchesInScope", request), "" + getResultsCount(), scope); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| public String getPreProcessorResults() |
| { |
| if (altList==null || altList.isEmpty()) |
| return ""; //$NON-NLS-1$ |
| |
| StringBuffer result = new StringBuffer(); |
| |
| result.append(ServletResources.getString("AlternateSearchQueries", request)); //$NON-NLS-1$ |
| result.append("<ul>"); //$NON-NLS-1$ |
| for (int a=0;a<altList.size();a++) |
| result.append("<li>"+altList.get(a)+"</li>"); //$NON-NLS-1$ //$NON-NLS-2$ |
| result.append("</ul>"); //$NON-NLS-1$ |
| |
| return result.toString(); |
| } |
| |
| /* |
| * Filters out results that help doesn't know how to open (i.e. those hits |
| * that implement ISearchEngineResult2 and canOpen() returns true. |
| */ |
| private static class SearchResultFilter extends SearchResults { |
| public SearchResultFilter(WorkingSet[] workingSets, int maxHits, String locale, |
| AbstractHelpScope filter, boolean isQuickSearch) { |
| super(workingSets, maxHits, locale, isQuickSearch); |
| setFilter(filter); |
| } |
| @Override |
| public void addHits(List<SearchHit> hits, String highlightTerms) { |
| List<SearchHit> filtered = new ArrayList<SearchHit>(); |
| Iterator<SearchHit> iter = hits.iterator(); |
| while (iter.hasNext()) { |
| SearchHit obj = iter.next(); |
| if (!(obj != null && obj.canOpen())) { |
| filtered.add(obj); |
| } |
| } |
| super.addHits(filtered, highlightTerms); |
| } |
| } |
| |
| /** |
| * Sorts the given {@link ISearchEngineResult} array alphabetically (case |
| * insensitive) by category label but keeps the order within each category. |
| * Results without a category or of a category without a label or with an |
| * empty label are sorted to the end ({@code "Category Label" < "" < null}). |
| * |
| * @param toSort the {@link ISearchEngineResult} array to sort; must not |
| * contain {@code null} elements |
| */ |
| private static void primallySortByCategory(ISearchEngineResult[] toSort) { |
| Arrays.sort(toSort, new Comparator<ISearchEngineResult>() { |
| @Override |
| public int compare(ISearchEngineResult c1, ISearchEngineResult c2) { |
| if (c1 == null && c2 == null) return 0; |
| if (c1 == null) return 1; |
| if (c2 == null) return -1; |
| String l1 = c1.getLabel(); |
| String l2 = c2.getLabel(); |
| if (l1 == null && l2 == null) return 0; |
| if (l1 == null) return 1; |
| if (l2 == null) return -1; |
| if (l1.length() == 0 && l2.length() == 0) return 0; |
| if (l1.length() == 0) return 1; |
| if (l2.length() == 0) return -1; |
| return l1.compareToIgnoreCase(l2); |
| } |
| }); |
| } |
| |
| } |