missing facet resultstags/5.0-RC1
@@ -20,10 +20,7 @@ | |||
package org.sonar.server.issue.index; | |||
import com.google.common.base.Preconditions; | |||
import com.google.common.collect.ArrayListMultimap; | |||
import com.google.common.collect.ImmutableMap; | |||
import com.google.common.collect.ListMultimap; | |||
import com.google.common.collect.Maps; | |||
import com.google.common.collect.*; | |||
import org.apache.commons.lang.BooleanUtils; | |||
import org.elasticsearch.action.search.SearchRequestBuilder; | |||
import org.elasticsearch.action.search.SearchResponse; | |||
@@ -45,6 +42,7 @@ import org.sonar.core.issue.db.IssueDto; | |||
import org.sonar.server.issue.IssueQuery; | |||
import org.sonar.server.issue.filter.IssueFilterParameters; | |||
import org.sonar.server.search.*; | |||
import org.sonar.server.user.UserSession; | |||
import javax.annotation.Nullable; | |||
@@ -384,8 +382,14 @@ public class IssueIndex extends BaseIndex<Issue, IssueDto, String> { | |||
assigneeFilters.remove(fieldName); | |||
StickyFacetBuilder assigneeFacetBuilder = new StickyFacetBuilder(esQuery, assigneeFilters); | |||
BoolFilterBuilder facetFilter = assigneeFacetBuilder.getStickyFacetFilter(fieldName); | |||
FilterAggregationBuilder facetTopAggregation = assigneeFacetBuilder.buildTopFacetAggregation(fieldName, facetName, facetFilter, DEFAULT_ISSUE_FACET_SIZE, 1); | |||
facetTopAggregation = assigneeFacetBuilder.addSelectedItemsToFacet(fieldName, facetName, facetTopAggregation, query.assignees().toArray()); | |||
FilterAggregationBuilder facetTopAggregation = assigneeFacetBuilder.buildTopFacetAggregation(fieldName, facetName, facetFilter, DEFAULT_ISSUE_FACET_SIZE, 0); | |||
List<String> assignees = Lists.newArrayList(query.assignees()); | |||
UserSession session = UserSession.get(); | |||
if (session.isLoggedIn()) { | |||
assignees.add(session.login()); | |||
} | |||
facetTopAggregation = assigneeFacetBuilder.addSelectedItemsToFacet(fieldName, facetName, facetTopAggregation, assignees.toArray()); | |||
// Add missing facet for unassigned issues | |||
facetTopAggregation.subAggregation( |
@@ -20,6 +20,8 @@ | |||
package org.sonar.server.issue.ws; | |||
import com.google.common.collect.ArrayListMultimap; | |||
import com.google.common.collect.Lists; | |||
import com.google.common.collect.Maps; | |||
import com.google.common.collect.Multimap; | |||
import com.google.common.io.Resources; | |||
import org.sonar.api.i18n.I18n; | |||
@@ -284,12 +286,28 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> { | |||
ruleKeys.add(RuleKey.parse(rule.getKey())); | |||
} | |||
} | |||
List<String> rulesFromRequest = request.paramAsStrings(IssueFilterParameters.RULES); | |||
if (rulesFromRequest != null ) { | |||
for (String ruleKey: rulesFromRequest) { | |||
ruleKeys.add(RuleKey.parse(ruleKey)); | |||
} | |||
} | |||
collectFacetKeys(result, IssueFilterParameters.PROJECT_UUIDS, projectUuids); | |||
collectParameterValues(request, IssueFilterParameters.PROJECT_UUIDS, projectUuids); | |||
collectFacetKeys(result, IssueFilterParameters.COMPONENT_UUIDS, componentUuids); | |||
collectParameterValues(request, IssueFilterParameters.COMPONENT_UUIDS, componentUuids); | |||
collectFacetKeys(result, IssueFilterParameters.ASSIGNEES, userLogins); | |||
collectParameterValues(request, IssueFilterParameters.ASSIGNEES, userLogins); | |||
collectFacetKeys(result, IssueFilterParameters.REPORTERS, userLogins); | |||
collectParameterValues(request, IssueFilterParameters.REPORTERS, userLogins); | |||
collectFacetKeys(result, IssueFilterParameters.ACTION_PLANS, actionPlanKeys); | |||
collectParameterValues(request, IssueFilterParameters.ACTION_PLANS, actionPlanKeys); | |||
UserSession userSession = UserSession.get(); | |||
if (userSession.isLoggedIn()) { | |||
userLogins.add(userSession.login()); | |||
} | |||
DbSession session = dbClient.openSession(false); | |||
try { | |||
@@ -336,6 +354,51 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> { | |||
writeLegacyPaging(context, json, result); | |||
} | |||
@Override | |||
protected void writeFacets(Request request, QueryContext context, Result<?> results, JsonWriter json) { | |||
addMandatoryFacetValues(results, IssueFilterParameters.SEVERITIES, Severity.ALL); | |||
addMandatoryFacetValues(results, IssueFilterParameters.STATUSES, Issue.STATUSES); | |||
List<String> resolutions = Lists.newArrayList(""); | |||
resolutions.addAll(Issue.RESOLUTIONS); | |||
addMandatoryFacetValues(results, IssueFilterParameters.RESOLUTIONS, resolutions); | |||
addMandatoryFacetValues(results, IssueFilterParameters.PROJECT_UUIDS, request.paramAsStrings(IssueFilterParameters.PROJECT_UUIDS)); | |||
List<String> assigneesFromRequest = request.paramAsStrings(IssueFilterParameters.ASSIGNEES); | |||
if (assigneesFromRequest == null) { | |||
assigneesFromRequest = Lists.newArrayList(); | |||
} | |||
UserSession userSession = UserSession.get(); | |||
if (userSession.isLoggedIn()) { | |||
assigneesFromRequest.add(userSession.login()); | |||
} | |||
addMandatoryFacetValues(results, IssueFilterParameters.ASSIGNEES, assigneesFromRequest); | |||
addMandatoryFacetValues(results, IssueFilterParameters.REPORTERS, request.paramAsStrings(IssueFilterParameters.REPORTERS)); | |||
addMandatoryFacetValues(results, IssueFilterParameters.RULES, request.paramAsStrings(IssueFilterParameters.RULES)); | |||
addMandatoryFacetValues(results, IssueFilterParameters.LANGUAGES, request.paramAsStrings(IssueFilterParameters.LANGUAGES)); | |||
addMandatoryFacetValues(results, IssueFilterParameters.ACTION_PLANS, request.paramAsStrings(IssueFilterParameters.ACTION_PLANS)); | |||
addMandatoryFacetValues(results, IssueFilterParameters.COMPONENT_UUIDS, request.paramAsStrings(IssueFilterParameters.COMPONENT_UUIDS)); | |||
super.writeFacets(request, context, results, json); | |||
} | |||
private void addMandatoryFacetValues(Result<?> results, String facetName, @Nullable List<String> mandatoryValues) { | |||
Collection<FacetValue> facetValues = results.getFacetValues(facetName); | |||
if (facetValues != null) { | |||
Map<String, Long> valuesByItem = Maps.newHashMap(); | |||
for (FacetValue value: facetValues) { | |||
valuesByItem.put(value.getKey(), value.getValue()); | |||
} | |||
if (mandatoryValues == null) { | |||
mandatoryValues = Lists.newArrayList(); | |||
} | |||
for (String item: mandatoryValues) { | |||
if (!valuesByItem.containsKey(item)) { | |||
facetValues.add(new FacetValue(item, 0)); | |||
} | |||
} | |||
} | |||
} | |||
private void collectFacetKeys(Result<Issue> result, String facetName, Collection<String> facetKeys) { | |||
Collection<FacetValue> facetValues = result.getFacetValues(facetName); | |||
if (facetValues != null) { | |||
@@ -345,6 +408,13 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> { | |||
} | |||
} | |||
private void collectParameterValues(Request request, String facetName, Collection<String> facetKeys) { | |||
Collection<String> paramValues = request.paramAsStrings(facetName); | |||
if (paramValues != null) { | |||
facetKeys.addAll(paramValues); | |||
} | |||
} | |||
private void writeLegacyPaging(QueryContext context, JsonWriter json, Result<?> result) { | |||
// TODO remove with stas on HTML side | |||
json.prop("maxResultsReached", false); |
@@ -100,7 +100,8 @@ public class StickyFacetBuilder { | |||
facetTopAggregation.subAggregation( | |||
AggregationBuilders.terms(facetName + "_selected") | |||
.field(fieldName) | |||
.include(Joiner.on('|').join(selected))); | |||
.include(Joiner.on('|').join(selected)) | |||
.minDocCount(0)); | |||
} | |||
return facetTopAggregation; | |||
} |
@@ -19,6 +19,7 @@ | |||
*/ | |||
package org.sonar.server.search.ws; | |||
import com.google.common.collect.Sets; | |||
import org.sonar.api.server.ws.Request; | |||
import org.sonar.api.server.ws.RequestHandler; | |||
import org.sonar.api.server.ws.Response; | |||
@@ -33,6 +34,7 @@ import javax.annotation.CheckForNull; | |||
import java.util.Collection; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.Set; | |||
public abstract class SearchRequestHandler<QUERY, DOMAIN> implements RequestHandler { | |||
@@ -113,7 +115,7 @@ public abstract class SearchRequestHandler<QUERY, DOMAIN> implements RequestHand | |||
this.writeStatistics(json, result, context); | |||
doContextResponse(request, context, result, json); | |||
if (context.isFacet()) { | |||
writeFacets(context, result, json); | |||
writeFacets(request, context, result, json); | |||
} | |||
json.endObject().close(); | |||
} | |||
@@ -139,19 +141,32 @@ public abstract class SearchRequestHandler<QUERY, DOMAIN> implements RequestHand | |||
json.prop(PARAM_PAGE_SIZE, context.getLimit()); | |||
} | |||
protected void writeFacets(QueryContext context, Result<?> results, JsonWriter json) { | |||
protected void writeFacets(Request request, QueryContext context, Result<?> results, JsonWriter json) { | |||
json.name("facets").beginArray(); | |||
for (String facetName: context.facets()) { | |||
json.beginObject(); | |||
json.prop("property", facetName); | |||
json.name("values").beginArray(); | |||
if (results.getFacets().containsKey(facetName)) { | |||
Set<String> itemsFromFacets = Sets.newHashSet(); | |||
for (FacetValue facetValue : results.getFacets().get(facetName)) { | |||
itemsFromFacets.add(facetValue.getKey()); | |||
json.beginObject(); | |||
json.prop("val", facetValue.getKey()); | |||
json.prop("count", facetValue.getValue()); | |||
json.endObject(); | |||
} | |||
List<String> requestParams = request.paramAsStrings(facetName); | |||
if (requestParams != null) { | |||
for (String param: requestParams) { | |||
if (!itemsFromFacets.contains(param)) { | |||
json.beginObject(); | |||
json.prop("val", param); | |||
json.prop("count", 0); | |||
json.endObject(); | |||
} | |||
} | |||
} | |||
} | |||
json.endArray().endObject(); | |||
} |
@@ -18,15 +18,47 @@ | |||
{ | |||
"val": "OPEN", | |||
"count": 1 | |||
}, | |||
{ | |||
"val": "CONFIRMED", | |||
"count": 0 | |||
}, | |||
{ | |||
"val": "REOPENED", | |||
"count": 0 | |||
}, | |||
{ | |||
"val": "RESOLVED", | |||
"count": 0 | |||
}, | |||
{ | |||
"val": "CLOSED", | |||
"count": 0 | |||
} | |||
] | |||
}, | |||
{ | |||
"property": "severities", | |||
"values": [ | |||
{ | |||
"val": "INFO", | |||
"count": 0 | |||
}, | |||
{ | |||
"val": "MINOR", | |||
"count": 0 | |||
}, | |||
{ | |||
"val": "MAJOR", | |||
"count": 1 | |||
}, | |||
{ | |||
"val": "CRITICAL", | |||
"count": 0 | |||
}, | |||
{ | |||
"val": "BLOCKER", | |||
"count": 0 | |||
} | |||
] | |||
}, | |||
@@ -36,6 +68,18 @@ | |||
{ | |||
"val": "", | |||
"count": 1 | |||
}, | |||
{ | |||
"val": "FALSE-POSITIVE", | |||
"count": 0 | |||
}, | |||
{ | |||
"val": "FIXED", | |||
"count": 0 | |||
}, | |||
{ | |||
"val": "REMOVED", | |||
"count": 0 | |||
} | |||
] | |||
}, | |||
@@ -72,6 +116,10 @@ | |||
{ | |||
"val": "", | |||
"count": 1 | |||
}, | |||
{ | |||
"val": "john", | |||
"count": 0 | |||
} | |||
] | |||
}, |
@@ -59,6 +59,12 @@ | |||
"name": "Fabrice", | |||
"active": true, | |||
"email": "fabrice@email.com" | |||
}, | |||
{ | |||
"login": "john", | |||
"name": "John", | |||
"active": true, | |||
"email": "john@email.com" | |||
} | |||
] | |||
} |