Project

General

Profile

1
package eu.dnetlib.index.query;
2

    
3
import java.util.ArrayList;
4
import java.util.Collection;
5
import java.util.List;
6
import java.util.Map;
7
import java.util.function.Function;
8
import java.util.stream.Collectors;
9

    
10
import com.google.common.collect.BiMap;
11
import com.google.common.collect.Iterables;
12
import com.google.common.collect.Lists;
13
import eu.dnetlib.clients.index.query.QueryResponseParser;
14
import eu.dnetlib.clients.index.utils.IndexFieldUtility;
15
import eu.dnetlib.rmi.provision.BrowsingRow;
16
import eu.dnetlib.rmi.provision.GroupResult;
17
import org.apache.commons.logging.Log;
18
import org.apache.commons.logging.LogFactory;
19
import org.apache.solr.client.solrj.response.FacetField;
20
import org.apache.solr.client.solrj.response.FacetField.Count;
21
import org.apache.solr.client.solrj.response.QueryResponse;
22
import org.apache.solr.common.SolrDocument;
23
import org.apache.solr.common.SolrDocumentList;
24

    
25
/**
26
 * The Class SolrResponseParser.
27
 */
28
public class SolrResponseParser extends QueryResponseParser {
29

    
30
	/**
31
	 * logger.
32
	 */
33
	private static final Log log = LogFactory.getLog(SolrResponseParser.class);
34
	/**
35
	 * The wrapper rank.
36
	 */
37
	protected final Function<SolrDocument, String> wrapperRank =
38
			doc -> addRanking(getSingleField(doc, IndexFieldUtility.RESULT), getSingleField(doc, IndexFieldUtility.SCORE_FIELD));
39
	/**
40
	 * The wrapper no rank.
41
	 */
42
	protected final Function<SolrDocument, String> wrapperNoRank = doc -> wrap(getSingleField(doc, IndexFieldUtility.RESULT));
43
	/**
44
	 * Lower level response.
45
	 */
46
	private QueryResponse queryRsp = null;
47

    
48
	/**
49
	 * The Constructor.
50
	 *
51
	 * @param highlightUtils    the highlight utils
52
	 * @param aliases           the aliases
53
	 * @param returnEmptyFields the return empty fields
54
	 * @param includeRanking    the include ranking
55
	 * @param response          the response
56
	 */
57
	public SolrResponseParser(final Function<String, String> highlightUtils, final BiMap<String, String> aliases, final boolean returnEmptyFields,
58
			final boolean includeRanking, final QueryResponse response) {
59
		super(highlightUtils, aliases, returnEmptyFields, includeRanking);
60
		this.queryRsp = response;
61
	}
62

    
63
	/**
64
	 * {@inheritDoc}
65
	 */
66
	@Override
67
	public long getNumFound() {
68

    
69
		return this.queryRsp.getResults().getNumFound();
70
	}
71

    
72
	/**
73
	 * {@inheritDoc}
74
	 */
75
	@Override
76
	public int getQueryTime() {
77
		return queryRsp.getQTime();
78
	}
79

    
80
	/**
81
	 * {@inheritDoc}
82
	 */
83
	@Override
84
	public long getElapsedTime() {
85
		return queryRsp.getElapsedTime();
86
	}
87

    
88
	/**
89
	 * {@inheritDoc}
90
	 */
91
	@Override
92
	public String getStatus() {
93
		return String.valueOf(queryRsp.getStatus());
94
	}
95

    
96
	/**
97
	 * {@inheritDoc}
98
	 */
99
	@Override
100
	public int getCurrentSize() {
101
		return queryRsp.getResults().size();
102
	}
103

    
104
	/**
105
	 * Gets the query response.
106
	 *
107
	 * @return the query response
108
	 */
109
	public QueryResponse getQueryResponse() {
110
		return queryRsp;
111
	}
112

    
113
	/**
114
	 * {@inheritDoc}
115
	 */
116
	@Override
117
	public List<String> getResults() {
118
		return asRankedList(queryRsp.getResults());
119
	}
120

    
121
	/**
122
	 * {@inheritDoc}
123
	 */
124
	@Override
125
	public Long getNumberOfBrowsingResults() {
126
		List<FacetField> ffList = queryRsp.getFacetFields();
127
		Long maxCount = 0L;
128

    
129
		if (ffList != null) {
130
			for (FacetField ff : ffList) {
131
				if (ff != null) {
132
					Long countFacets = countFacets(ff.getValues());
133
					if (countFacets > maxCount) {
134
						maxCount = countFacets;
135
					}
136
				}
137
			}
138
		}
139
		return maxCount;
140
	}
141

    
142
	/**
143
	 * {@inheritDoc}
144
	 */
145
	@Override
146
	public List<BrowsingRow> getBrowsingResults() {
147
		List<BrowsingRow> bresList = new ArrayList<>();
148
		List<GroupResult> facets = new ArrayList<>();
149

    
150
		final List<FacetField> ffList = queryRsp.getFacetFields();
151

    
152
		Long numberOfBrowsingResults = getNumberOfBrowsingResults();
153
		for (int i = 0; (ffList != null) && (i < numberOfBrowsingResults); i++) {
154
			for (FacetField ff : ffList) {
155

    
156
				String name = null;
157
				if (aliases != null) {
158
					name = aliases.inverse().get(ff.getName());
159
				}
160

    
161
				// fix #1456
162
				if (name == null) {
163
					name = ff.getName();
164
				}
165

    
166
				final Count facet = getFacet(ff, i);
167

    
168
				if ((facet != null) && (facet.getCount() > 0)) {
169

    
170
					final String value = facet.getName();
171
					final int count = (int) facet.getCount();
172

    
173
					if (returnEmptyFields || !value.isEmpty()) {
174
						facets.add(new GroupResult(name, value, count));
175
					}
176
				}
177
			}
178

    
179
			if (facets.size() > 0) {
180
				bresList.add(new BrowsingRow(Lists.newArrayList(facets)));
181
				facets.clear();
182
			}
183
		}
184
		if (log.isDebugEnabled()) {
185
			log.debug("BrowsingResult size: " + bresList.size());
186
		}
187
		return bresList;
188
	}
189

    
190
	// /////////////// helpers
191

    
192
	/**
193
	 * Gets the facet.
194
	 *
195
	 * @param ff  the ff
196
	 * @param pos the pos
197
	 * @return the facet
198
	 */
199
	private Count getFacet(final FacetField ff, final int pos) {
200

    
201
		if ((ff.getValues() == null) || (pos >= ff.getValues().size())) return null;
202
		return ff.getValues().get(pos);
203
	}
204

    
205
	/**
206
	 * Given SolrDocumentList, return a List of Strings, representing it.
207
	 *
208
	 * @param documentList the document list
209
	 * @return the list< string>
210
	 */
211
	private List<String> asRankedList(final SolrDocumentList documentList) {
212
		Function<SolrDocument, String> wrapper = includeRanking ? wrapperRank : wrapperNoRank;
213

    
214
		if (queryRsp.getHighlighting() != null) return documentList
215
				.stream()
216
				.map(doc -> {
217
					String score = getSingleField(doc, IndexFieldUtility.SCORE_FIELD);
218

    
219
					String hl = getHighlighting(getSingleField(doc, IndexFieldUtility.INDEX_RECORD_ID));
220
					String res = hl != null ? hl : getSingleField(doc, IndexFieldUtility.RESULT);
221

    
222
					return includeRanking ? addRanking(res, score) : wrap(res);
223
				}).map(highlightUtils)
224
				.collect(Collectors.toList());
225
		return documentList.stream().map(wrapper).collect(Collectors.toList());
226
	}
227

    
228
	/**
229
	 * Converts a String document to
230
	 * <p>
231
	 * <record rank="score"> [document] </record>.
232
	 *
233
	 * @param doc   the doc
234
	 * @param score the score
235
	 * @return the string
236
	 */
237
	private String addRanking(final String doc, final String score) {
238
		return new String("<record rank=\"" + score + "\">" + doc + "</record>");
239
	}
240

    
241
	/**
242
	 * Wraps the given document as <record> [document] </record>.
243
	 *
244
	 * @param doc the doc
245
	 * @return the string
246
	 */
247
	private String wrap(final String doc) {
248
		return new String("<record>" + doc + "</record>");
249
	}
250

    
251
	/**
252
	 * Gets the single field.
253
	 *
254
	 * @param doc       the doc
255
	 * @param fieldName the field name
256
	 * @return the single field
257
	 */
258
	@SuppressWarnings("unchecked")
259
	protected String getSingleField(final SolrDocument doc, final String fieldName) {
260
		Object value = doc.getFieldValue(fieldName);
261
		if (value instanceof Collection) return Iterables.getOnlyElement((Iterable<String>) value);
262
		return String.valueOf(value);
263
	}
264

    
265
	/**
266
	 * Gets the highlighting.
267
	 *
268
	 * @param docId the doc id
269
	 * @return the highlighting
270
	 */
271
	private String getHighlighting(final String docId) {
272
		final Map<String, List<String>> highlight = queryRsp.getHighlighting().get(docId);
273

    
274
		String result = new String();
275
		if ((highlight != null) && (highlight.get(IndexFieldUtility.RESULT) != null)) {
276
			for (String s : highlight.get(IndexFieldUtility.RESULT)) {
277
				result = result.concat(s);
278
			}
279
			return result;
280
		}
281
		return null;
282
	}
283

    
284
	/**
285
	 * helper method.
286
	 *
287
	 * @param facets the list of facets to analyze
288
	 * @return the number of non-empty facets in the list whose count is greater than zero
289
	 */
290
	private Long countFacets(final List<Count> facets) {
291

    
292
		if (facets == null) return 0L;
293
		return facets.stream().filter(c -> (c != null) && (c.getName() != null) && !c.getName().isEmpty() && (c.getCount() > 0)).count();
294
	}
295

    
296
	@Override
297
	public long getStart() {
298
		// TODO Auto-generated method stub
299
		return queryRsp.getResults().getStart();
300
	}
301

    
302
}
(5-5/5)