1 package org.kuali.ole.docstore.engine.service.search;
2
3 import org.apache.commons.lang.StringUtils;
4 import org.apache.solr.client.solrj.SolrServer;
5 import org.apache.solr.client.solrj.SolrServerException;
6 import org.apache.solr.client.solrj.response.QueryResponse;
7 import org.apache.solr.common.SolrDocument;
8 import org.apache.solr.common.SolrDocumentList;
9 import org.kuali.ole.docstore.common.document.*;
10 import org.kuali.ole.docstore.common.exception.DocstoreIndexException;
11 import org.kuali.ole.docstore.common.search.*;
12 import org.kuali.ole.docstore.discovery.service.SolrServerManager;
13 import org.kuali.ole.docstore.engine.service.index.solr.BibConstants;
14 import org.kuali.ole.docstore.engine.service.index.solr.HoldingsConstants;
15 import org.kuali.ole.docstore.model.enums.DocType;
16 import org.slf4j.Logger;
17 import org.slf4j.LoggerFactory;
18 import org.apache.solr.client.solrj.SolrQuery;
19 import org.springframework.util.CollectionUtils;
20
21 import java.io.UnsupportedEncodingException;
22 import java.net.URLEncoder;
23 import java.text.CharacterIterator;
24 import java.text.StringCharacterIterator;
25 import java.util.*;
26
27
28
29
30
31
32
33
34 public class DocstoreSolrSearchService implements DocstoreSearchService {
35
36 private static final Logger LOG = LoggerFactory.getLogger(DocstoreSolrSearchService.class);
37
38 private static Map<String, String> searchFieldsMap = new HashMap<>();
39
40 static {
41 searchFieldsMap.put(Bib.ID, "id");
42 searchFieldsMap.put(Bib.AUTHOR, "Author_search");
43 searchFieldsMap.put(Bib.TITLE, "Title_search");
44 searchFieldsMap.put(Bib.PUBLICATIONDATE, "PublicationDate_search");
45 searchFieldsMap.put(Bib.PUBLISHER, "Publisher_search");
46 searchFieldsMap.put(Bib.ISBN, "ISBN_search");
47 searchFieldsMap.put(Bib.ISSN, "ISSN_search");
48 searchFieldsMap.put(Bib.SUBJECT, "Subject_search");
49 searchFieldsMap.put(Bib.EDITION, "Edition_search");
50 searchFieldsMap.put(Bib.DESCRIPTION, "Description_search");
51 searchFieldsMap.put(Bib.FORMAT, "Format_search");
52 searchFieldsMap.put(Bib.LANGUAGE, "Language_search");
53 searchFieldsMap.put(Bib.BIBIDENTIFIER, "bibIdentifier");
54 searchFieldsMap.put(Holdings.LOCATION_NAME, "LocationLevel_search");
55 searchFieldsMap.put(Holdings.CALL_NUMBER, "CallNumber_search");
56 searchFieldsMap.put(Holdings.CALLNUMBER_PREFIX, "CallNumberPrefix_search");
57 searchFieldsMap.put(Holdings.CALLNUMBER_TYPE, "CallNumberType_search");
58 searchFieldsMap.put(Holdings.COPY_NUMBER, "CopyNumber_search");
59 searchFieldsMap.put(Holdings.HOLDINGSIDENTIFIER, "holdingsIdentifier");
60 searchFieldsMap.put(Item.SHELVING_ORDER, "ShelvingOrder_search");
61 searchFieldsMap.put(Item.ITEM_BARCODE, "ItemBarcode_search");
62 searchFieldsMap.put(Item.ENUMERATION, "Enumeration_search");
63 searchFieldsMap.put(Item.CHRONOLOGY, "Chronology_search");
64 searchFieldsMap.put(Item.ITEM_TYPE, "ItemTypeCodeValue_search");
65 searchFieldsMap.put(Item.VOLUME_NUMBER, "VolumeNumber_search");
66 searchFieldsMap.put(Item.ITEM_STATUS, "ItemStatus_search");
67 searchFieldsMap.put(Item.ITEMIDENTIFIER, "ItemIdentifier_search");
68 }
69
70 private static Map<String, String> searchResultFieldsMap = new HashMap<>();
71
72 static {
73 searchResultFieldsMap.put(Bib.ID, "id");
74 searchResultFieldsMap.put(Bib.AUTHOR, "Author_display");
75 searchResultFieldsMap.put(Bib.TITLE, "Title_display");
76 searchResultFieldsMap.put(Bib.PUBLICATIONDATE, "PublicationDate_display");
77 searchResultFieldsMap.put(Bib.PUBLISHER, "Publisher_display");
78 searchResultFieldsMap.put(Bib.ISBN, "ISBN_display");
79 searchResultFieldsMap.put(Bib.ISSN, "ISSN_display");
80 searchResultFieldsMap.put(Bib.SUBJECT, "Subject_display");
81 searchResultFieldsMap.put(Bib.EDITION, "Edition_display");
82 searchResultFieldsMap.put(Bib.DESCRIPTION, "Description_display");
83 searchResultFieldsMap.put(Bib.FORMAT, "Format_display");
84 searchResultFieldsMap.put(Bib.LANGUAGE, "Language_display");
85 searchResultFieldsMap.put(Holdings.LOCATION_NAME, "LocationLevel_display");
86 searchResultFieldsMap.put(Holdings.CALL_NUMBER, "CallNumber_display");
87 searchResultFieldsMap.put(Holdings.CALLNUMBER_PREFIX, "CallNumberPrefix_display");
88 searchResultFieldsMap.put(Holdings.CALLNUMBER_TYPE, "CallNumberType_display");
89 searchResultFieldsMap.put(Holdings.COPY_NUMBER, "CopyNumber_display");
90 searchResultFieldsMap.put(Item.SHELVING_ORDER, "ShelvingOrder_display");
91 searchResultFieldsMap.put(Item.ITEM_BARCODE, "ItemBarcode_display");
92 searchResultFieldsMap.put(Item.ENUMERATION, "Enumeration_display");
93 searchResultFieldsMap.put(Item.CHRONOLOGY, "Chronology_display");
94 searchResultFieldsMap.put(Item.ITEM_TYPE, "ItemTypeCodeValue_display");
95 searchResultFieldsMap.put(Item.VOLUME_NUMBER, "VolumeNumber_display");
96 searchResultFieldsMap.put(Item.ITEM_STATUS, "ItemStatus_display");
97 searchResultFieldsMap.put(Bib.BIBIDENTIFIER, "bibIdentifier");
98 searchResultFieldsMap.put(Holdings.HOLDINGSIDENTIFIER, "holdingsIdentifier");
99 searchResultFieldsMap.put(Item.ITEMIDENTIFIER, "itemIdentifier");
100 }
101
102 @Override
103 public SearchResponse search(SearchParams searchParams) {
104 try {
105 SolrQuery solrQuery = new SolrQuery();
106 SolrServer server = SolrServerManager.getInstance().getSolrServer();
107 String query = buildQueryWithSearchParams(searchParams);
108 solrQuery.setQuery(query);
109 if (searchParams.getPageSize() != 0) {
110 solrQuery.setRows(searchParams.getPageSize());
111 }
112 solrQuery.setStart(searchParams.getStartIndex());
113 if (!CollectionUtils.isEmpty(searchParams.getSearchResultFields())) {
114 solrQuery.setFields(buildQueryWithResultFieldsLists(searchParams));
115 }
116 QueryResponse response = server.query(solrQuery);
117 return buildSearchResponse(response.getResults(), searchParams);
118 } catch (SolrServerException ex) {
119 LOG.info("Exception :", ex);
120 throw new DocstoreIndexException(ex.getMessage());
121 }
122 }
123
124 private SearchResponse buildSearchResponse(SolrDocumentList results, SearchParams searchParams) {
125 String searchConditionDocType = null;
126 SearchResponse searchResponse = new SearchResponse();
127 List<SearchResult> searchResults = new ArrayList<>();
128 if (!CollectionUtils.isEmpty(searchParams.getSearchConditions())) {
129 searchConditionDocType = searchParams.getSearchConditions().get(0).getSearchField().getDocType();
130 }
131 List<SearchResultField> searchResultFields = new ArrayList<SearchResultField>();
132 if (CollectionUtils.isEmpty(searchParams.getSearchResultFields())) {
133 searchResultFields = getDefaultSearchResultFields(searchParams);
134 } else {
135 searchResultFields = searchParams.getSearchResultFields();
136 }
137 for (SolrDocument solrDocument : results) {
138 SolrDocument bibSolrDocument = null;
139
140
141 SearchResult searchResult = new SearchResult();
142 List<SearchResultField> newSearchResultFields = new ArrayList<SearchResultField>();
143 for (SearchResultField searchResultField : searchResultFields) {
144 SearchResultField newSearchResultField = new SearchResultField();
145 if (StringUtils.isBlank(searchConditionDocType) || searchResultField.getDocType().equalsIgnoreCase(searchConditionDocType)) {
146 String fieldValue = searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) : searchResultField.getFieldName();
147 if (fieldValue.equalsIgnoreCase("id") || fieldValue.equalsIgnoreCase("bibIdentifier") || fieldValue.equalsIgnoreCase("holdingsIdentifier") || fieldValue.equalsIgnoreCase("itemIdentifier") || fieldValue.equalsIgnoreCase("ItemIdentifier_display")) {
148 newSearchResultFields.addAll(buildSearchResultsForIds(solrDocument, searchResultField));
149 continue;
150 }
151 String resultFieldValue = getSolrFieldValue(solrDocument, fieldValue);
152 if (StringUtils.isNotBlank(resultFieldValue)) {
153 newSearchResultField.setFieldValue(resultFieldValue);
154 }
155 } else {
156 if (searchResultField.getDocType().equalsIgnoreCase(HOLDINGS)) {
157 if (searchConditionDocType.equalsIgnoreCase(ITEM) || searchConditionDocType.equalsIgnoreCase(BIBLIOGRAPHIC)) {
158 newSearchResultFields.addAll(buildHoldingsSearchResults(solrDocument, searchResultField));
159 continue;
160 }
161 } else if (searchResultField.getDocType().equalsIgnoreCase(BIBLIOGRAPHIC)) {
162 if (searchConditionDocType.equalsIgnoreCase(ITEM) || searchConditionDocType.equalsIgnoreCase(HOLDINGS)) {
163 newSearchResultFields.addAll(buildBibSearchResults(solrDocument, searchResultField));
164 continue;
165 }
166 } else if (searchResultField.getDocType().equalsIgnoreCase(ITEM)) {
167 if (searchConditionDocType.equalsIgnoreCase(HOLDINGS)) {
168 newSearchResultFields.addAll(buildItemSearchResultsForHoldings(solrDocument, searchResultField));
169 continue;
170 } else if (searchConditionDocType.equalsIgnoreCase(BIBLIOGRAPHIC)) {
171 newSearchResultFields.addAll(buildItemSearchResultsForBib(solrDocument, searchResultField));
172 continue;
173 }
174 } else if (searchConditionDocType.equalsIgnoreCase(EHOLDINGS)) {
175 if (bibSolrDocument == null) {
176 bibSolrDocument = getBibRecord((String) solrDocument.getFieldValue("bibIdentifier"));
177 }
178 String fieldValue = searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) : searchResultField.getFieldName();
179 String resultFieldValue = getSolrFieldValue(bibSolrDocument, fieldValue);
180 if (StringUtils.isNotBlank(resultFieldValue)) {
181 newSearchResultField.setFieldValue(resultFieldValue);
182 }
183 }
184 }
185 newSearchResultField.setDocType(searchResultField.getDocType());
186 newSearchResultField.setFieldName(searchResultField.getFieldName());
187
188 newSearchResultFields.add(newSearchResultField);
189 }
190 searchResult.getSearchResultFields().addAll(newSearchResultFields);
191 searchResults.add(searchResult);
192 }
193 searchResponse.getSearchResults().addAll(searchResults);
194 searchResponse.setTotalRecordCount((int) results.getNumFound());
195 if (searchParams.getPageSize() == 0) {
196 searchResponse.setPageSize(results.size());
197 } else {
198 searchResponse.setPageSize(searchParams.getPageSize());
199 }
200 searchResponse.setStartIndex(searchParams.getStartIndex());
201 searchResponse.setEndIndex(searchParams.getStartIndex() + searchParams.getPageSize());
202 return searchResponse;
203 }
204
205 private List<SearchResultField> buildSearchResultsForIds(SolrDocument solrDocument, SearchResultField searchResultField) {
206 List<SearchResultField> newSearchResultFields = new ArrayList<SearchResultField>();
207 Object object = solrDocument.getFieldValue(searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) : searchResultField.getFieldName());
208 if (object instanceof String) {
209 SearchResultField newSearchResultField = new SearchResultField();
210 newSearchResultField.setDocType(searchResultField.getDocType());
211 newSearchResultField.setFieldName(searchResultField.getFieldName());
212 newSearchResultField.setFieldValue((String) object);
213 newSearchResultFields.add(newSearchResultField);
214 } else {
215 if (((List) object) != null) {
216 for (Object identifier : (List) object) {
217 SearchResultField newSearchResultField = new SearchResultField();
218 newSearchResultField.setDocType(searchResultField.getDocType());
219 newSearchResultField.setFieldName(searchResultField.getFieldName());
220 newSearchResultField.setFieldValue((String) identifier);
221 newSearchResultFields.add(newSearchResultField);
222 }
223 }
224 }
225 return newSearchResultFields;
226 }
227
228 private List<SearchResultField> buildBibSearchResults(SolrDocument solrDocument, SearchResultField searchResultField) {
229 List<SearchResultField> newSearchResultFields = new ArrayList<SearchResultField>();
230 Object object = solrDocument.getFieldValue("bibIdentifier");
231 if (object instanceof String) {
232 SearchResultField newSearchResultField = new SearchResultField();
233 SolrDocument bibSolrDocument = getBibRecord((String) object);
234 if (bibSolrDocument != null) {
235 String fieldValue = searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) : searchResultField.getFieldName();
236 String resultFieldValue = getSolrFieldValue(bibSolrDocument, fieldValue);
237 if (StringUtils.isNotBlank(resultFieldValue)) {
238 newSearchResultField.setFieldValue(resultFieldValue);
239 }
240 newSearchResultField.setDocType(searchResultField.getDocType());
241 newSearchResultField.setFieldName(searchResultField.getFieldName());
242
243 newSearchResultFields.add(newSearchResultField);
244 }
245 } else {
246 if (((List) object) != null) {
247 for (Object bibIdentifier : (List) object) {
248 SearchResultField newSearchResultField = new SearchResultField();
249 SolrDocument bibSolrDocument = getBibRecord((String) bibIdentifier);
250 if (bibSolrDocument != null) {
251 String fieldValue = searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) : searchResultField.getFieldName();
252 String resultFieldValue = getSolrFieldValue(bibSolrDocument, fieldValue);
253 if (StringUtils.isNotBlank(resultFieldValue)) {
254 newSearchResultField.setFieldValue(resultFieldValue);
255 }
256 newSearchResultField.setDocType(searchResultField.getDocType());
257 newSearchResultField.setFieldName(searchResultField.getFieldName());
258
259 newSearchResultFields.add(newSearchResultField);
260 }
261 }
262 }
263 }
264 return newSearchResultFields;
265 }
266
267 private List<SearchResultField> buildItemSearchResultsForHoldings(SolrDocument solrDocument, SearchResultField searchResultField) {
268 List<SearchResultField> newSearchResultFields = new ArrayList<SearchResultField>();
269 Object object = solrDocument.getFieldValue("itemIdentifier");
270 if (object instanceof String) {
271 SearchResultField newSearchResultField = new SearchResultField();
272 SolrDocument itemSolrDocument = getItemRecord((String) object);
273 String fieldValue = searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) : searchResultField.getFieldName();
274 String resultFieldValue = getSolrFieldValue(itemSolrDocument, fieldValue);
275 if (StringUtils.isNotBlank(resultFieldValue)) {
276 newSearchResultField.setFieldValue(resultFieldValue);
277 }
278 newSearchResultField.setDocType(searchResultField.getDocType());
279 newSearchResultField.setFieldName(searchResultField.getFieldName());
280
281 newSearchResultFields.add(newSearchResultField);
282 } else {
283 if (((List) object) != null) {
284 for (Object identifier : (List) object) {
285 SearchResultField newSearchResultField = new SearchResultField();
286 SolrDocument itemSolrDocument = getItemRecord((String) identifier);
287 String fieldValue = searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) : searchResultField.getFieldName();
288 String resultFieldValue = getSolrFieldValue(itemSolrDocument, fieldValue);
289 if (StringUtils.isNotBlank(resultFieldValue)) {
290 newSearchResultField.setFieldValue(resultFieldValue);
291 }
292 newSearchResultField.setDocType(searchResultField.getDocType());
293 newSearchResultField.setFieldName(searchResultField.getFieldName());
294
295 newSearchResultFields.add(newSearchResultField);
296 }
297 }
298 }
299 return newSearchResultFields;
300 }
301
302 private List<SearchResultField> buildItemSearchResultsForBib(SolrDocument solrDocument, SearchResultField searchResultField) {
303 List<SearchResultField> newSearchResultFields = new ArrayList<SearchResultField>();
304 Object holdingsObject = solrDocument.getFieldValue("holdingsIdentifier");
305 if (holdingsObject instanceof String) {
306 SearchResultField newSearchResultField = new SearchResultField();
307 SolrDocument holdingsSolrDocument = getHoldingsRecord((String) holdingsObject);
308 if (holdingsSolrDocument != null) {
309 Object itemObject = holdingsSolrDocument.getFieldValue("itemIdentifier");
310 if (itemObject instanceof String) {
311 SolrDocument itemSolrDocument = getItemRecord((String) itemObject);
312 String fieldValue = searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) : searchResultField.getFieldName();
313 String resultFieldValue = getSolrFieldValue(itemSolrDocument, fieldValue);
314 if (StringUtils.isNotBlank(resultFieldValue)) {
315 newSearchResultField.setFieldValue(resultFieldValue);
316 }
317 newSearchResultField.setDocType(searchResultField.getDocType());
318 newSearchResultField.setFieldName(searchResultField.getFieldName());
319
320 newSearchResultFields.add(newSearchResultField);
321 } else {
322 if (((List) itemObject) != null) {
323 for (Object identifier : (List) itemObject) {
324 SearchResultField newSearchResultField1 = new SearchResultField();
325 SolrDocument itemSolrDocument = getItemRecord((String) identifier);
326 String fieldValue = searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) : searchResultField.getFieldName();
327 String resultFieldValue = getSolrFieldValue(itemSolrDocument, fieldValue);
328 if (StringUtils.isNotBlank(resultFieldValue)) {
329 newSearchResultField.setFieldValue(resultFieldValue);
330 }
331 newSearchResultField1.setDocType(searchResultField.getDocType());
332 newSearchResultField1.setFieldName(searchResultField.getFieldName());
333
334 newSearchResultFields.add(newSearchResultField1);
335 }
336 }
337 }
338 }
339 } else {
340 if (((List) holdingsObject) != null) {
341 for (Object identifier : (List) holdingsObject) {
342 SearchResultField newSearchResultField = new SearchResultField();
343 SolrDocument holdingsSolrDocument = getHoldingsRecord((String) identifier);
344 if (holdingsSolrDocument != null) {
345 Object itemObject = holdingsSolrDocument.getFieldValue("itemIdentifier");
346 if (itemObject instanceof String) {
347 SolrDocument itemSolrDocument = getItemRecord((String) itemObject);
348 String fieldValue = searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) : searchResultField.getFieldName();
349 String resultFieldValue = getSolrFieldValue(itemSolrDocument, fieldValue);
350 if (StringUtils.isNotBlank(resultFieldValue)) {
351 searchResultField.setFieldValue(resultFieldValue);
352 }
353 newSearchResultField.setDocType(searchResultField.getDocType());
354 newSearchResultField.setFieldName(searchResultField.getFieldName());
355 newSearchResultField.setFieldValue(searchResultField.getFieldValue());
356 newSearchResultFields.add(newSearchResultField);
357 } else {
358 if (((List) itemObject) != null) {
359 for (Object itemIdentifier : (List) itemObject) {
360 SearchResultField newSearchResultField1 = new SearchResultField();
361 SolrDocument itemSolrDocument = getItemRecord((String) itemIdentifier);
362 String fieldValue = searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) : searchResultField.getFieldName();
363 String resultFieldValue = getSolrFieldValue(itemSolrDocument, fieldValue);
364 if (StringUtils.isNotBlank(resultFieldValue)) {
365 searchResultField.setFieldValue(resultFieldValue);
366 }
367 newSearchResultField1.setDocType(searchResultField.getDocType());
368 newSearchResultField1.setFieldName(searchResultField.getFieldName());
369 newSearchResultField1.setFieldValue(searchResultField.getFieldValue());
370 newSearchResultFields.add(newSearchResultField1);
371 }
372 }
373 }
374 }
375 }
376 }
377 }
378 return newSearchResultFields;
379 }
380
381 private List<SearchResultField> buildHoldingsSearchResults(SolrDocument solrDocument, SearchResultField searchResultField) {
382 List<SearchResultField> newSearchResultFields = new ArrayList<SearchResultField>();
383 Object object = solrDocument.getFieldValue("holdingsIdentifier");
384 if (object instanceof String) {
385 SearchResultField newSearchResultField = new SearchResultField();
386 SolrDocument holdingsSolrDocument = getHoldingsRecord((String) object);
387 if (holdingsSolrDocument != null) {
388 String fieldValue = searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) : searchResultField.getFieldName();
389 String resultFieldValue = getSolrFieldValue(holdingsSolrDocument, fieldValue);
390 if (StringUtils.isNotBlank(resultFieldValue)) {
391 newSearchResultField.setFieldValue(resultFieldValue);
392 }
393 newSearchResultField.setDocType(searchResultField.getDocType());
394 newSearchResultField.setFieldName(searchResultField.getFieldName());
395
396 newSearchResultFields.add(newSearchResultField);
397 }
398 } else {
399 if (((List) object) != null) {
400 for (Object identifier : (List) object) {
401 SearchResultField newSearchResultField = new SearchResultField();
402 SolrDocument holdingsSolrDocument = getHoldingsRecord((String) identifier);
403 if (holdingsSolrDocument != null) {
404 String fieldValue = searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) : searchResultField.getFieldName();
405 String resultFieldValue = getSolrFieldValue(holdingsSolrDocument, fieldValue);
406 if (StringUtils.isNotBlank(resultFieldValue)) {
407 newSearchResultField.setFieldValue(resultFieldValue);
408 }
409 newSearchResultField.setDocType(searchResultField.getDocType());
410 newSearchResultField.setFieldName(searchResultField.getFieldName());
411
412 newSearchResultFields.add(newSearchResultField);
413 }
414 }
415 }
416 }
417 return newSearchResultFields;
418 }
419
420 private String getSolrFieldValue(SolrDocument solrDocument, String fieldValue) {
421 Object obj = solrDocument.getFieldValue(fieldValue);
422 String resultFieldValue = null;
423 if (obj instanceof String) {
424 resultFieldValue = (String) obj;
425 } else if (obj instanceof Boolean) {
426 resultFieldValue = String.valueOf(obj);
427 } else {
428 if (((List) obj) != null) {
429 resultFieldValue = (String) ((List) obj).get(0);
430 }
431 }
432 return resultFieldValue;
433 }
434
435 private List<SearchResultField> getDefaultSearchResultFields(SearchParams searchParams) {
436 String docType = null;
437 if (!CollectionUtils.isEmpty(searchParams.getSearchConditions())) {
438 docType = searchParams.getSearchConditions().get(0).getSearchField().getDocType();
439 }
440 List<SearchResultField> searchResultFields = new ArrayList<>();
441 if (StringUtils.isBlank(docType)) {
442 String allFields = BIB_FIELDS + "," + HOLDINGS_FIELDS + "," + ITEM_FIELDS;
443 for (String defaultField : getDefaultFields(allFields)) {
444 SearchResultField searchResultField = new SearchResultField();
445 searchResultField.setDocType(docType);
446 searchResultField.setFieldName(defaultField);
447 searchResultFields.add(searchResultField);
448 }
449 } else if (docType.equalsIgnoreCase(BIBLIOGRAPHIC)) {
450 for (String bibField : getDefaultFields(BIB_FIELDS)) {
451 SearchResultField searchResultField = new SearchResultField();
452 searchResultField.setDocType(docType);
453 searchResultField.setFieldName(bibField);
454 searchResultFields.add(searchResultField);
455 }
456 } else if (docType.equalsIgnoreCase(HOLDINGS)) {
457 for (String holdingsField : getDefaultFields(HOLDINGS_FIELDS)) {
458 SearchResultField searchResultField = new SearchResultField();
459 searchResultField.setDocType(docType);
460 searchResultField.setFieldName(holdingsField);
461 searchResultFields.add(searchResultField);
462 }
463 } else if (docType.equalsIgnoreCase(ITEM)) {
464 for (String itemField : getDefaultFields(ITEM_FIELDS)) {
465 SearchResultField searchResultField = new SearchResultField();
466 searchResultField.setDocType(docType);
467 searchResultField.setFieldName(itemField);
468 searchResultFields.add(searchResultField);
469 }
470 } else if (docType.equalsIgnoreCase(EHOLDINGS)) {
471 for (String itemField : getDefaultFields(EHOLDINGS_FIELDS)) {
472 SearchResultField searchResultField = new SearchResultField();
473 searchResultField.setDocType(docType);
474 searchResultField.setFieldName(itemField);
475 searchResultFields.add(searchResultField);
476 }
477 }
478 return searchResultFields;
479 }
480
481 private List<String> getDefaultFields(String bibFields) {
482 return Arrays.asList(bibFields.split(","));
483 }
484
485
486 public String buildQueryWithSearchParams(SearchParams searchParams) {
487 return buildQueryWithSearchConditions(searchParams.getSearchConditions()) + buildQueryWithSortConditions(searchParams.getSortConditions());
488 }
489
490 private SolrDocument getItemRecord(String itemIdentifier) {
491 try {
492 SolrDocument itemSolrDocument = null;
493 SearchParams searchParams = new SearchParams();
494 SearchField searchField = searchParams.buildSearchField("item", "itemIdentifier", itemIdentifier);
495 searchParams.getSearchConditions().add(searchParams.buildSearchCondition("none", searchField, null));
496 SolrQuery solrQuery = new SolrQuery();
497 SolrServer server = SolrServerManager.getInstance().getSolrServer();
498 solrQuery.setQuery(buildQueryWithSearchConditions(searchParams.getSearchConditions()));
499 QueryResponse response = server.query(solrQuery);
500 if (response.getResults().size() > 0) {
501 itemSolrDocument = response.getResults().get(0);
502 }
503 return itemSolrDocument;
504 } catch (SolrServerException ex) {
505 LOG.info("Exception :", ex);
506 throw new DocstoreIndexException(ex.getMessage());
507 }
508 }
509
510 private SolrDocument getBibRecord(String bibIdentifier) {
511 try {
512 SolrDocument bibSolrDocument = null;
513 SearchParams searchParams = new SearchParams();
514 SearchField searchField = searchParams.buildSearchField("bibliographic", "bibIdentifier", bibIdentifier);
515 searchParams.getSearchConditions().add(searchParams.buildSearchCondition("none", searchField, null));
516 SolrQuery solrQuery = new SolrQuery();
517 SolrServer server = SolrServerManager.getInstance().getSolrServer();
518 solrQuery.setQuery(buildQueryWithSearchConditions(searchParams.getSearchConditions()));
519 QueryResponse response = server.query(solrQuery);
520 if (response.getResults().size() > 0) {
521 bibSolrDocument = response.getResults().get(0);
522 }
523 return bibSolrDocument;
524 } catch (SolrServerException ex) {
525 LOG.info("Exception :", ex);
526 throw new DocstoreIndexException(ex.getMessage());
527 }
528 }
529
530 private SolrDocument getHoldingsRecord(String holdingsIdentifier) {
531 try {
532 SolrDocument holdingsSolrDocument = null;
533 SearchParams searchParams = new SearchParams();
534 SearchField searchField = searchParams.buildSearchField("holdings", "holdingsIdentifier", holdingsIdentifier);
535 searchParams.getSearchConditions().add(searchParams.buildSearchCondition("none", searchField, null));
536 SolrQuery solrQuery = new SolrQuery();
537 SolrServer server = SolrServerManager.getInstance().getSolrServer();
538 solrQuery.setQuery(buildQueryWithSearchConditions(searchParams.getSearchConditions()));
539 QueryResponse response = server.query(solrQuery);
540 if (response.getResults().size() > 0) {
541 holdingsSolrDocument = response.getResults().get(0);
542 }
543 return holdingsSolrDocument;
544 } catch (SolrServerException ex) {
545 LOG.info("Exception :", ex);
546 throw new DocstoreIndexException(ex.getMessage());
547 }
548 }
549
550 private String buildQueryWithResultFieldsLists(SearchParams searchParams) {
551 String docType = null;
552 List<SearchResultField> searchResultFields = searchParams.getSearchResultFields();
553 if (!CollectionUtils.isEmpty(searchParams.getSearchConditions())) {
554 docType = searchParams.getSearchConditions().get(0).getSearchField().getDocType();
555 }
556 StringBuffer resultFieldsBuffer = new StringBuffer();
557
558
559 if (StringUtils.isBlank(docType)) {
560 if (!CollectionUtils.isEmpty(searchResultFields)) {
561 for (int i = 0; i < searchResultFields.size(); i++) {
562 resultFieldsBuffer.append(searchResultFieldsMap.get(searchResultFields.get(i).getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultFields.get(i).getFieldName().toUpperCase()) : searchResultFields.get(i).getFieldName());
563 if (i != searchResultFields.size() - 1) {
564 resultFieldsBuffer.append(",");
565 }
566 }
567 }
568
569
570 } else if (docType.equalsIgnoreCase(BIBLIOGRAPHIC)) {
571 if (!CollectionUtils.isEmpty(searchResultFields)) {
572 for (int i = 0; i < searchResultFields.size(); i++) {
573 if (searchResultFields.get(i).getDocType().equalsIgnoreCase(BIBLIOGRAPHIC)) {
574 resultFieldsBuffer.append(searchResultFieldsMap.get(searchResultFields.get(i).getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultFields.get(i).getFieldName().toUpperCase()) : searchResultFields.get(i).getFieldName());
575 resultFieldsBuffer.append(",");
576 }
577 }
578 resultFieldsBuffer.append(BIB_LINK_FIELDS);
579 }
580
581
582 } else if (docType.equalsIgnoreCase(HOLDINGS)) {
583 if (!CollectionUtils.isEmpty(searchResultFields)) {
584 for (int i = 0; i < searchResultFields.size(); i++) {
585 if (searchResultFields.get(i).getDocType().equalsIgnoreCase(HOLDINGS)) {
586 resultFieldsBuffer.append(searchResultFieldsMap.get(searchResultFields.get(i).getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultFields.get(i).getFieldName().toUpperCase()) : searchResultFields.get(i).getFieldName());
587 resultFieldsBuffer.append(",");
588 }
589 }
590 resultFieldsBuffer.append(HOLDINGS_LINK_FIELDS);
591 }
592
593
594
595 } else if (docType.equalsIgnoreCase(ITEM)) {
596 if (!CollectionUtils.isEmpty(searchResultFields)) {
597 for (int i = 0; i < searchResultFields.size(); i++) {
598 if (searchResultFields.get(i).getDocType().equalsIgnoreCase(ITEM)) {
599 resultFieldsBuffer.append(searchResultFieldsMap.get(searchResultFields.get(i).getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultFields.get(i).getFieldName().toUpperCase()) : searchResultFields.get(i).getFieldName());
600 resultFieldsBuffer.append(",");
601 }
602 }
603 resultFieldsBuffer.append(ITEM_LINK_FIELDS);
604 }
605
606
607 } else if (docType.equalsIgnoreCase(EHOLDINGS)) {
608 if (!CollectionUtils.isEmpty(searchResultFields)) {
609 for (int i = 0; i < searchResultFields.size(); i++) {
610 if (searchResultFields.get(i).getDocType().equalsIgnoreCase(EHOLDINGS)) {
611 resultFieldsBuffer.append(searchResultFieldsMap.get(searchResultFields.get(i).getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultFields.get(i).getFieldName().toUpperCase()) : searchResultFields.get(i).getFieldName());
612 resultFieldsBuffer.append(",");
613 }
614 }
615 resultFieldsBuffer.append(EHOLDINGS_FIELDS);
616 }
617
618
619 }
620 return resultFieldsBuffer.toString();
621 }
622
623 private List<String> getIds(List<SolrDocument> solrDocumentList) {
624 List<String> ids = new ArrayList<>();
625 for (SolrDocument solrDocument : solrDocumentList) {
626 String docType = (String) solrDocument.getFieldValue("DocType");
627 if (docType.equalsIgnoreCase(DocType.BIB.getCode())) {
628 ids.add((String) solrDocument.getFieldValue("id"));
629 } else if (docType.equalsIgnoreCase(DocType.HOLDINGS.getCode())) {
630 ids.add((String) solrDocument.getFieldValue("id"));
631 } else if (docType.equalsIgnoreCase(DocType.ITEM.getCode())) {
632 ids.add((String) solrDocument.getFieldValue("id"));
633 }
634 }
635 return ids;
636 }
637
638 public String buildQueryWithSearchConditions(List<SearchCondition> searchConditions) {
639 boolean searchConditionCheck = false;
640 SearchCondition searchCondition = null;
641 String docType = null;
642 StringBuffer queryStringBuffer = new StringBuffer();
643 if (searchConditions != null && searchConditions.size() > 0) {
644 for (int i = 0; i < searchConditions.size(); i++) {
645 int searchScopeAddLimit = i;
646 searchCondition = searchConditions.get(i);
647 if (searchCondition.getSearchField() != null) {
648 if (StringUtils.isBlank(docType) && searchScopeAddLimit == 0) {
649 docType = searchCondition.getSearchField().getDocType();
650 if (StringUtils.isNotBlank(docType)) {
651 queryStringBuffer.append("(");
652 queryStringBuffer.append("DocType:" + docType);
653 queryStringBuffer.append(")");
654 }
655 }
656 String searchScope = searchCondition.getSearchScope();
657 String searchOperator = searchCondition.getOperator();
658 String searchText = searchCondition.getSearchField().getFieldValue();
659 if (StringUtils.isBlank(docType) || docType.equalsIgnoreCase(searchCondition.getSearchField().getDocType())) {
660 if (StringUtils.isNotBlank(searchCondition.getSearchField().getFieldName()) || StringUtils.isNotBlank(searchCondition.getSearchField().getFieldValue())) {
661 if (StringUtils.isNotBlank(docType) && searchScopeAddLimit == 0) {
662 queryStringBuffer.append("AND");
663 queryStringBuffer.append("(");
664 }
665 queryStringBuffer.append("(");
666 if (StringUtils.isNotBlank(searchCondition.getSearchField().getFieldName())) {
667 if (searchCondition.getSearchField().getFieldName().equalsIgnoreCase("all")) {
668 queryStringBuffer.append("all_text");
669 } else {
670 queryStringBuffer.append(searchFieldsMap.get(searchCondition.getSearchField().getFieldName().toUpperCase()) != null ? searchFieldsMap.get(searchCondition.getSearchField().getFieldName().toUpperCase()) : searchCondition.getSearchField().getFieldName());
671 }
672 queryStringBuffer.append(":");
673 }
674
675 if (StringUtils.isNotBlank(searchText)) {
676 String searchTextVal = getModifiedText(searchText);
677 if (searchText.length() > 0) {
678 queryStringBuffer.append("(");
679 if (StringUtils.isNotBlank(searchScope)) {
680 if (searchScope.equalsIgnoreCase("AND")) {
681 searchTextVal = searchTextVal.trim().replaceAll("\\s+", "+ AND +");
682 } else if (searchScope.equalsIgnoreCase("OR")) {
683 searchTextVal = searchTextVal.trim().replaceAll("\\s+", "+ OR +");
684 } else if (searchScope.equalsIgnoreCase("phrase")) {
685 searchTextVal = "\"" + searchText + "\"";
686 } else if (searchScope.equalsIgnoreCase("none")) {
687 searchTextVal = searchText;
688 }
689 }
690 queryStringBuffer.append(searchTextVal);
691 queryStringBuffer.append(")");
692 }
693 queryStringBuffer.append(")");
694 searchConditionCheck = true;
695 } else {
696 queryStringBuffer.append("(*:*)");
697 queryStringBuffer.append(")");
698 searchConditionCheck = true;
699 }
700 }
701 }
702 ++searchScopeAddLimit;
703 if (StringUtils.isBlank(searchOperator)) {
704 break;
705 }
706 if (searchScopeAddLimit != searchConditions.size()) {
707 if (StringUtils.isBlank(docType) || StringUtils.isNotBlank(docType) && docType.equalsIgnoreCase(searchConditions.get(searchScopeAddLimit).getSearchField().getDocType())) {
708 queryStringBuffer.append(searchOperator);
709 }
710 }
711 }
712 if (StringUtils.isBlank(docType) && StringUtils.isBlank(searchCondition.getSearchField().getFieldName()) && StringUtils.isBlank(searchCondition.getSearchField().getFieldValue())) {
713 queryStringBuffer.append("*:*");
714 }
715 }
716 } else {
717 queryStringBuffer.append("*:*");
718 }
719 if (searchConditionCheck && StringUtils.isNotBlank(docType)) {
720 queryStringBuffer.append(")");
721 }
722 return queryStringBuffer.toString();
723 }
724
725 private String getModifiedText(String searchText) {
726 StringBuffer modifiedText = new StringBuffer();
727 StringCharacterIterator stringCharacterIterator = new StringCharacterIterator(searchText);
728 char character = stringCharacterIterator.current();
729 while (character != CharacterIterator.DONE) {
730
731 if (character == '\\') {
732 modifiedText.append("\\\\");
733 } else if (character == '?') {
734 modifiedText.append("\\?");
735 } else if (character == '*' && StringUtils.isEmpty(modifiedText.toString())) {
736 modifiedText.append("\\*");
737 } else if (character == '+') {
738 modifiedText.append("\\+");
739 } else if (character == ':') {
740 modifiedText.append("\\:");
741 } else if (character == '{') {
742 modifiedText.append("\\{");
743 } else if (character == '}') {
744 modifiedText.append("\\}");
745 } else if (character == '[') {
746 modifiedText.append("\\[");
747 } else if (character == ']') {
748 modifiedText.append("\\]");
749 } else if (character == '(') {
750 modifiedText.append("\\(");
751 } else if (character == ')') {
752 modifiedText.append("\\)");
753 } else if (character == '^') {
754 modifiedText.append("\\^");
755 } else if (character == '~') {
756 modifiedText.append("\\~");
757 } else if (character == '-') {
758 modifiedText.append("\\-");
759 } else if (character == '!') {
760 modifiedText.append("\\!");
761 } else if (character == '\'') {
762 modifiedText.append("\\'");
763 } else if (character == '@') {
764 modifiedText.append("\\@");
765 } else if (character == '#') {
766 modifiedText.append("\\#");
767 } else if (character == '$') {
768 modifiedText.append("\\$");
769 } else if (character == '%') {
770 modifiedText.append("\\%");
771 } else {
772
773
774 modifiedText.append(character);
775 }
776 character = stringCharacterIterator.next();
777 }
778 return modifiedText.toString().toLowerCase();
779 }
780
781 public String buildQueryWithSortConditions(List<SortCondition> sortConditions) {
782 StringBuffer sortFieldsQuery = new StringBuffer();
783 for (SortCondition sortCondition : sortConditions) {
784 String sortField = sortCondition.getSortField();
785 String sortOrder = sortCondition.getSortOrder();
786 if (StringUtils.isNotBlank(sortField) && StringUtils.isNotBlank(getSolrSortField(sortField.toUpperCase())) && StringUtils.isNotBlank(sortOrder)) {
787 sortFieldsQuery.append("&");
788 sortFieldsQuery.append("sort=");
789 sortFieldsQuery.append(getSolrSortField(sortField.toUpperCase()));
790 sortFieldsQuery.append(" ");
791 sortFieldsQuery.append(sortOrder);
792 }
793 }
794 return sortFieldsQuery.toString();
795 }
796
797 private String getSolrSortField(String sortField) {
798
799 if ("TITLE".equals(sortField)) {
800 return "Title_sort";
801 } else if ("AUTHOR".equals(sortField)) {
802 return "Author_sort";
803 } else if ("PUBLICATION DATE".equals(sortField)) {
804 return "PublicationDate_sort";
805 } else if ("LOCATION".equals(sortField)) {
806 return "LocationLevel_sort";
807 } else if ("CALL NUMBER".equals(sortField)) {
808 return "CallNumber_sort";
809 }
810 return null;
811 }
812
813 @Override
814 public List<String> callNumberBrowse(BrowseParams browseParams) {
815 try {
816 SolrQuery solrQuery = new SolrQuery();
817 SolrServer server = SolrServerManager.getInstance().getSolrServer();
818 solrQuery.setQuery(buildQueryWithSearchParams(browseParams));
819 QueryResponse response = server.query(solrQuery);
820 browseParams.setTotalCount(response.getResults().getNumFound());
821 return getIds(response.getResults());
822 } catch (SolrServerException ex) {
823 LOG.info("Exception :", ex);
824 throw new DocstoreIndexException(ex.getMessage());
825 }
826 }
827
828 @Override
829 public String findBib(Map<String, String> map) {
830 List<String> bibIds = new ArrayList<>();
831 SearchParams searchParams = buildSearchParamsFromMap(map);
832 SearchResponse searchResponse = search(searchParams);
833 for (SearchResult searchResult : searchResponse.getSearchResults()) {
834 for (SearchResultField searchResultField : searchResult.getSearchResultFields()) {
835 bibIds.add(searchResultField.getFieldValue());
836 }
837 }
838 if (!CollectionUtils.isEmpty(bibIds)) {
839 return bibIds.get(0);
840 }
841 return null;
842 }
843
844 private SearchParams buildSearchParamsFromMap(Map<String, String> map) {
845 SearchParams searchParams = new SearchParams();
846 Set<String> keys = map.keySet();
847 for (String key : keys) {
848 if (!BibConstants.DOC_TYPE.equalsIgnoreCase(key)) {
849 SearchCondition searchCondition = new SearchCondition();
850 SearchField searchField = searchParams.buildSearchField(map.get(BibConstants.DOC_TYPE), searchFieldsMap.get(key), map.get(key));
851 searchCondition.setSearchField(searchField);
852 searchParams.getSearchConditions().add(searchCondition);
853 }
854 }
855 searchParams.getSearchResultFields().add(searchParams.buildSearchResultField(map.get(BibConstants.DOC_TYPE), "id"));
856 return searchParams;
857 }
858
859 @Override
860 public String findHoldings(Map<String, String> map) {
861 List<String> holdingIds = new ArrayList<>();
862 map.put(BibConstants.DOC_TYPE, "holdings");
863 SearchParams searchParams = buildSearchParamsFromMap(map);
864 SearchResponse searchResponse = search(searchParams);
865 for (SearchResult searchResult : searchResponse.getSearchResults()) {
866 for (SearchResultField searchResultField : searchResult.getSearchResultFields()) {
867 holdingIds.add(searchResultField.getFieldValue());
868 }
869 }
870 if (!CollectionUtils.isEmpty(holdingIds)) {
871 return holdingIds.get(0);
872 }
873 return null;
874 }
875
876 @Override
877 public String findItem(Map<String, String> map) {
878 List<String> itemIds = new ArrayList<>();
879 map.put(BibConstants.DOC_TYPE, "item");
880 SearchParams searchParams = buildSearchParamsFromMap(map);
881 SearchResponse searchResponse = search(searchParams);
882 for (SearchResult searchResult : searchResponse.getSearchResults()) {
883 for (SearchResultField searchResultField : searchResult.getSearchResultFields()) {
884 itemIds.add(searchResultField.getFieldValue());
885 }
886 }
887 if (!CollectionUtils.isEmpty(itemIds)) {
888 return itemIds.get(0);
889 }
890 return null;
891 }
892
893 @Override
894 public String findHoldingsTree(Map<String, String> map) {
895 return findHoldings(map);
896 }
897
898 @Override
899 public String findBibTree(Map<String, String> map) {
900 return findBib(map);
901 }
902
903 }