001
002package org.opencms.search.solr;
003
004import org.opencms.search.CmsSearchResource;
005
006import java.util.ArrayList;
007import java.util.Collections;
008import java.util.HashMap;
009import java.util.List;
010import java.util.Map;
011
012import org.apache.solr.client.solrj.SolrQuery;
013import org.apache.solr.client.solrj.response.FacetField;
014import org.apache.solr.client.solrj.response.QueryResponse;
015import org.apache.solr.client.solrj.response.RangeFacet;
016import org.apache.solr.client.solrj.response.SpellCheckResponse;
017import org.apache.solr.common.SolrDocumentList;
018
019/**
020 * Encapsulates a list of 'OpenCms resource documents' ({@link CmsSearchResource}).<p>
021 *
022 * This list can be accessed exactly like an {@link ArrayList} which entries are
023 * {@link CmsSearchResource} that extend {@link org.opencms.file.CmsResource} and
024 * holds the Solr implementation of {@link org.opencms.search.I_CmsSearchDocument}
025 * as member. <b>This enables you to deal with the resulting list as you do with
026 * well known {@link List} and work on it's entries like you do on
027 * {@link org.opencms.file.CmsResource}.</b><p>
028 *
029 * @since 8.5.0
030 */
031public class CmsSolrResultList extends ArrayList<CmsSearchResource> {
032
033    /** The serial version UID. */
034    private static final long serialVersionUID = 707475894827620542L;
035
036    /** The end index of documents to display (start + rows). */
037    private int m_end;
038
039    /** The time in ms when the highlighting is finished. */
040    private long m_highlightEndTime;
041
042    /** A map of highlighting. */
043    private Map<String, Map<String, List<String>>> m_highlighting;
044
045    /** The current page (start / rows), used to build a pagination. */
046    private int m_page;
047
048    /** The original Solr query. */
049    private SolrQuery m_query;
050
051    /** The original query response. */
052    private QueryResponse m_queryResponse;
053
054    /** The original list of Solr documents. */
055    private SolrDocumentList m_resultDocuments;
056
057    /** The row count. */
058    private Integer m_rows;
059
060    /** The start time, when the search query was executed. */
061    private long m_startTime;
062
063    /** The count of visible documents. */
064    private long m_visibleHitCount;
065
066    /**
067     * The public constructor.<p>
068     *
069     * @param query original Solr query
070     * @param queryResponse original query response
071     * @param resultDocuments original list of Solr documents
072     * @param resourceDocumentList the list of resource documents
073     * @param start the start (offset)
074     * @param rows the rows (hits per page)
075     * @param end the end (start + rows)
076     * @param page the current page (start / rows)
077     * @param visibleHitCount the visible hit count
078     * @param maxScore the max score of the best matching doc
079     * @param startTime the start time when the query has been executed
080     * @param highlightEndTime the time in ms when the highlighting is finished
081     */
082    public CmsSolrResultList(
083        SolrQuery query,
084        QueryResponse queryResponse,
085        SolrDocumentList resultDocuments,
086        List<CmsSearchResource> resourceDocumentList,
087        int start,
088        Integer rows,
089        int end,
090        int page,
091        long visibleHitCount,
092        Float maxScore,
093        long startTime,
094        long highlightEndTime) {
095
096        super(resourceDocumentList);
097
098        m_query = query;
099        m_startTime = startTime;
100        m_highlightEndTime = highlightEndTime;
101        m_rows = rows;
102        m_end = end;
103        m_page = page;
104        m_visibleHitCount = visibleHitCount;
105
106        m_resultDocuments = resultDocuments;
107        m_queryResponse = queryResponse;
108
109        m_highlighting = transformHighlighting();
110    }
111
112    /**
113     * Returns the last index of documents to display.<p>
114     *
115     * @return the last index of documents to display
116     */
117    public int getEnd() {
118
119        return m_end;
120    }
121
122    /**
123     * Delegator.<p>
124     *
125     * @param name the name
126     *
127     * @return the facet field
128     */
129    public FacetField getFacetDate(String name) {
130
131        return m_queryResponse.getFacetDate(name);
132    }
133
134    /**
135     * Delegator.<p>
136     *
137     * @return the list of faceted date fields
138     */
139    public List<FacetField> getFacetDates() {
140
141        return m_queryResponse.getFacetDates();
142    }
143
144    /**
145     * Delegator.<p>
146     *
147     * @param name the name
148     *
149     * @return the facet field
150     */
151    public FacetField getFacetField(String name) {
152
153        return m_queryResponse.getFacetField(name);
154    }
155
156    /**
157     * Delegator.<p>
158     *
159     * @return the list of faceted fields
160     */
161    public List<FacetField> getFacetFields() {
162
163        return m_queryResponse.getFacetFields();
164    }
165
166    /**
167     * Delegator.<p>
168     *
169     * @return the facet query
170     */
171    public Map<String, Integer> getFacetQuery() {
172
173        return m_queryResponse.getFacetQuery();
174    }
175
176    /**
177     * Delegator.<p>
178     *
179     * @return the list of facet ranges
180     */
181    @SuppressWarnings("rawtypes")
182    public List<RangeFacet> getFacetRanges() {
183
184        return m_queryResponse.getFacetRanges();
185    }
186
187    /**
188     * Returns the time in ms when the highlighting is finished.<p>
189     *
190     * @return the time in ms when the highlighting is finished
191     */
192    public long getHighlightEndTime() {
193
194        return m_highlightEndTime;
195    }
196
197    /**
198     * Returns the highlighting information.<p>
199     *
200     * @return the highlighting information
201     */
202    public Map<String, Map<String, List<String>>> getHighLighting() {
203
204        return m_highlighting;
205    }
206
207    /**
208     * Delegator.<p>
209     *
210     * @return the limiting facets
211     */
212    public List<FacetField> getLimitingFacets() {
213
214        return m_queryResponse.getLimitingFacets();
215    }
216
217    /**
218     * Returns the score of the best matching document.<p>
219     *
220     * @return the score of the best matching document
221     */
222    public Float getMaxScore() {
223
224        return m_resultDocuments.getMaxScore();
225    }
226
227    /**
228     * Returns the count of docs that have been found.<p>
229     *
230     * @return the count of docs that have been found
231     */
232    public long getNumFound() {
233
234        return m_resultDocuments.getNumFound();
235    }
236
237    /**
238     * Returns the current page.<p>
239     *
240     * @return the current page
241     */
242    public int getPage() {
243
244        return m_page;
245    }
246
247    /**
248     * The original Solr query.<p>
249     *
250     * @return the query
251     */
252    public SolrQuery getQuery() {
253
254        return m_query;
255    }
256
257    /**
258     * Returns the requested row count.<p>
259     *
260     * @return the rows
261     */
262    public Integer getRows() {
263
264        return m_rows;
265    }
266
267    /**
268     * Delegator.<p>
269     *
270     * @return the spellcheck response
271     */
272    public SpellCheckResponse getSpellCheckResponse() {
273
274        return m_queryResponse.getSpellCheckResponse();
275    }
276
277    /**
278     * Returns the start index (offset).<p>
279     *
280     * @return the start
281     */
282    public Long getStart() {
283
284        return Long.valueOf(m_resultDocuments.getStart());
285    }
286
287    /**
288     * Returns the start time.<p>
289     *
290     * @return the start time
291     */
292    public long getStartTime() {
293
294        return m_startTime;
295    }
296
297    /**
298     * Returns the visible hit count.<p>
299     *
300     * @return the visible count of documents
301     */
302    public long getVisibleHitCount() {
303
304        return m_visibleHitCount;
305    }
306
307    /**
308     * Transforms / corrects the highlighting.<p>
309     *
310     * @return the highlighting
311     */
312    private Map<String, Map<String, List<String>>> transformHighlighting() {
313
314        Map<String, Map<String, List<String>>> result = new HashMap<String, Map<String, List<String>>>();
315        if (m_queryResponse.getHighlighting() != null) {
316            for (String key : m_queryResponse.getHighlighting().keySet()) {
317                Map<String, ?> value = m_queryResponse.getHighlighting().get(key);
318                Map<String, List<String>> innerResult = new HashMap<String, List<String>>();
319                for (String innerKey : value.keySet()) {
320                    Object entry = value.get(innerKey);
321                    List<String> innerList = new ArrayList<String>();
322                    if (entry instanceof String) {
323                        innerResult.put(innerKey, Collections.singletonList((String)entry));
324                    } else if (entry instanceof String[]) {
325                        String[] li = (String[])entry;
326                        for (Object lo : li) {
327                            String s = (String)lo;
328                            innerList.add(s);
329                        }
330                        innerResult.put(innerKey, innerList);
331                    } else if (entry instanceof List<?>) {
332                        List<?> li = (List<?>)entry;
333                        for (Object lo : li) {
334                            String s = (String)lo;
335                            innerList.add(s);
336                        }
337                        innerResult.put(innerKey, innerList);
338                    }
339                }
340                result.put(key, innerResult);
341            }
342        }
343        return result;
344    }
345}