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.SolrRequest;
5   import org.apache.solr.client.solrj.SolrServer;
6   import org.apache.solr.client.solrj.SolrServerException;
7   import org.apache.solr.client.solrj.response.*;
8   import org.apache.solr.common.SolrDocument;
9   import org.apache.solr.common.SolrDocumentList;
10  import org.kuali.ole.DocumentUniqueIDPrefix;
11  import org.kuali.ole.docstore.common.document.*;
12  import org.kuali.ole.docstore.common.exception.DocstoreIndexException;
13  import org.kuali.ole.docstore.common.search.*;
14  import org.kuali.ole.docstore.common.search.FacetResultField;
15  import org.kuali.ole.docstore.discovery.service.SolrServerManager;
16  import org.kuali.ole.docstore.engine.service.index.solr.BibConstants;
17  import org.kuali.ole.docstore.model.enums.DocType;
18  import org.slf4j.Logger;
19  import org.slf4j.LoggerFactory;
20  import org.apache.solr.client.solrj.SolrQuery;
21  import org.springframework.util.CollectionUtils;
22  
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  
39      private static Map<String, String> searchResultFieldsMap = new HashMap<>();
40  
41      private static Map<String, String> searchFieldsMap = new HashMap<>();
42      private static Map<String, String> joinQueryMap = new HashMap<>();
43      private static final String BIB_HOLDINGS = "bibliographicholdings";
44      private static final String BIB_EHOLDINGS = "bibliographiceHoldings";
45      private static final String BIB_ITEM="bibliographicitem";
46      private static final String HOLDINGS_BIB = "holdingsbibliographic";
47      private static final String EHOLDINGS_BIB = "eHoldingsbibliographic";
48      private static final String HOLDINGS_ITEM = "holdingsitem";
49      private static final String ITEM_HOLDINGS = "itemholdings";
50      private static final String ITEM_BIB = "itembibliographic";
51      static {
52          searchFieldsMap.put(Bib.ID, "id");
53          searchFieldsMap.put(Bib.AUTHOR, "Author_search");
54          searchFieldsMap.put(Bib.TITLE, "Title_search");
55          searchFieldsMap.put(Bib.PUBLICATIONDATE, "PublicationDate_search");
56          searchFieldsMap.put(Bib.PUBLISHER, "Publisher_search");
57          searchFieldsMap.put(Bib.ISBN, "ISBN_search");
58          searchFieldsMap.put(Bib.ISSN, "ISSN_search");
59          searchFieldsMap.put(Bib.SUBJECT, "Subject_search");
60          searchFieldsMap.put(Bib.EDITION, "Edition_search");
61          searchFieldsMap.put(Bib.DESCRIPTION, "Description_search");
62          searchFieldsMap.put(Bib.FORMAT, "Format_search");
63          searchFieldsMap.put(Bib.LANGUAGE, "Language_search");
64          searchFieldsMap.put(Bib.BIBIDENTIFIER, "bibIdentifier");
65          searchFieldsMap.put(Holdings.HOLDINGSIDENTIFIER, "holdingsIdentifier");
66          searchFieldsMap.put(Holdings.LOCATION_NAME, "Location_search");
67          searchFieldsMap.put(Holdings.LOCATION_LEVEL1, "Location_search");
68          searchFieldsMap.put(Holdings.LOCATION_LEVEL2, "Location_search");
69          searchFieldsMap.put(Holdings.LOCATION_LEVEL3, "Location_search");
70          searchFieldsMap.put(Holdings.LOCATION_LEVEL4, "Location_search");
71          searchFieldsMap.put(Holdings.LOCATION_LEVEL5, "Location_search");
72          searchFieldsMap.put(Holdings.CALL_NUMBER, "CallNumber_search");
73          searchFieldsMap.put(Holdings.CALLNUMBER_PREFIX, "CallNumberPrefix_search");
74          searchFieldsMap.put(Holdings.CALLNUMBER_TYPE, "CallNumberType_search");
75          searchFieldsMap.put(Holdings.COPY_NUMBER, "CopyNumber_search");
76          searchFieldsMap.put(Item.ITEMIDENTIFIER, "ItemIdentifier_search");
77          searchFieldsMap.put(Item.SHELVING_ORDER, "ShelvingOrder_search");
78          searchFieldsMap.put(Item.ITEM_BARCODE, "ItemBarcode_search");
79          searchFieldsMap.put(Item.ENUMERATION, "Enumeration_search");
80          searchFieldsMap.put(Item.CHRONOLOGY, "Chronology_search");
81          searchFieldsMap.put(Item.ITEM_TYPE, "ItemTypeCodeValue_search");
82          searchFieldsMap.put(Item.VOLUME_NUMBER, "VolumeNumber_search");
83          searchFieldsMap.put(Item.ITEM_STATUS, "ItemStatus_search");
84          searchFieldsMap.put(Item.ITEMIDENTIFIER, "ItemIdentifier_search");
85          searchFieldsMap.put(Item.DONOR_CODE, "DonorCode_search");
86          searchFieldsMap.put(Item.DONOR_NOTE, "DonorNote_display");
87          searchFieldsMap.put(Item.DONOR_PUBLIC, "DonorPublic_display");
88          searchFieldsMap.put(Item.HOLDINGS_CALL_NUMBER, "HoldingsCallNumber_search");
89          searchFieldsMap.put(Item.HOLDINGS_CALL_NUMBER_PREFIX, "CallNumberPrefix_search");
90          searchFieldsMap.put(Item.HOLDINGS_CALL_NUMBER_TYPE, "CallNumberType_search");
91          searchFieldsMap.put(Item.HOLDINGS_COPY_NUMBER, "HoldingsCopyNumber_search");
92          searchFieldsMap.put(Item.HOLDINGS_LOCATION_LEVEL1, "HoldingsLocation_search");
93          searchFieldsMap.put(Item.HOLDINGS_LOCATION_LEVEL2, "HoldingsLocation_search");
94          searchFieldsMap.put(Item.HOLDINGS_LOCATION_LEVEL3, "HoldingsLocation_search");
95          searchFieldsMap.put(Item.HOLDINGS_LOCATION_LEVEL4, "HoldingsLocation_search");
96          searchFieldsMap.put(Item.HOLDINGS_LOCATION_LEVEL5, "HoldingsLocation_search");
97          searchFieldsMap.put(Item.VENDOR_LINE_ITEM_IDENTIFIER, "VendorLineItemIdentifier_search");
98          searchFieldsMap.put(EHoldings.ACCESS_STATUS, "AccessStatus_search");
99          searchFieldsMap.put(EHoldings.URL, "URL_search");
100         searchFieldsMap.put(EHoldings.PERSISTENT_LINK, "Persist_Link_search");
101         searchFieldsMap.put(EHoldings.LINK_TEXT, "Link_Text_search");
102         searchFieldsMap.put(EHoldings.PUBLIC_DISPLAY_NOTE, "Public_Note_display");
103         searchFieldsMap.put(EHoldings.COVERAGE_START_DATE, "CoverageDate_display");
104         searchFieldsMap.put(EHoldings.COVERAGE_END_DATE, "CoverageDate_display");
105         searchFieldsMap.put(EHoldings.STATISTICAL_CODE, "StatisticalSearchingCodeValue_display");
106         searchFieldsMap.put(EHoldings.PLATFORM, "Platform_display");
107 
108         searchResultFieldsMap.put(Bib.ID, "id");
109         searchResultFieldsMap.put(Bib.AUTHOR, "Author_display");
110         searchResultFieldsMap.put(Bib.TITLE, "Title_display");
111         searchResultFieldsMap.put(Bib.PUBLICATIONDATE, "PublicationDate_display");
112         searchResultFieldsMap.put(Bib.PUBLISHER, "Publisher_display");
113         searchResultFieldsMap.put(Bib.ISBN, "ISBN_display");
114         searchResultFieldsMap.put(Bib.ISSN, "ISSN_display");
115         searchResultFieldsMap.put(Bib.SUBJECT, "Subject_display");
116         searchResultFieldsMap.put(Bib.EDITION, "Edition_display");
117         searchResultFieldsMap.put(Bib.DESCRIPTION, "Description_display");
118         searchResultFieldsMap.put(Bib.FORMAT, "Format_display");
119         searchResultFieldsMap.put(Bib.LANGUAGE, "Language_display");
120         searchResultFieldsMap.put(Bib.BIBIDENTIFIER, "bibIdentifier");
121         searchResultFieldsMap.put(Holdings.HOLDINGSIDENTIFIER, "holdingsIdentifier");
122         searchResultFieldsMap.put(Holdings.LOCATION_NAME, "Location_display");
123         searchResultFieldsMap.put(Holdings.LOCATION_LEVEL1, "Location_display");
124         searchResultFieldsMap.put(Holdings.LOCATION_LEVEL2, "Location_display");
125         searchResultFieldsMap.put(Holdings.LOCATION_LEVEL3, "Location_display");
126         searchResultFieldsMap.put(Holdings.LOCATION_LEVEL4, "Location_display");
127         searchResultFieldsMap.put(Holdings.LOCATION_LEVEL5, "Location_display");
128         searchResultFieldsMap.put(Holdings.CALL_NUMBER, "CallNumber_display");
129         searchResultFieldsMap.put(Holdings.CALLNUMBER_PREFIX, "CallNumberPrefix_display");
130         searchResultFieldsMap.put(Holdings.CALLNUMBER_TYPE, "CallNumberType_display");
131         searchResultFieldsMap.put(Holdings.COPY_NUMBER, "CopyNumber_display");
132         searchResultFieldsMap.put(Item.ITEMIDENTIFIER, "itemIdentifier");
133         searchResultFieldsMap.put(Item.SHELVING_ORDER, "ShelvingOrder_display");
134         searchResultFieldsMap.put(Item.ITEM_BARCODE, "ItemBarcode_display");
135         searchResultFieldsMap.put(Item.ENUMERATION, "Enumeration_display");
136         searchResultFieldsMap.put(Item.CHRONOLOGY, "Chronology_display");
137         searchResultFieldsMap.put(Item.ITEM_TYPE, "ItemTypeCodeValue_display");
138         searchResultFieldsMap.put(Item.VOLUME_NUMBER, "VolumeNumber_display");
139         searchResultFieldsMap.put(Item.ITEM_STATUS, "ItemStatus_display");
140         searchResultFieldsMap.put(Item.DONOR_CODE, "DonorCode_display");
141         searchResultFieldsMap.put(Item.DONOR_NOTE, "DonorNote_display");
142         searchResultFieldsMap.put(Item.DONOR_PUBLIC, "DonorPublic_display");
143         searchResultFieldsMap.put(Item.HOLDINGS_CALL_NUMBER, "HoldingsCallNumber_display");
144         searchResultFieldsMap.put(Item.HOLDINGS_CALL_NUMBER_PREFIX, "CallNumberPrefix_display");
145         searchResultFieldsMap.put(Item.HOLDINGS_CALL_NUMBER_TYPE, "CallNumberType_display");
146         searchResultFieldsMap.put(Item.HOLDINGS_COPY_NUMBER, "HoldingsCopyNumber_display");
147         searchResultFieldsMap.put(Item.HOLDINGS_LOCATION_LEVEL1, "HoldingsLocation_display");
148         searchResultFieldsMap.put(Item.HOLDINGS_LOCATION_LEVEL2, "HoldingsLocation_display");
149         searchResultFieldsMap.put(Item.HOLDINGS_LOCATION_LEVEL3, "HoldingsLocation_display");
150         searchResultFieldsMap.put(Item.HOLDINGS_LOCATION_LEVEL4, "HoldingsLocation_display");
151         searchResultFieldsMap.put(Item.HOLDINGS_LOCATION_LEVEL5, "HoldingsLocation_display");
152         searchResultFieldsMap.put(Item.VENDOR_LINE_ITEM_IDENTIFIER, "VendorLineItemIdentifier_display");
153         searchResultFieldsMap.put(EHoldings.ACCESS_STATUS, "AccessStatus_display");
154         searchResultFieldsMap.put(EHoldings.URL, "URL_display");
155         searchResultFieldsMap.put(EHoldings.PERSISTENT_LINK, "Persist_Link_display");
156         searchResultFieldsMap.put(EHoldings.LINK_TEXT, "Link_Text_display");
157         searchResultFieldsMap.put(EHoldings.PUBLIC_DISPLAY_NOTE, "Public_Note_display");
158         searchResultFieldsMap.put(EHoldings.PUBLIC_DISPLAY_NOTE, "CoverageDate_display");
159         searchResultFieldsMap.put(EHoldings.STATISTICAL_CODE, "StatisticalSearchingCodeValue_display");
160         searchResultFieldsMap.put(EHoldings.PLATFORM, "Platform_display");
161         searchResultFieldsMap.put(Bib.BIBIDENTIFIER, "bibIdentifier");
162         searchResultFieldsMap.put(Holdings.HOLDINGSIDENTIFIER, "holdingsIdentifier");
163         searchResultFieldsMap.put(Item.ITEMIDENTIFIER, "itemIdentifier");
164         searchResultFieldsMap.put(Item.DUE_DATE_TIME, "dueDateTime");
165 
166         joinQueryMap.put(BIB_HOLDINGS, "{!join from=id to=holdingsIdentifier}");
167         joinQueryMap.put(HOLDINGS_BIB, "{!join from=id to=bibIdentifier}");
168         joinQueryMap.put(BIB_EHOLDINGS, "{!join from=id to=holdingsIdentifier}");
169         joinQueryMap.put(EHOLDINGS_BIB, "{!join from=id to=bibIdentifier}");
170         joinQueryMap.put(HOLDINGS_ITEM, "{!join from=id to=itemIdentifier}");
171         joinQueryMap.put(ITEM_BIB, "{!join from=id to=bibIdentifier}");
172         joinQueryMap.put(ITEM_HOLDINGS, "{!join from=id to=holdingsIdentifier}");
173         joinQueryMap.put(BIB_ITEM, "{!join from=id to=itemIdentifier}");
174     }
175 
176     @Override
177     public SearchResponse search(SearchParams searchParams) {
178         try {
179             SolrQuery solrQuery = new SolrQuery();
180             SolrServer server = SolrServerManager.getInstance().getSolrServer();
181             buildQueryWithSearchConditions(searchParams,solrQuery);
182             if (!CollectionUtils.isEmpty(searchParams.getSortConditions())) {
183                 buildQueryWithSortConditions(solrQuery, searchParams.getSortConditions());
184             }
185             if (searchParams.getPageSize() != 0) {
186                 solrQuery.setRows(searchParams.getPageSize());
187             }
188             solrQuery.setStart(searchParams.getStartIndex());
189             if (!CollectionUtils.isEmpty(searchParams.getSearchResultFields())) {
190                 solrQuery.setFields(buildQueryWithResultFieldsLists(searchParams));
191             }
192             if (!CollectionUtils.isEmpty(searchParams.getFacetFields())) {
193                 for(String facetField : searchParams.getFacetFields()) {
194                     solrQuery.addFacetField(facetField);
195                 }
196                 solrQuery.setFacet(true);
197                 if(StringUtils.isNotEmpty(searchParams.getFacetPrefix())) {
198                     if(!searchParams.getFacetPrefix().equalsIgnoreCase("all")) {
199                         solrQuery.setFacetPrefix(searchParams.getFacetPrefix().toLowerCase());
200                     }
201                 }
202 //                else {
203                     solrQuery.setFacetLimit(searchParams.getFacetLimit());
204 //                }
205                 solrQuery.setFacetMinCount(1);
206                 solrQuery.setFacetSort(searchParams.getFacetSort());
207                 solrQuery.set("facet.offset", searchParams.getFacetOffset());
208             }
209 
210             if (!CollectionUtils.isEmpty(searchParams.getFacetConditions())) {
211                buildQueryWithFacetConditions(solrQuery, searchParams.getFacetConditions());
212             }
213             LOG.info("Executing solr query :" +solrQuery.toString());
214             QueryResponse response = server.query(solrQuery, SolrRequest.METHOD.POST);
215             return buildSearchResponse(response, searchParams);
216         } catch (SolrServerException ex) {
217             LOG.info("Exception :", ex);
218             throw new DocstoreIndexException(ex.getMessage());
219         }
220     }
221 
222     private void buildQueryWithFacetConditions(SolrQuery solrQuery, List<FacetCondition> facetConditions) {
223 
224         StringBuffer facetTerms = new StringBuffer();
225         StringBuffer filterQuery = new StringBuffer();
226         int facetConditionsSize = facetConditions.size();
227         for (int i=0; i < facetConditionsSize; i++) {
228             FacetCondition facetCondition = facetConditions.get(i);
229             if(StringUtils.isNotEmpty(facetCondition.getFieldValue())) {
230                 facetTerms.append(facetCondition.getFieldValue());
231                 if(i != (facetConditionsSize-1)) {
232                     facetTerms.append("|");
233                 }
234             }
235             if(StringUtils.isNotEmpty(facetCondition.getFieldValue())) {
236                 filterQuery.append(facetCondition.getFieldName());
237                 filterQuery.append(":");
238                 filterQuery.append("\"" + facetCondition.getFieldValue() + "\"");
239 
240                 if(i != (facetConditionsSize-1)) {
241                     filterQuery.append(" AND ");
242                 }
243             }
244         }
245 
246         solrQuery.setTermsRegex(facetTerms.toString());
247         solrQuery.setFilterQueries(filterQuery.toString());
248     }
249 
250 
251     private SearchResponse buildSearchResponse(QueryResponse response, SearchParams searchParams) {
252         SolrDocumentList results = response.getResults();
253         List<org.apache.solr.client.solrj.response.FacetField> facetFields = response.getFacetFields();
254         String searchConditionDocType = searchParams.getDocType();
255         SearchResponse searchResponse = new SearchResponse();
256         List<SearchResult> searchResults = new ArrayList<>();
257         if (StringUtils.isEmpty(searchConditionDocType) && !CollectionUtils.isEmpty(searchParams.getSearchConditions())) {
258             for(SearchCondition searchCondition:searchParams.getSearchConditions()){
259                 if(searchCondition.getSearchField()!=null){
260                     searchConditionDocType = searchCondition.getSearchField().getDocType();
261                     break;
262                 }
263             }
264         }
265         List<SearchResultField> searchResultFields = new ArrayList<SearchResultField>();
266         if (CollectionUtils.isEmpty(searchParams.getSearchResultFields())) {
267             searchResultFields = getDefaultSearchResultFields(searchParams);
268         } else {
269             searchResultFields = searchParams.getSearchResultFields();
270         }
271         for (SolrDocument solrDocument : results) {
272             SolrDocument bibSolrDocument = null;
273             //SolrDocument holdingsSolrDocument = null;
274             //SolrDocument itemSolrDocument = null;
275             SearchResult searchResult = new SearchResult();
276             List<SearchResultField> newSearchResultFields = new ArrayList<SearchResultField>();
277             for (SearchResultField searchResultField : searchResultFields) {
278                 SearchResultField newSearchResultField = new SearchResultField();
279                 if (StringUtils.isBlank(searchConditionDocType) || searchResultField.getDocType().equalsIgnoreCase(searchConditionDocType)) {
280                     String fieldValue = searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) : searchResultField.getFieldName();
281                     if (fieldValue.equalsIgnoreCase("id") || fieldValue.equalsIgnoreCase("bibIdentifier")
282                             || fieldValue.equalsIgnoreCase("holdingsIdentifier")
283                             || fieldValue.equalsIgnoreCase("itemIdentifier")
284                             || fieldValue.equalsIgnoreCase("ItemIdentifier_display")
285                             || fieldValue.equalsIgnoreCase("DonorCode_search")
286                             || fieldValue.equalsIgnoreCase("DonorCode_display")
287                             || fieldValue.equalsIgnoreCase("ISBN_search")
288                             || fieldValue.equalsIgnoreCase("ISBN_display")
289                             || fieldValue.equalsIgnoreCase("ISSN_search")
290                             || fieldValue.equalsIgnoreCase("ISSN_display")) {
291                         newSearchResultFields.addAll(buildSearchResultsForIds(solrDocument, searchResultField));
292                         continue;
293                     }
294 
295                     String resultFieldValue = getSolrFieldValue(solrDocument, fieldValue);
296                     if (StringUtils.isNotBlank(resultFieldValue)) {
297                         newSearchResultField.setFieldValue(resultFieldValue);
298                     }
299                 } else {
300                     if (searchResultField.getDocType().equalsIgnoreCase(HOLDINGS)) {
301                         if (searchConditionDocType.equalsIgnoreCase(ITEM) || searchConditionDocType.equalsIgnoreCase(BIBLIOGRAPHIC)) {
302                             newSearchResultFields.addAll(buildHoldingsSearchResults(solrDocument, searchResultField));
303                             continue;
304                         }
305                     } else if (searchResultField.getDocType().equalsIgnoreCase(BIBLIOGRAPHIC)) {
306                         if (searchConditionDocType.equalsIgnoreCase(ITEM) || searchConditionDocType.equalsIgnoreCase(HOLDINGS) || searchConditionDocType.equalsIgnoreCase(EHOLDINGS) ) {
307                              newSearchResultFields.addAll(buildBibSearchResults(solrDocument, searchResultField));
308                             continue;
309                         }
310                     } else if (searchResultField.getDocType().equalsIgnoreCase(ITEM)) {
311                         if (searchConditionDocType.equalsIgnoreCase(HOLDINGS)) {
312                             newSearchResultFields.addAll(buildItemSearchResultsForHoldings(solrDocument, searchResultField));
313                             continue;
314                         } else if (searchConditionDocType.equalsIgnoreCase(BIBLIOGRAPHIC)) {
315                             newSearchResultFields.addAll(buildItemSearchResultsForBib(solrDocument, searchResultField));
316                             continue;
317                         }
318                     } else if (searchConditionDocType.equalsIgnoreCase(EHOLDINGS)) {
319                         if (bibSolrDocument == null) {
320                             bibSolrDocument = getBibRecord((String) solrDocument.getFieldValue("bibIdentifier"));
321                         }
322                         String fieldValue = searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) : searchResultField.getFieldName();
323                         String resultFieldValue = getSolrFieldValue(bibSolrDocument, fieldValue);
324                         if (StringUtils.isNotBlank(resultFieldValue)) {
325                             newSearchResultField.setFieldValue(resultFieldValue);
326                         }
327                     }
328                 }
329                 newSearchResultField.setDocType(searchResultField.getDocType());
330                 newSearchResultField.setFieldName(searchResultField.getFieldName());
331                 //newSearchResultField.setFieldValue(searchResultField.getFieldValue());
332                 newSearchResultFields.add(newSearchResultField);
333             }
334             searchResult.getSearchResultFields().addAll(newSearchResultFields);
335             searchResults.add(searchResult);
336         }
337         searchResponse.getSearchResults().addAll(searchResults);
338         searchResponse.setTotalRecordCount((int) results.getNumFound());
339         if (searchParams.getPageSize() == 0) {
340             searchResponse.setPageSize(results.size());
341         } else {
342             searchResponse.setPageSize(searchParams.getPageSize());
343         }
344         searchResponse.setStartIndex(searchParams.getStartIndex());
345         searchResponse.setEndIndex(searchParams.getStartIndex() + searchParams.getPageSize());
346         FacetResult facetResult = new FacetResult();
347         if (!CollectionUtils.isEmpty(facetFields)) {
348 
349             for (org.apache.solr.client.solrj.response.FacetField facetField : facetFields) {
350 
351 
352                 FacetResultField facetFieldResult = new FacetResultField();
353                 facetFieldResult.setFieldName(facetField.getName());
354 
355                 if(facetField.getValues() != null) {
356                     for (org.apache.solr.client.solrj.response.FacetField.Count count : facetField.getValues()) {
357                         String valCount = String.valueOf(count.getCount());
358                         if(!valCount.equalsIgnoreCase("0")) {
359 
360                             ValueCount valueCount = new ValueCount();
361                             String fullValue = count.getName();
362                             String value = "";
363                             if(fullValue.contains("/r/n!@#$")) {
364                                 int index = fullValue.indexOf("/r/n!@#$");
365                                 value = fullValue.substring(index + 8, fullValue.length());
366                             }
367                             else {
368                                 value = fullValue;
369                             }
370                             valueCount.setValue(value);
371                             valueCount.setFullValue(count.getName());
372                             valueCount.setCount(valCount);
373                             facetFieldResult.getValueCounts().add(valueCount);
374                         }
375                     }
376                 }
377 
378                 facetResult.getFacetResultFields().add(facetFieldResult);
379             }
380         }
381 
382         searchResponse.setFacetResult(facetResult);
383         searchResponse.setTime(response.getQTime());
384         return searchResponse;
385     }
386 
387     private List<SearchResultField> buildSearchResultsForIds(SolrDocument solrDocument, SearchResultField searchResultField) {
388         List<SearchResultField> newSearchResultFields = new ArrayList<SearchResultField>();
389         Object object = solrDocument.getFieldValue(searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) : searchResultField.getFieldName());
390         if (object instanceof String) {
391             SearchResultField newSearchResultField = new SearchResultField();
392             newSearchResultField.setDocType(searchResultField.getDocType());
393             newSearchResultField.setFieldName(searchResultField.getFieldName());
394             newSearchResultField.setFieldValue((String) object);
395             newSearchResultFields.add(newSearchResultField);
396         } else {
397             if (((List) object) != null) {
398                 for (Object identifier : (List) object) {
399                     SearchResultField newSearchResultField = new SearchResultField();
400                     newSearchResultField.setDocType(searchResultField.getDocType());
401                     newSearchResultField.setFieldName(searchResultField.getFieldName());
402                     newSearchResultField.setFieldValue((String) identifier);
403                     newSearchResultFields.add(newSearchResultField);
404                 }
405             }
406         }
407         return newSearchResultFields;
408     }
409 
410     private List<SearchResultField> buildBibSearchResults(SolrDocument solrDocument, SearchResultField searchResultField) {
411         List<SearchResultField> newSearchResultFields = new ArrayList<SearchResultField>();
412          Object object = solrDocument.getFieldValue("bibIdentifier");
413         if (object instanceof String) {
414              SearchResultField newSearchResultField = new SearchResultField();
415              SolrDocument bibSolrDocument = getBibRecord((String) object);
416             if (bibSolrDocument != null) {
417                 String fieldValue = searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) : searchResultField.getFieldName();
418                 String resultFieldValue = getSolrFieldValue(bibSolrDocument, fieldValue);
419                 if (StringUtils.isNotBlank(resultFieldValue)) {
420                     newSearchResultField.setFieldValue(resultFieldValue);
421                 }
422                 newSearchResultField.setDocType(searchResultField.getDocType());
423                 newSearchResultField.setFieldName(searchResultField.getFieldName());
424                 //newSearchResultField.setFieldValue(searchResultField.getFieldValue());
425                 newSearchResultFields.add(newSearchResultField);
426             }
427         } else {
428             if (((List) object) != null) {
429                 for (Object bibIdentifier : (List) object) {
430                     SearchResultField newSearchResultField = new SearchResultField();
431                     SolrDocument bibSolrDocument = getBibRecord((String) bibIdentifier);
432                     if (bibSolrDocument != null) {
433                         String fieldValue = searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) : searchResultField.getFieldName();
434                         String resultFieldValue = getSolrFieldValue(bibSolrDocument, fieldValue);
435                         if (StringUtils.isNotBlank(resultFieldValue)) {
436                             newSearchResultField.setFieldValue(resultFieldValue);
437                         }
438                         newSearchResultField.setDocType(searchResultField.getDocType());
439                         newSearchResultField.setFieldName(searchResultField.getFieldName());
440                         //newSearchResultField.setFieldValue(searchResultField.getFieldValue());
441                         newSearchResultFields.add(newSearchResultField);
442                     }
443                 }
444             }
445         }
446         return newSearchResultFields;
447     }
448 
449     private List<SearchResultField> buildItemSearchResultsForHoldings(SolrDocument solrDocument, SearchResultField searchResultField) {
450         List<SearchResultField> newSearchResultFields = new ArrayList<SearchResultField>();
451         Object object = solrDocument.getFieldValue("itemIdentifier");
452         if (object instanceof String) {
453             SearchResultField newSearchResultField = new SearchResultField();
454             SolrDocument itemSolrDocument = getItemRecord((String) object);
455             String fieldValue = searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) : searchResultField.getFieldName();
456             String resultFieldValue = getSolrFieldValue(itemSolrDocument, fieldValue);
457             if (StringUtils.isNotBlank(resultFieldValue)) {
458                 newSearchResultField.setFieldValue(resultFieldValue);
459             }
460             newSearchResultField.setDocType(searchResultField.getDocType());
461             newSearchResultField.setFieldName(searchResultField.getFieldName());
462             //newSearchResultField.setFieldValue(searchResultField.getFieldValue());
463             newSearchResultFields.add(newSearchResultField);
464         } else {
465             if (((List) object) != null) {
466                 for (Object identifier : (List) object) {
467                     SearchResultField newSearchResultField = new SearchResultField();
468                     SolrDocument itemSolrDocument = getItemRecord((String) identifier);
469                     String fieldValue = searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) : searchResultField.getFieldName();
470                     String resultFieldValue = getSolrFieldValue(itemSolrDocument, fieldValue);
471                     if (StringUtils.isNotBlank(resultFieldValue)) {
472                         newSearchResultField.setFieldValue(resultFieldValue);
473                     }
474                     newSearchResultField.setDocType(searchResultField.getDocType());
475                     newSearchResultField.setFieldName(searchResultField.getFieldName());
476                     //newSearchResultField.setFieldValue(searchResultField.getFieldValue());
477                     newSearchResultFields.add(newSearchResultField);
478                 }
479             }
480         }
481         return newSearchResultFields;
482     }
483 
484     private List<SearchResultField> buildItemSearchResultsForBib(SolrDocument solrDocument, SearchResultField searchResultField) {
485         List<SearchResultField> newSearchResultFields = new ArrayList<SearchResultField>();
486         Object holdingsObject = solrDocument.getFieldValue("holdingsIdentifier");
487         if (holdingsObject instanceof String) {
488             SearchResultField newSearchResultField = new SearchResultField();
489             SolrDocument holdingsSolrDocument = getHoldingsRecord((String) holdingsObject);
490             if (holdingsSolrDocument != null) {
491                 Object itemObject = holdingsSolrDocument.getFieldValue("itemIdentifier");
492                 if (itemObject instanceof String) {
493                     SolrDocument itemSolrDocument = getItemRecord((String) itemObject);
494                     String fieldValue = searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) : searchResultField.getFieldName();
495                     String resultFieldValue = getSolrFieldValue(itemSolrDocument, fieldValue);
496                     if (StringUtils.isNotBlank(resultFieldValue)) {
497                         newSearchResultField.setFieldValue(resultFieldValue);
498                     }
499                     newSearchResultField.setDocType(searchResultField.getDocType());
500                     newSearchResultField.setFieldName(searchResultField.getFieldName());
501                     //newSearchResultField.setFieldValue(searchResultField.getFieldValue());
502                     newSearchResultFields.add(newSearchResultField);
503                 } else {
504                     if (((List) itemObject) != null) {
505                         for (Object identifier : (List) itemObject) {
506                             SearchResultField newSearchResultField1 = new SearchResultField();
507                             SolrDocument itemSolrDocument = getItemRecord((String) identifier);
508                             String fieldValue = searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) : searchResultField.getFieldName();
509                             String resultFieldValue = getSolrFieldValue(itemSolrDocument, fieldValue);
510                             if (StringUtils.isNotBlank(resultFieldValue)) {
511                                 newSearchResultField.setFieldValue(resultFieldValue);
512                             }
513                             newSearchResultField1.setDocType(searchResultField.getDocType());
514                             newSearchResultField1.setFieldName(searchResultField.getFieldName());
515                             //newSearchResultField1.setFieldValue(searchResultField.getFieldValue());
516                             newSearchResultFields.add(newSearchResultField1);
517                         }
518                     }
519                 }
520             }
521         } else {
522             if (((List) holdingsObject) != null) {
523                 for (Object identifier : (List) holdingsObject) {
524                     SearchResultField newSearchResultField = new SearchResultField();
525                     SolrDocument holdingsSolrDocument = getHoldingsRecord((String) identifier);
526                     if (holdingsSolrDocument != null) {
527                         Object itemObject = holdingsSolrDocument.getFieldValue("itemIdentifier");
528                         if (itemObject instanceof String) {
529                             SolrDocument itemSolrDocument = getItemRecord((String) itemObject);
530                             String fieldValue = searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) : searchResultField.getFieldName();
531                             String resultFieldValue = getSolrFieldValue(itemSolrDocument, fieldValue);
532                             if (StringUtils.isNotBlank(resultFieldValue)) {
533                                 searchResultField.setFieldValue(resultFieldValue);
534                             }
535                             newSearchResultField.setDocType(searchResultField.getDocType());
536                             newSearchResultField.setFieldName(searchResultField.getFieldName());
537                             newSearchResultField.setFieldValue(searchResultField.getFieldValue());
538                             newSearchResultFields.add(newSearchResultField);
539                         } else {
540                             if (((List) itemObject) != null) {
541                                 for (Object itemIdentifier : (List) itemObject) {
542                                     SearchResultField newSearchResultField1 = new SearchResultField();
543                                     SolrDocument itemSolrDocument = getItemRecord((String) itemIdentifier);
544                                     String fieldValue = searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) : searchResultField.getFieldName();
545                                     String resultFieldValue = getSolrFieldValue(itemSolrDocument, fieldValue);
546                                     if (StringUtils.isNotBlank(resultFieldValue)) {
547                                         searchResultField.setFieldValue(resultFieldValue);
548                                     }
549                                     newSearchResultField1.setDocType(searchResultField.getDocType());
550                                     newSearchResultField1.setFieldName(searchResultField.getFieldName());
551                                     newSearchResultField1.setFieldValue(searchResultField.getFieldValue());
552                                     newSearchResultFields.add(newSearchResultField1);
553                                 }
554                             }
555                         }
556                     }
557                 }
558             }
559         }
560         return newSearchResultFields;
561     }
562 
563     private List<SearchResultField> buildHoldingsSearchResults(SolrDocument solrDocument, SearchResultField searchResultField) {
564         List<SearchResultField> newSearchResultFields = new ArrayList<SearchResultField>();
565         Object object = solrDocument.getFieldValue("holdingsIdentifier");
566         if (object instanceof String) {
567             SearchResultField newSearchResultField = new SearchResultField();
568             SolrDocument holdingsSolrDocument = getHoldingsRecord((String) object);
569             if (holdingsSolrDocument != null) {
570                 String fieldValue = searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) : searchResultField.getFieldName();
571                 String resultFieldValue = getSolrFieldValue(holdingsSolrDocument, fieldValue);
572                 if (StringUtils.isNotBlank(resultFieldValue)) {
573                     newSearchResultField.setFieldValue(resultFieldValue);
574                 }
575                 newSearchResultField.setDocType(searchResultField.getDocType());
576                 newSearchResultField.setFieldName(searchResultField.getFieldName());
577                 //newSearchResultField.setFieldValue(searchResultField.getFieldValue());
578                 newSearchResultFields.add(newSearchResultField);
579             }
580         } else {
581             if (((List) object) != null) {
582                 for (Object identifier : (List) object) {
583                     SearchResultField newSearchResultField = new SearchResultField();
584                     SolrDocument holdingsSolrDocument = getHoldingsRecord((String) identifier);
585                     if (holdingsSolrDocument != null) {
586                         String fieldValue = searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultField.getFieldName().toUpperCase()) : searchResultField.getFieldName();
587                         String resultFieldValue = getSolrFieldValue(holdingsSolrDocument, fieldValue);
588                         if (StringUtils.isNotBlank(resultFieldValue)) {
589                             newSearchResultField.setFieldValue(resultFieldValue);
590                         }
591                         newSearchResultField.setDocType(searchResultField.getDocType());
592                         newSearchResultField.setFieldName(searchResultField.getFieldName());
593                         //newSearchResultField.setFieldValue(searchResultField.getFieldValue());
594                         newSearchResultFields.add(newSearchResultField);
595                     }
596                 }
597             }
598         }
599         return newSearchResultFields;
600     }
601 
602     private String getSolrFieldValue(SolrDocument solrDocument, String fieldValue) {
603         Object obj = solrDocument.getFieldValue(fieldValue);
604         String resultFieldValue = null;
605         if (obj instanceof String) {
606             resultFieldValue = (String) obj;
607         } else if (obj instanceof Boolean) {
608             resultFieldValue = String.valueOf(obj);
609         } else if (obj instanceof Date) {
610             resultFieldValue = String.valueOf(obj);
611         } else if (obj instanceof List) {
612             if(fieldValue.endsWith("_display")) {
613                 if (((List) obj) != null) {
614                     StringBuilder resultFieldList = new StringBuilder();
615                     ArrayList<String> fields = (ArrayList<String>) obj;
616                     for(String s : fields) {
617                         resultFieldList.append(s);
618                         resultFieldList.append(", ");
619                     }
620                     resultFieldValue = resultFieldList.substring(0, (resultFieldList.length() -1));
621                 }
622             }
623             else {
624                 resultFieldValue = (String) ((List) obj).get(0);
625             }
626         }
627         return resultFieldValue;
628     }
629 
630     private List<SearchResultField> getDefaultSearchResultFields(SearchParams searchParams) {
631         String docType = null;
632         if (!CollectionUtils.isEmpty(searchParams.getSearchConditions())) {
633             docType = searchParams.getSearchConditions().get(0).getSearchField().getDocType();
634         }
635         List<SearchResultField> searchResultFields = new ArrayList<>();
636         if (StringUtils.isBlank(docType)) {
637             String allFields = BIB_FIELDS + "," + HOLDINGS_FIELDS + "," + ITEM_FIELDS;
638             for (String defaultField : getDefaultFields(allFields)) {
639                 SearchResultField searchResultField = new SearchResultField();
640                 searchResultField.setDocType(docType);
641                 searchResultField.setFieldName(defaultField);
642                 searchResultFields.add(searchResultField);
643             }
644         } else if (docType.equalsIgnoreCase(BIBLIOGRAPHIC)) {
645             for (String bibField : getDefaultFields(BIB_FIELDS)) {
646                 SearchResultField searchResultField = new SearchResultField();
647                 searchResultField.setDocType(docType);
648                 searchResultField.setFieldName(bibField);
649                 searchResultFields.add(searchResultField);
650             }
651         } else if (docType.equalsIgnoreCase(HOLDINGS)) {
652             for (String holdingsField : getDefaultFields(HOLDINGS_FIELDS)) {
653                 SearchResultField searchResultField = new SearchResultField();
654                 searchResultField.setDocType(docType);
655                 searchResultField.setFieldName(holdingsField);
656                 searchResultFields.add(searchResultField);
657             }
658         } else if (docType.equalsIgnoreCase(ITEM)) {
659             for (String itemField : getDefaultFields(ITEM_FIELDS)) {
660                 SearchResultField searchResultField = new SearchResultField();
661                 searchResultField.setDocType(docType);
662                 searchResultField.setFieldName(itemField);
663                 searchResultFields.add(searchResultField);
664             }
665         } else if (docType.equalsIgnoreCase(EHOLDINGS)) {
666             for (String itemField : getDefaultFields(EHOLDINGS_FIELDS)) {
667                 SearchResultField searchResultField = new SearchResultField();
668                 searchResultField.setDocType(docType);
669                 searchResultField.setFieldName(itemField);
670                 searchResultFields.add(searchResultField);
671             }
672         }
673         return searchResultFields;
674     }
675 
676     private List<String> getDefaultFields(String bibFields) {
677         return Arrays.asList(bibFields.split(","));
678     }
679 
680 
681     public String buildQueryWithSearchParams(SearchParams searchParams) {
682         return buildQueryWithSearchConditions(searchParams.getSearchConditions()) /*+ buildQueryWithSortConditions(searchParams.getSortConditions())*/;
683     }
684 
685     private SolrDocument getItemRecord(String itemIdentifier) {
686         try {
687             SolrDocument itemSolrDocument = null;
688             SearchParams searchParams = new SearchParams();
689             SearchField searchField = searchParams.buildSearchField("item", "itemIdentifier", itemIdentifier);
690             searchParams.getSearchConditions().add(searchParams.buildSearchCondition("none", searchField, null));
691             SolrQuery solrQuery = new SolrQuery();
692             SolrServer server = SolrServerManager.getInstance().getSolrServer();
693             buildQueryWithSearchConditions(searchParams,solrQuery);
694             QueryResponse response = server.query(solrQuery);
695             if (response.getResults().size() > 0) {
696                 itemSolrDocument = response.getResults().get(0);
697             }
698             return itemSolrDocument;
699         } catch (SolrServerException ex) {
700             LOG.info("Exception :", ex);
701             throw new DocstoreIndexException(ex.getMessage());
702         }
703     }
704 
705     private SolrDocument getBibRecord(String bibIdentifier) {
706         try {
707             SolrDocument bibSolrDocument = null;
708             SearchParams searchParams = new SearchParams();
709             SearchField searchField = searchParams.buildSearchField("bibliographic", "LocalId_search", DocumentUniqueIDPrefix.getDocumentId(bibIdentifier));
710             searchParams.getSearchConditions().add(searchParams.buildSearchCondition("none", searchField, null));
711             SolrQuery solrQuery = new SolrQuery();
712             SolrServer server = SolrServerManager.getInstance().getSolrServer();
713             buildQueryWithSearchConditions(searchParams,solrQuery);
714             QueryResponse response = server.query(solrQuery);
715             if (response.getResults().size() > 0) {
716                 bibSolrDocument = response.getResults().get(0);
717             }
718             return bibSolrDocument;
719         } catch (SolrServerException ex) {
720             LOG.info("Exception :", ex);
721             throw new DocstoreIndexException(ex.getMessage());
722         }
723     }
724 
725     private SolrDocument getHoldingsRecord(String holdingsIdentifier) {
726         try {
727             SolrDocument holdingsSolrDocument = null;
728             SearchParams searchParams = new SearchParams();
729             SearchField searchField = searchParams.buildSearchField("holdings", "holdingsIdentifier", holdingsIdentifier);
730             searchParams.getSearchConditions().add(searchParams.buildSearchCondition("none", searchField, null));
731             SolrQuery solrQuery = new SolrQuery();
732             SolrServer server = SolrServerManager.getInstance().getSolrServer();
733             buildQueryWithSearchConditions(searchParams,solrQuery);
734             QueryResponse response = server.query(solrQuery);
735             if (response.getResults().size() > 0) {
736                 holdingsSolrDocument = response.getResults().get(0);
737             }
738             return holdingsSolrDocument;
739         } catch (SolrServerException ex) {
740             LOG.info("Exception :", ex);
741             throw new DocstoreIndexException(ex.getMessage());
742         }
743     }
744 
745     private String buildQueryWithResultFieldsLists(SearchParams searchParams) {
746         String docType = searchParams.getDocType();
747         List<SearchResultField> searchResultFields = searchParams.getSearchResultFields();
748         if (StringUtils.isEmpty(docType) && !CollectionUtils.isEmpty(searchParams.getSearchConditions())) {
749             for(SearchCondition searchCondition:searchParams.getSearchConditions()){
750                 if(searchCondition.getSearchField()!=null){
751                     docType = searchCondition.getSearchField().getDocType();
752                     break;
753                 }
754             }
755         }
756         StringBuffer resultFieldsBuffer = new StringBuffer();
757         //resultFieldsBuffer.append("&");
758         //resultFieldsBuffer.append("fl=");
759         if (StringUtils.isBlank(docType)) {
760             if (!CollectionUtils.isEmpty(searchResultFields)) {
761                 for (int i = 0; i < searchResultFields.size(); i++) {
762                     resultFieldsBuffer.append(searchResultFieldsMap.get(searchResultFields.get(i).getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultFields.get(i).getFieldName().toUpperCase()) : searchResultFields.get(i).getFieldName());
763                     if (i != searchResultFields.size() - 1) {
764                         resultFieldsBuffer.append(",");
765                     }
766                 }
767             } /*else {
768                 resultFieldsBuffer.append(BIB_FIELDS + "," + HOLDINGS_FIELDS + "," + ITEM_FIELDS);
769             }*/
770         } else if (docType.equalsIgnoreCase(BIBLIOGRAPHIC)) {
771             if (!CollectionUtils.isEmpty(searchResultFields)) {
772                 for (int i = 0; i < searchResultFields.size(); i++) {
773                     if (searchResultFields.get(i).getDocType().equalsIgnoreCase(BIBLIOGRAPHIC)) {
774                         resultFieldsBuffer.append(searchResultFieldsMap.get(searchResultFields.get(i).getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultFields.get(i).getFieldName().toUpperCase()) : searchResultFields.get(i).getFieldName());
775                         resultFieldsBuffer.append(",");
776                     }
777                 }
778                 resultFieldsBuffer.append(BIB_LINK_FIELDS);
779             } /*else {
780                 resultFieldsBuffer.append(BIB_FIELDS);
781             }*/
782         } else if (docType.equalsIgnoreCase(HOLDINGS)) {
783             if (!CollectionUtils.isEmpty(searchResultFields)) {
784                 for (int i = 0; i < searchResultFields.size(); i++) {
785                     if (searchResultFields.get(i).getDocType().equalsIgnoreCase(HOLDINGS)) {
786                         resultFieldsBuffer.append(searchResultFieldsMap.get(searchResultFields.get(i).getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultFields.get(i).getFieldName().toUpperCase()) : searchResultFields.get(i).getFieldName());
787                         resultFieldsBuffer.append(",");
788                     }
789                 }
790                 resultFieldsBuffer.append(HOLDINGS_LINK_FIELDS);
791             } /*else {
792                 resultFieldsBuffer.append(HOLDINGS_FIELDS);
793             }*/
794 
795         } else if (docType.equalsIgnoreCase(ITEM)) {
796             if (!CollectionUtils.isEmpty(searchResultFields)) {
797                 for (int i = 0; i < searchResultFields.size(); i++) {
798                     if (searchResultFields.get(i).getDocType().equalsIgnoreCase(ITEM)) {
799                         resultFieldsBuffer.append(searchResultFieldsMap.get(searchResultFields.get(i).getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultFields.get(i).getFieldName().toUpperCase()) : searchResultFields.get(i).getFieldName());
800                         resultFieldsBuffer.append(",");
801                     }
802                 }
803                 resultFieldsBuffer.append(ITEM_LINK_FIELDS);
804             } /*else {
805                 resultFieldsBuffer.append(ITEM_FIELDS);
806             }*/
807         } else if (docType.equalsIgnoreCase(EHOLDINGS)) {
808             if (!CollectionUtils.isEmpty(searchResultFields)) {
809                 for (int i = 0; i < searchResultFields.size(); i++) {
810                     if (searchResultFields.get(i).getDocType().equalsIgnoreCase(EHOLDINGS)) {
811                         resultFieldsBuffer.append(searchResultFieldsMap.get(searchResultFields.get(i).getFieldName().toUpperCase()) != null ? searchResultFieldsMap.get(searchResultFields.get(i).getFieldName().toUpperCase()) : searchResultFields.get(i).getFieldName());
812                         resultFieldsBuffer.append(",");
813                     }
814                 }
815                 resultFieldsBuffer.append(EHOLDINGS_FIELDS);
816             } /*else {
817                 resultFieldsBuffer.append(ITEM_FIELDS);
818             }*/
819         }
820         return resultFieldsBuffer.toString();
821     }
822 
823     private List<String> getIds(List<SolrDocument> solrDocumentList) {
824         List<String> ids = new ArrayList<>();
825         for (SolrDocument solrDocument : solrDocumentList) {
826             String docType = (String) solrDocument.getFieldValue("DocType");
827             if (docType.equalsIgnoreCase(DocType.BIB.getCode())) {
828                 ids.add((String) solrDocument.getFieldValue("id"));
829             } else if (docType.equalsIgnoreCase(DocType.HOLDINGS.getCode())) {
830                 ids.add((String) solrDocument.getFieldValue("id"));
831             } else if (docType.equalsIgnoreCase(DocType.ITEM.getCode())) {
832                 ids.add((String) solrDocument.getFieldValue("id"));
833             }
834         }
835         return ids;
836     }
837 
838     public String buildQueryWithSearchConditions(List<SearchCondition> searchConditions) {
839         StringBuffer query = new StringBuffer();
840         StringBuffer addDocType = new StringBuffer();
841         if (searchConditions != null && searchConditions.size() > 0) {
842             for (SearchCondition searchCondition : searchConditions) {
843                 if (searchCondition.getSearchField() != null && searchCondition.getSearchField().getDocType() != null) {
844                     addDocType.append("(DocType:");
845                     addDocType.append(searchCondition.getSearchField().getDocType());
846                     addDocType.append(")");
847                     break;
848                 }
849             }
850         } else {
851             return "(*:*)";
852         }
853 
854         modifySearchCondition(searchConditions);
855         //    Collections.reverse(searchConditions);
856         int size = searchConditions.size();
857         String previousOperator = "";
858         String docOperator ="AND";
859         for (int i = size - 1; i >= 0; i--) {
860             boolean isInsert = false;
861             SearchCondition searchCondition = null;
862             String searchText = null;
863             String searchScope = null;
864             if (searchConditions.get(i) != null && searchConditions.get(i).getSearchField() != null) {
865                 if ((size - 1) != i) {
866                     query.insert(0, "(");
867                     isInsert = true;
868                 }
869                 searchCondition = searchConditions.get(i);
870                 searchText = searchCondition.getSearchField().getFieldValue();
871                 searchScope = searchCondition.getSearchScope();
872                 if (StringUtils.isNotEmpty(searchCondition.getOperator()) && searchCondition.getOperator().equalsIgnoreCase("NOT")) {
873                     previousOperator = searchCondition.getOperator();
874                     if(size == 1){
875                         docOperator = searchCondition.getOperator();
876                     }
877                 }
878 
879             } else {
880                 continue;
881             }
882 
883             if (isInsert) {
884                 query.append(previousOperator);
885             }
886 
887             query.append("(");
888             if (StringUtils.isNotBlank(searchCondition.getSearchField().getFieldName())) {
889                 if (searchCondition.getSearchField().getFieldName().equalsIgnoreCase("all") || searchCondition.getSearchField().getFieldName().equalsIgnoreCase("any")) {
890                     query.append("all_text");
891                 } else {
892                     query.append(searchFieldsMap.get(searchCondition.getSearchField().getFieldName().toUpperCase()) != null ? searchFieldsMap.get(searchCondition.getSearchField().getFieldName().toUpperCase()) : searchCondition.getSearchField().getFieldName());
893                 }
894                 query.append(":");
895             }
896 
897             if (StringUtils.isNotBlank(searchText)) {
898                 String searchTextVal = getModifiedText(searchText);
899                 if (searchText.length() > 0) {
900                     query.append("(");
901                     if (StringUtils.isNotBlank(searchScope)) {
902                         if (searchScope.equalsIgnoreCase("AND")) {
903                             searchTextVal = searchTextVal.trim().replaceAll("\\s+", "+ AND +");
904                         } else if (searchScope.equalsIgnoreCase("OR")) {
905                             searchTextVal = searchTextVal.trim().replaceAll("\\s+", "+ OR +");
906                         } else if (searchScope.equalsIgnoreCase("phrase")) {
907                             searchTextVal = "\"" + searchText + "\"";
908                         } else if (searchScope.equalsIgnoreCase("none")) {
909                             searchTextVal = searchText;
910                         }
911                     }
912                     query.append(searchTextVal);
913                     query.append(")");
914                 }
915                 query.append(")");
916             } else {
917                 query.append("(*:*)");
918                 query.append(")");
919             }
920 
921             previousOperator = searchCondition.getOperator();
922 
923 
924             if (isInsert) {
925                 query.append(")");
926             }
927         }
928         if (addDocType != null && addDocType.length() > 0) {
929             return addDocType.append(docOperator).append(query).toString();
930         } else {
931             return query.toString();
932         }
933     }
934 
935     private void modifySearchCondition(List<SearchCondition> searchConditions) {
936         List<SearchCondition> tempSearchConditions = new ArrayList<>();
937         List<SearchCondition> notSearchConditions = new ArrayList<>();
938 
939         for(SearchCondition searchCondition:searchConditions){
940             if(StringUtils.isNotEmpty(searchCondition.getOperator()) && searchCondition.getOperator().equalsIgnoreCase("NOT")){
941                 notSearchConditions.add(searchCondition);
942             }else{
943                 tempSearchConditions.add(searchCondition);
944             }
945         }
946 
947         if(tempSearchConditions.size() >0){
948             notSearchConditions.addAll(tempSearchConditions);
949         }
950 
951         searchConditions.clear();
952         searchConditions.addAll(notSearchConditions);
953     }
954 
955 
956     public void buildQueryWithSearchConditions(SearchParams searchParams, SolrQuery solrQuery) {
957         String docType = searchParams.getDocType(); // second
958         String key = "";
959         String firstDocType = "";
960         String secondDocType = searchParams.getDocType();
961         String query = "";
962         List<SearchCondition> filterSearchConditions = new ArrayList<>();
963         List<SearchCondition> querySearchConditions = new ArrayList<>();
964         int size = searchParams.getSearchConditions().size();
965         for (int i = size - 1; i >= 0; i--) {
966             SearchCondition searchCondition = searchParams.getSearchConditions().get(i);
967             if (!searchCondition.getSearchField().getDocType().equalsIgnoreCase(secondDocType)) {
968                 firstDocType = searchCondition.getSearchField().getDocType();
969             }
970             if (searchCondition.getSearchField() != null && searchCondition.getSearchField().getDocType() != null && docType.equals(searchCondition.getSearchField().getDocType())) {
971                 filterSearchConditions.add(searchCondition);
972             } else {
973                 querySearchConditions.add(searchCondition);
974             }
975         }
976         if (StringUtils.isEmpty(secondDocType)) {
977             secondDocType = docType;
978         }
979 
980         if (StringUtils.isEmpty(secondDocType)) {
981             secondDocType = firstDocType;
982         }
983         if (StringUtils.isEmpty(docType)) {
984             docType = firstDocType;
985         }
986         if (StringUtils.isNotEmpty(firstDocType) && StringUtils.isNotEmpty(secondDocType)) {
987             key = secondDocType + firstDocType;
988             String crossDocumentJoinQuery = joinQueryMap.get(key);
989             if (StringUtils.isNotEmpty(crossDocumentJoinQuery)) {
990                 query = joinQueryMap.get(key) + buildQueryWithSearchConditions(querySearchConditions);
991             } else {
992                 query = buildQueryWithSearchConditions(querySearchConditions);
993             }
994 
995             String filterQuery = "";
996             if (filterSearchConditions != null && filterSearchConditions.size() > 0) {
997                 filterQuery = buildQueryWithSearchConditions(filterSearchConditions);
998             }
999             if (StringUtils.isEmpty(filterQuery)) {
1000                 filterQuery = "DocType:" + docType;
1001             }
1002             solrQuery.setQuery(query);
1003             solrQuery.setFilterQueries(filterQuery);
1004             LOG.info("join query = " + solrQuery.getQuery() + "\tfilter query = " + solrQuery.getFilterQueries()[0]);
1005         } else {
1006             String filterQuery = buildQueryWithSearchConditions(filterSearchConditions);
1007             solrQuery.setQuery(filterQuery);
1008             LOG.info("query = " + solrQuery.getQuery());
1009         }
1010 
1011     }
1012 
1013 
1014 //    public String buildQueryWithSearchConditions(List<SearchCondition> searchConditions) {
1015 //        boolean searchConditionCheck = false;
1016 //        SearchCondition searchCondition = null;
1017 //        String docType = null;
1018 //        StringBuffer queryStringBuffer = new StringBuffer();
1019 //        if (searchConditions != null && searchConditions.size() > 0) {
1020 //            for (int i = 0; i < searchConditions.size(); i++) {
1021 //                int searchScopeAddLimit = i;
1022 //                searchCondition = searchConditions.get(i);
1023 //                if (searchCondition.getSearchField() != null) {
1024 //                    if (StringUtils.isBlank(docType) && searchScopeAddLimit == 0) {
1025 //                        docType = searchCondition.getSearchField().getDocType();
1026 //                        if (StringUtils.isNotBlank(docType)) {
1027 //                            queryStringBuffer.append("(");
1028 //                            queryStringBuffer.append("DocType:" + docType);
1029 //                            queryStringBuffer.append(")");
1030 //                        }
1031 //                    }
1032 //                    String searchScope = searchCondition.getSearchScope();
1033 //                    String searchOperator = searchCondition.getOperator();
1034 //                    String searchText = searchCondition.getSearchField().getFieldValue();
1035 //                    if (StringUtils.isBlank(docType) || docType.equalsIgnoreCase(searchCondition.getSearchField().getDocType())) {
1036 //                        if (StringUtils.isNotBlank(searchCondition.getSearchField().getFieldName()) || StringUtils.isNotBlank(searchCondition.getSearchField().getFieldValue())) {
1037 //                            if (StringUtils.isNotBlank(docType) && searchScopeAddLimit == 0) {
1038 //                                queryStringBuffer.append("AND");
1039 //                                queryStringBuffer.append("(");
1040 //                            }
1041 //                            queryStringBuffer.append("(");
1042 //                            if (StringUtils.isNotBlank(searchCondition.getSearchField().getFieldName())) {
1043 //                                if (searchCondition.getSearchField().getFieldName().equalsIgnoreCase("all")) {
1044 //                                    queryStringBuffer.append("all_text");
1045 //                                } else {
1046 //                                    queryStringBuffer.append(searchFieldsMap.get(searchCondition.getSearchField().getFieldName().toUpperCase()) != null ? searchFieldsMap.get(searchCondition.getSearchField().getFieldName().toUpperCase()) : searchCondition.getSearchField().getFieldName());
1047 //                                }
1048 //                                queryStringBuffer.append(":");
1049 //                            }
1050 //
1051 //                            if (StringUtils.isNotBlank(searchText)) {
1052 //                                String searchTextVal = getModifiedText(searchText);
1053 //                                if (searchText.length() > 0) {
1054 //                                    queryStringBuffer.append("(");
1055 //                                    if (StringUtils.isNotBlank(searchScope)) {
1056 //                                        if (searchScope.equalsIgnoreCase("AND")) {
1057 //                                            searchTextVal = searchTextVal.trim().replaceAll("\\s+", "+ AND +");
1058 //                                        } else if (searchScope.equalsIgnoreCase("OR")) {
1059 //                                            searchTextVal = searchTextVal.trim().replaceAll("\\s+", "+ OR +");
1060 //                                        } else if (searchScope.equalsIgnoreCase("phrase")) {
1061 //                                            searchTextVal = "\"" + searchText + "\"";
1062 //                                        } else if (searchScope.equalsIgnoreCase("none")) {
1063 //                                            searchTextVal = searchText;
1064 //                                        }
1065 //                                    }
1066 //                                    queryStringBuffer.append(searchTextVal);
1067 //                                    queryStringBuffer.append(")");
1068 //                                }
1069 //                                queryStringBuffer.append(")");
1070 //                                searchConditionCheck = true;
1071 //                            } else {
1072 //                                queryStringBuffer.append("(*:*)");
1073 //                                queryStringBuffer.append(")");
1074 //                                searchConditionCheck = true;
1075 //                            }
1076 //                        }
1077 //                    }
1078 //                    ++searchScopeAddLimit;
1079 //                    if (StringUtils.isBlank(searchOperator)) {
1080 //                        break;
1081 //                    }
1082 //                    if (searchScopeAddLimit != searchConditions.size()) {
1083 //                        if (StringUtils.isBlank(docType) || StringUtils.isNotBlank(docType) && docType.equalsIgnoreCase(searchConditions.get(searchScopeAddLimit).getSearchField().getDocType())) {
1084 //                            queryStringBuffer.append(searchOperator);
1085 //                        }
1086 //                    }
1087 //                }
1088 //                if (StringUtils.isBlank(docType) && StringUtils.isBlank(searchCondition.getSearchField().getFieldName()) && StringUtils.isBlank(searchCondition.getSearchField().getFieldValue())) {
1089 //                    queryStringBuffer.append("*:*");
1090 //                }
1091 //            }
1092 //        } else {
1093 //            queryStringBuffer.append("*:*");
1094 //        }
1095 //        if (searchConditionCheck && StringUtils.isNotBlank(docType)) {
1096 //            queryStringBuffer.append(")");
1097 //        }
1098 //        return queryStringBuffer.toString();
1099 //    }
1100 
1101     private String getModifiedText(String searchText) {
1102         StringBuffer modifiedText = new StringBuffer();
1103         boolean isHashReplaced=true;
1104         if(searchText.contains(DocumentUniqueIDPrefix.PREFIX_WORK_BIB_MARC) || searchText.contains(DocumentUniqueIDPrefix.PREFIX_WORK_HOLDINGS_OLEML) || searchText.contains(DocumentUniqueIDPrefix.PREFIX_WORK_ITEM_OLEML) ){
1105             isHashReplaced=false;
1106         }
1107         StringCharacterIterator stringCharacterIterator = new StringCharacterIterator(searchText);
1108         char character = stringCharacterIterator.current();
1109         while (character != CharacterIterator.DONE) {
1110 
1111             if (character == '\\') {
1112                 modifiedText.append("\\\\");
1113             } else if (character == '?') {
1114                 modifiedText.append("\\?");
1115             } else if (character == '*' && StringUtils.isEmpty(modifiedText.toString())) {
1116                 modifiedText.append("\\*");
1117             } else if (character == '+') {
1118                 modifiedText.append("\\+");
1119             } else if (character == ':') {
1120                 modifiedText.append("\\:");
1121             } else if (character == '{') {
1122                 modifiedText.append("\\{");
1123             } else if (character == '}') {
1124                 modifiedText.append("\\}");
1125             } else if (character == '[') {
1126                 modifiedText.append("\\[");
1127             } else if (character == ']') {
1128                 modifiedText.append("\\]");
1129             } else if (character == '(') {
1130                 modifiedText.append("\\(");
1131             } else if (character == ')') {
1132                 modifiedText.append("\\)");
1133             } else if (character == '^') {
1134                 modifiedText.append("\\^");
1135             } else if (character == '~') {
1136                 modifiedText.append("\\~");
1137             } else if (character == '-') {
1138                 if (isHashReplaced) {
1139                     modifiedText.append("");
1140                 } else {
1141                     modifiedText.append("\\-");
1142                 }
1143             } else if (character == '!') {
1144                 modifiedText.append("\\!");
1145             } else if (character == '\'') {
1146                 modifiedText.append("\\'");
1147             } else if (character == '@') {
1148                 modifiedText.append("\\@");
1149             } else if (character == '#') {
1150                 modifiedText.append("\\#");
1151             } else if (character == '$') {
1152                 modifiedText.append("\\$");
1153             } else if (character == '%') {
1154                 modifiedText.append("\\%");
1155             } else {
1156                 // the char is not a special one
1157                 // add it to the result as is
1158                 modifiedText.append(character);
1159             }
1160             character = stringCharacterIterator.next();
1161         }
1162         return modifiedText.toString();
1163     }
1164 
1165     /*public String buildQueryWithSortConditions(List<SortCondition> sortConditions) {
1166         StringBuffer sortFieldsQuery = new StringBuffer();
1167         for (SortCondition sortCondition : sortConditions) {
1168             String sortField = sortCondition.getSortField();
1169             String sortOrder = sortCondition.getSortOrder();
1170             if (StringUtils.isNotBlank(sortField) && StringUtils.isNotBlank(getSolrSortField(sortField.toUpperCase())) && StringUtils.isNotBlank(sortOrder)) {
1171                 sortFieldsQuery.append("&");
1172                 sortFieldsQuery.append("sort=");
1173                 sortFieldsQuery.append(getSolrSortField(sortField.toUpperCase()));
1174                 sortFieldsQuery.append(" ");
1175                 sortFieldsQuery.append(sortOrder);
1176             }
1177         }
1178         return sortFieldsQuery.toString();
1179     }*/
1180 
1181     private void buildQueryWithSortConditions(SolrQuery solrQuery, List<SortCondition> sortConditions) {
1182         for (SortCondition sortCondition : sortConditions) {
1183             String sortField = sortCondition.getSortField();
1184             String sortOrder = sortCondition.getSortOrder();
1185             if (StringUtils.isNotBlank(sortField) && StringUtils.isNotBlank(sortOrder)) {
1186                 solrQuery.addSortField(getSolrSortField(sortField.toUpperCase()) != null ? getSolrSortField(sortField.toUpperCase()) : sortField, SolrQuery.ORDER.valueOf(sortOrder));
1187             }
1188         }
1189     }
1190 
1191     private String getSolrSortField(String sortField) {
1192 
1193         if ("TITLE".equals(sortField)) {
1194             return "Title_sort";
1195         } else if ("AUTHOR".equals(sortField)) {
1196             return "Author_sort";
1197         } else if ("PUBLICATION DATE".equals(sortField)) {
1198             return "PublicationDate_sort";
1199         } else if ("LOCATION".equals(sortField)) {
1200             return "Location_sort";
1201         } else if ("CALL NUMBER".equals(sortField)) {
1202             return "CallNumber_sort";
1203         } else if ("LOCAL IDENTIFIER".equalsIgnoreCase(sortField)){
1204             return "LocalId_search";
1205         } else if ("Journal Title".equalsIgnoreCase(sortField)){
1206             return "JournalTitle_sort";
1207         }
1208         return null;
1209     }
1210 
1211     @Override
1212     public List<String> callNumberBrowse(BrowseParams browseParams) {
1213         try {
1214             SolrQuery solrQuery = new SolrQuery();
1215             SolrServer server = SolrServerManager.getInstance().getSolrServer();
1216             solrQuery.setQuery(buildQueryWithSearchParams(browseParams));
1217             QueryResponse response = server.query(solrQuery);
1218             browseParams.setTotalCount(response.getResults().getNumFound());
1219             return getIds(response.getResults());
1220         } catch (SolrServerException ex) {
1221             LOG.info("Exception :", ex);
1222             throw new DocstoreIndexException(ex.getMessage());
1223         }
1224     }
1225 
1226     @Override
1227     public String findBib(Map<String, String> map) {
1228         List<String> bibIds = new ArrayList<>();
1229         SearchParams searchParams = buildSearchParamsFromMap(map);
1230         SearchResponse searchResponse = search(searchParams);
1231         for (SearchResult searchResult : searchResponse.getSearchResults()) {
1232             for (SearchResultField searchResultField : searchResult.getSearchResultFields()) {
1233                 bibIds.add(searchResultField.getFieldValue());
1234             }
1235         }
1236         if (!CollectionUtils.isEmpty(bibIds)) {
1237             return bibIds.get(0);
1238         }
1239         return null;
1240     }
1241 
1242     private SearchParams buildSearchParamsFromMap(Map<String, String> map) {
1243         SearchParams searchParams = new SearchParams();
1244         Set<String> keys = map.keySet();
1245         for (String key : keys) {
1246             if (!BibConstants.DOC_TYPE.equalsIgnoreCase(key)) {
1247                 SearchCondition searchCondition = new SearchCondition();
1248                 SearchField searchField = searchParams.buildSearchField(map.get(BibConstants.DOC_TYPE), searchFieldsMap.get(key), map.get(key));
1249                 searchCondition.setSearchField(searchField);
1250                 searchParams.getSearchConditions().add(searchCondition);
1251             }
1252         }
1253         searchParams.getSearchResultFields().add(searchParams.buildSearchResultField(map.get(BibConstants.DOC_TYPE), "id"));
1254         return searchParams;
1255     }
1256 
1257     @Override
1258     public String findHoldings(Map<String, String> map) {
1259         List<String> holdingIds = new ArrayList<>();
1260         map.put(BibConstants.DOC_TYPE, "holdings");
1261         SearchParams searchParams = buildSearchParamsFromMap(map);
1262         SearchResponse searchResponse = search(searchParams);
1263         for (SearchResult searchResult : searchResponse.getSearchResults()) {
1264             for (SearchResultField searchResultField : searchResult.getSearchResultFields()) {
1265                 holdingIds.add(searchResultField.getFieldValue());
1266             }
1267         }
1268         if (!CollectionUtils.isEmpty(holdingIds)) {
1269             return holdingIds.get(0);
1270         }
1271         return null;
1272     }
1273 
1274     @Override
1275     public String findItem(Map<String, String> map) {
1276         List<String> itemIds = new ArrayList<>();
1277         map.put(BibConstants.DOC_TYPE, "item");
1278         SearchParams searchParams = buildSearchParamsFromMap(map);
1279         SearchResponse searchResponse = search(searchParams);
1280         for (SearchResult searchResult : searchResponse.getSearchResults()) {
1281             for (SearchResultField searchResultField : searchResult.getSearchResultFields()) {
1282                 itemIds.add(searchResultField.getFieldValue());
1283             }
1284         }
1285         if (!CollectionUtils.isEmpty(itemIds)) {
1286             return itemIds.get(0);
1287         }
1288         return null;
1289     }
1290 
1291     @Override
1292     public String findHoldingsTree(Map<String, String> map) {
1293         return findHoldings(map);
1294     }
1295 
1296     @Override
1297     public String findBibTree(Map<String, String> map) {
1298         return findBib(map);
1299     }
1300 
1301 }