From 4764a458a39a37dfc8946c2039f9acf8af3f67da Mon Sep 17 00:00:00 2001 From: Gethin James Date: Fri, 24 Mar 2017 13:18:03 +0000 Subject: [PATCH] Merged searchbcr (5.2.1) to 5.2.N (5.2.1) 135972 gjames: SEARCH-339: Changed facet intervals to use the generic facets metric git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/DEV/5.2.N/root@136098 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../api/search/context/SearchContext.java | 11 +-- .../context/facetsresponse/GenericBucket.java | 69 +++++++++++++++++++ .../facetsresponse/GenericFacetResponse.java | 62 +++++++++++++++++ .../search/context/facetsresponse/Metric.java | 39 +++++++++++ .../context/facetsresponse/MetricCount.java | 54 +++++++++++++++ .../rest/api/search/impl/ResultMapper.java | 55 +++++++++------ .../rest/api/search/ResultMapperTests.java | 21 ++++-- .../search/SearchQuerySerializerTests.java | 4 +- 8 files changed, 279 insertions(+), 36 deletions(-) create mode 100644 source/java/org/alfresco/rest/api/search/context/facetsresponse/GenericBucket.java create mode 100644 source/java/org/alfresco/rest/api/search/context/facetsresponse/GenericFacetResponse.java create mode 100644 source/java/org/alfresco/rest/api/search/context/facetsresponse/Metric.java create mode 100644 source/java/org/alfresco/rest/api/search/context/facetsresponse/MetricCount.java diff --git a/source/java/org/alfresco/rest/api/search/context/SearchContext.java b/source/java/org/alfresco/rest/api/search/context/SearchContext.java index 8ea90f8dbf..a985a8804d 100644 --- a/source/java/org/alfresco/rest/api/search/context/SearchContext.java +++ b/source/java/org/alfresco/rest/api/search/context/SearchContext.java @@ -25,6 +25,7 @@ */ package org.alfresco.rest.api.search.context; +import org.alfresco.rest.api.search.context.facetsresponse.GenericFacetResponse; import org.alfresco.rest.api.search.model.SearchQuery; import java.util.List; @@ -38,10 +39,10 @@ public class SearchContext private final List facetQueries; private final SpellCheckContext spellCheck; private final List facetsFields; - private final List facetIntervals; + private final List facets; private final SearchQuery request; - public SearchContext(long lastTxId, List facetQueries, List facetsFields, List facetIntervals, SpellCheckContext spellCheck, + public SearchContext(long lastTxId, List facets, List facetQueries, List facetsFields, SpellCheckContext spellCheck, SearchQuery request) { this.spellCheck = spellCheck; @@ -56,7 +57,7 @@ public class SearchContext } this.facetQueries = facetQueries; this.facetsFields = facetsFields; - this.facetIntervals = facetIntervals; + this.facets = facets; } public Consistency getConsistency() @@ -74,9 +75,9 @@ public class SearchContext return spellCheck; } - public List getFacetIntervals() + public List getFacets() { - return facetIntervals; + return facets; } public List getFacetsFields() diff --git a/source/java/org/alfresco/rest/api/search/context/facetsresponse/GenericBucket.java b/source/java/org/alfresco/rest/api/search/context/facetsresponse/GenericBucket.java new file mode 100644 index 0000000000..e0806b11af --- /dev/null +++ b/source/java/org/alfresco/rest/api/search/context/facetsresponse/GenericBucket.java @@ -0,0 +1,69 @@ +/*- + * #%L + * Alfresco Remote API + * %% + * Copyright (C) 2005 - 2017 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.rest.api.search.context.facetsresponse; + +import java.util.List; + +/** + * A Generic Bucket response covering range, interval, pivot etc. + */ +public class GenericBucket +{ + private final String label; + private final String filterQuery; + private final Object display; + private final List metrics; + + public GenericBucket(String label, String filterQuery, Object display, List metrics) + { + this.label = label; + this.filterQuery = filterQuery; + this.display = display; + this.metrics = metrics; + } + + public String getFilterQuery() + { + return filterQuery; + } + + public Object getDisplay() + { + return display; + } + + public String getLabel() + { + return label; + } + + public List getMetrics() + { + return metrics; + } + + +} diff --git a/source/java/org/alfresco/rest/api/search/context/facetsresponse/GenericFacetResponse.java b/source/java/org/alfresco/rest/api/search/context/facetsresponse/GenericFacetResponse.java new file mode 100644 index 0000000000..caa81aef3b --- /dev/null +++ b/source/java/org/alfresco/rest/api/search/context/facetsresponse/GenericFacetResponse.java @@ -0,0 +1,62 @@ +/*- + * #%L + * Alfresco Remote API + * %% + * Copyright (C) 2005 - 2017 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.rest.api.search.context.facetsresponse; + +import java.util.List; + +/** + * A Generic facet response covering range, interval, pivot etc. + */ +public class GenericFacetResponse +{ + public static enum FACET_TYPE {range, interval}; + private final FACET_TYPE type; + private final String label; + private final List buckets; + + public GenericFacetResponse(FACET_TYPE type, String label, List buckets) + { + this.type = type; + this.label = label; + this.buckets = buckets; + } + + public String getLabel() + { + return label; + } + + public List getBuckets() + { + return buckets; + } + + public FACET_TYPE getType() + { + return type; + } + +} diff --git a/source/java/org/alfresco/rest/api/search/context/facetsresponse/Metric.java b/source/java/org/alfresco/rest/api/search/context/facetsresponse/Metric.java new file mode 100644 index 0000000000..c864d9fd33 --- /dev/null +++ b/source/java/org/alfresco/rest/api/search/context/facetsresponse/Metric.java @@ -0,0 +1,39 @@ +/*- + * #%L + * Alfresco Remote API + * %% + * Copyright (C) 2005 - 2017 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.rest.api.search.context.facetsresponse; + +import java.util.Map; +import java.util.Date; +/** + * Metrics returned from Solr + */ +public interface Metric +{ + public static enum METRIC_TYPE {count}; + + METRIC_TYPE getType(); + Map getValue(); +} diff --git a/source/java/org/alfresco/rest/api/search/context/facetsresponse/MetricCount.java b/source/java/org/alfresco/rest/api/search/context/facetsresponse/MetricCount.java new file mode 100644 index 0000000000..b9b14a2864 --- /dev/null +++ b/source/java/org/alfresco/rest/api/search/context/facetsresponse/MetricCount.java @@ -0,0 +1,54 @@ +/*- + * #%L + * Alfresco Remote API + * %% + * Copyright (C) 2005 - 2017 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.rest.api.search.context.facetsresponse; + +import java.util.HashMap; +import java.util.Map; + +/** + * A count metric + */ +public class MetricCount implements Metric +{ + private final Map value = new HashMap<>(1); + + public MetricCount(Integer count) + { + value.put("count", count); + } + + @Override + public METRIC_TYPE getType() + { + return METRIC_TYPE.count; + } + + @Override + public Map getValue() + { + return value; + } +} diff --git a/source/java/org/alfresco/rest/api/search/impl/ResultMapper.java b/source/java/org/alfresco/rest/api/search/impl/ResultMapper.java index 4dd5c982fc..1d737ec715 100644 --- a/source/java/org/alfresco/rest/api/search/impl/ResultMapper.java +++ b/source/java/org/alfresco/rest/api/search/impl/ResultMapper.java @@ -29,16 +29,6 @@ package org.alfresco.rest.api.search.impl; import static org.alfresco.rest.api.search.impl.StoreMapper.DELETED; import static org.alfresco.rest.api.search.impl.StoreMapper.LIVE_NODES; import static org.alfresco.rest.api.search.impl.StoreMapper.VERSIONS; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Optional; - import org.alfresco.repo.search.impl.lucene.SolrJSONResultSet; import org.alfresco.repo.version.Version2Model; import org.alfresco.rest.api.DeletedNodes; @@ -52,6 +42,10 @@ import org.alfresco.rest.api.search.context.FacetFieldContext.Bucket; import org.alfresco.rest.api.search.context.FacetQueryContext; import org.alfresco.rest.api.search.context.SearchContext; import org.alfresco.rest.api.search.context.SpellCheckContext; +import org.alfresco.rest.api.search.context.facetsresponse.GenericBucket; +import org.alfresco.rest.api.search.context.facetsresponse.GenericFacetResponse; +import org.alfresco.rest.api.search.context.facetsresponse.GenericFacetResponse.FACET_TYPE; +import org.alfresco.rest.api.search.context.facetsresponse.MetricCount; import org.alfresco.rest.api.search.model.FacetField; import org.alfresco.rest.api.search.model.FacetQuery; import org.alfresco.rest.api.search.model.HighlightEntry; @@ -74,7 +68,16 @@ import org.alfresco.util.Pair; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import com.google.gdata.data.introspection.Collection; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Optional; + /** * Maps from a ResultSet to a json public api representation. @@ -274,6 +277,7 @@ public class ResultMapper { SearchContext context = null; Map facetQueries = solrResultSet.getFacetQueries(); + List facets = new ArrayList<>(); List facetResults = null; SpellCheckContext spellCheckContext = null; List ffcs = new ArrayList(); @@ -310,7 +314,7 @@ public class ResultMapper ffcs.addAll(getFacetBucketsForFacetFields(facetFields, searchQuery)); Map>> facetInterval = solrResultSet.getFacetIntervals(); - List intervals = getFacetBucketsForIntervals(facetInterval, searchQuery); + facets.addAll(getGenericFacetsForIntervals(facetInterval, searchQuery)); //Spelling SpellCheckResult spell = solrResultSet.getSpellCheckResult(); @@ -320,7 +324,7 @@ public class ResultMapper } //Put it all together - context = new SearchContext(solrResultSet.getLastIndexedTxId(), facetResults, ffcs, intervals, spellCheckContext, searchQuery.includeRequest()?searchQuery:null); + context = new SearchContext(solrResultSet.getLastIndexedTxId(), facets, facetResults, ffcs, spellCheckContext, searchQuery.includeRequest()?searchQuery:null); return isNullContext(context)?null:context; } /** @@ -366,6 +370,7 @@ public class ResultMapper } return facetResults; } + protected List getFacetBucketsForFacetFields(Map>> facetFields, SearchQuery searchQuery) { if (facetFields != null && !facetFields.isEmpty()) @@ -375,7 +380,7 @@ public class ResultMapper { if (facet.getValue() != null && !facet.getValue().isEmpty()) { - List buckets = new ArrayList<>(facet.getValue().size()); + List buckets = new ArrayList<>(facet.getValue().size()); for (Pair buck:facet.getValue()) { Object display = null; @@ -397,7 +402,7 @@ public class ResultMapper } } } - buckets.add(new Bucket(buck.getFirst(), filterQuery, buck.getSecond(), display)); + buckets.add(new FacetFieldContext.Bucket(buck.getFirst(), filterQuery, buck.getSecond(), display)); } ffcs.add(new FacetFieldContext(facet.getKey(), buckets)); } @@ -408,16 +413,22 @@ public class ResultMapper return Collections.emptyList(); } - protected List getFacetBucketsForIntervals(Map>> facetFields, SearchQuery searchQuery) + /** + * Returns generic faceting responses for Intervals + * @param facetFields + * @param searchQuery + * @return GenericFacetResponse + */ + protected static List getGenericFacetsForIntervals(Map>> facetFields, SearchQuery searchQuery) { if (facetFields != null && !facetFields.isEmpty()) { - List ffcs = new ArrayList<>(facetFields.size()); + List ffcs = new ArrayList<>(facetFields.size()); for (Entry>> facet:facetFields.entrySet()) { if (facet.getValue() != null && !facet.getValue().isEmpty()) { - List buckets = new ArrayList<>(facet.getValue().size()); + List buckets = new ArrayList<>(facet.getValue().size()); for (Pair buck:facet.getValue()) { String filterQuery = null; @@ -437,16 +448,16 @@ public class ResultMapper } } } - Bucket bucket = new Bucket(buck.getFirst(), filterQuery, buck.getSecond(), null); + GenericBucket bucket = new GenericBucket(buck.getFirst(), filterQuery, null , Arrays.asList(new MetricCount(buck.getSecond()))); buckets.add(bucket); } - ffcs.add(new FacetFieldContext(facet.getKey(), buckets)); + ffcs.add(new GenericFacetResponse(FACET_TYPE.interval, facet.getKey(), buckets)); } } return ffcs; } - return null; + return Collections.emptyList(); } /** @@ -460,7 +471,7 @@ public class ResultMapper && context.getConsistency() == null && context.getSpellCheck() == null && context.getFacetsFields() == null - && context.getFacetIntervals() == null); + && context.getFacets() == null); } /** diff --git a/source/test-java/org/alfresco/rest/api/search/ResultMapperTests.java b/source/test-java/org/alfresco/rest/api/search/ResultMapperTests.java index e8e9cdd9c7..668af7425e 100644 --- a/source/test-java/org/alfresco/rest/api/search/ResultMapperTests.java +++ b/source/test-java/org/alfresco/rest/api/search/ResultMapperTests.java @@ -51,6 +51,9 @@ import org.alfresco.rest.api.search.context.FacetFieldContext; import org.alfresco.rest.api.search.context.FacetQueryContext; import org.alfresco.rest.api.search.context.SearchContext; import org.alfresco.rest.api.search.context.SpellCheckContext; +import org.alfresco.rest.api.search.context.facetsresponse.GenericFacetResponse; +import org.alfresco.rest.api.search.context.facetsresponse.GenericFacetResponse.FACET_TYPE; +import org.alfresco.rest.api.search.context.facetsresponse.Metric.METRIC_TYPE; import org.alfresco.rest.api.search.impl.ResultMapper; import org.alfresco.rest.api.search.impl.StoreMapper; import org.alfresco.rest.api.search.model.HighlightEntry; @@ -88,6 +91,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** * Tests the ResultMapper class @@ -272,11 +276,14 @@ public class ResultMapperTests assertEquals("content.size",searchContext.getFacetsFields().get(0).getLabel()); //Facet intervals - assertEquals(2, searchContext.getFacetIntervals().size()); - assertEquals("creator",searchContext.getFacetIntervals().get(0).getLabel()); - assertEquals("last",searchContext.getFacetIntervals().get(0).getBuckets().get(0).getLabel()); - assertEquals("cm:creator:(a,b]",searchContext.getFacetIntervals().get(0).getBuckets().get(0).getFilterQuery()); - assertEquals(4,searchContext.getFacetIntervals().get(0).getBuckets().get(0).getCount()); + List intervalFacets = searchContext.getFacets().stream() + .filter(f -> f.getType().equals(FACET_TYPE.interval)).collect(Collectors.toList()); + assertEquals(2, intervalFacets.size()); + assertEquals("creator",intervalFacets.get(0).getLabel()); + assertEquals("last",intervalFacets.get(0).getBuckets().get(0).getLabel()); + assertEquals("cm:creator:(a,b]",intervalFacets.get(0).getBuckets().get(0).getFilterQuery()); + assertEquals(METRIC_TYPE.count,intervalFacets.get(0).getBuckets().get(0).getMetrics().get(0).getType()); + assertEquals(4,intervalFacets.get(0).getBuckets().get(0).getMetrics().get(0).getValue().get("count")); //Requests search Query assertNotNull(searchContext.getRequest()); @@ -289,9 +296,9 @@ public class ResultMapperTests assertTrue(mapper.isNullContext(new SearchContext(0l,null,null,null,null, null))); assertFalse(mapper.isNullContext(new SearchContext(1l,null,null,null,null, null))); assertFalse(mapper.isNullContext(new SearchContext(0l,null,null,null,new SpellCheckContext(null, null), null))); - assertFalse(mapper.isNullContext(new SearchContext(0l,Arrays.asList(new FacetQueryContext(null, null, 0)),null,null,null, null))); - assertFalse(mapper.isNullContext(new SearchContext(0l,null,Arrays.asList(new FacetFieldContext(null, null)),null,null, null))); + assertFalse(mapper.isNullContext(new SearchContext(0l,null, Arrays.asList(new FacetQueryContext(null, null, 0)),null,null, null))); assertFalse(mapper.isNullContext(new SearchContext(0l,null,null,Arrays.asList(new FacetFieldContext(null, null)),null, null))); + assertFalse(mapper.isNullContext(new SearchContext(0l,Arrays.asList(new GenericFacetResponse(null,null, null)),null,null, null, null))); } @Test diff --git a/source/test-java/org/alfresco/rest/api/search/SearchQuerySerializerTests.java b/source/test-java/org/alfresco/rest/api/search/SearchQuerySerializerTests.java index 367355640f..f3e9a6feff 100644 --- a/source/test-java/org/alfresco/rest/api/search/SearchQuerySerializerTests.java +++ b/source/test-java/org/alfresco/rest/api/search/SearchQuerySerializerTests.java @@ -171,8 +171,8 @@ public class SearchQuerySerializerTests ExecutionResult exec1 = new ExecutionResult(new Farmer("180"),null); FacetFieldContext ffc = new FacetFieldContext("theLabel", Arrays.asList(new Bucket("b1", "name:b1", 23, "displayText1"), new Bucket("b2", null, 34, "displayText2"))); - SearchContext searchContext = new SearchContext(23l, Arrays.asList(new FacetQueryContext("f1", "creator:bob", 15), new FacetQueryContext("f2", null, 20)), - Arrays.asList(ffc), null, + SearchContext searchContext = new SearchContext(23l,null, Arrays.asList(new FacetQueryContext("f1", "creator:bob", 15), new FacetQueryContext("f2", null, 20)), + Arrays.asList(ffc), new SpellCheckContext("aFlag", Arrays.asList("bish", "bash")), null); CollectionWithPagingInfo coll = CollectionWithPagingInfo.asPaged(null, Arrays.asList(exec1), false, 2, null, searchContext); String out = helper.writeResponse(coll);