View Javadoc

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   * Created with IntelliJ IDEA.
29   * User: sambasivam
30   * Date: 12/13/13
31   * Time: 6:42 PM
32   * To change this template use File | Settings | File Templates.
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             //SolrDocument holdingsSolrDocument = null;
140             //SolrDocument itemSolrDocument = null;
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                 //newSearchResultField.setFieldValue(searchResultField.getFieldValue());
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                 //newSearchResultField.setFieldValue(searchResultField.getFieldValue());
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                         //newSearchResultField.setFieldValue(searchResultField.getFieldValue());
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             //newSearchResultField.setFieldValue(searchResultField.getFieldValue());
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                     //newSearchResultField.setFieldValue(searchResultField.getFieldValue());
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                     //newSearchResultField.setFieldValue(searchResultField.getFieldValue());
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                             //newSearchResultField1.setFieldValue(searchResultField.getFieldValue());
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                 //newSearchResultField.setFieldValue(searchResultField.getFieldValue());
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                         //newSearchResultField.setFieldValue(searchResultField.getFieldValue());
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         //resultFieldsBuffer.append("&");
558         //resultFieldsBuffer.append("fl=");
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             } /*else {
568                 resultFieldsBuffer.append(BIB_FIELDS + "," + HOLDINGS_FIELDS + "," + ITEM_FIELDS);
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             } /*else {
580                 resultFieldsBuffer.append(BIB_FIELDS);
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             } /*else {
592                 resultFieldsBuffer.append(HOLDINGS_FIELDS);
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             } /*else {
605                 resultFieldsBuffer.append(ITEM_FIELDS);
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             } /*else {
617                 resultFieldsBuffer.append(ITEM_FIELDS);
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                 // the char is not a special one
773                 // add it to the result as is
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 }