View Javadoc

1   /*
2    * Copyright 2011 The Kuali Foundation.
3    * 
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    * http://www.opensource.org/licenses/ecl2.php
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.ole.docstore.discovery.service;
17  
18  import org.kuali.ole.docstore.discovery.model.SearchCondition;
19  import org.kuali.ole.docstore.discovery.model.SearchParams;
20  import org.kuali.ole.docstore.discovery.util.PropertyUtil;
21  import org.slf4j.Logger;
22  import org.slf4j.LoggerFactory;
23  
24  import java.io.BufferedReader;
25  import java.io.InputStreamReader;
26  import java.io.UnsupportedEncodingException;
27  import java.net.URL;
28  import java.net.URLConnection;
29  import java.net.URLDecoder;
30  import java.net.URLEncoder;
31  import java.util.*;
32  
33  public class DiscoveryServiceImpl
34          implements DiscoveryService {
35      private static final Logger           LOG              = LoggerFactory.getLogger(DiscoveryServiceImpl.class);
36      private static       String           docSearchUrl     = null;
37      private static       DiscoveryService discoveryService = null;
38  
39      private DiscoveryServiceImpl() {
40          LOG.debug("DiscoveryServiceImpl ");
41          init();
42      }
43  
44      public static DiscoveryService getInstance() {
45          if (null == discoveryService) {
46              discoveryService = new DiscoveryServiceImpl();
47          }
48          return discoveryService;
49      }
50  
51      protected void init() {
52          LOG.debug("DiscoveryServiceImpl init ");
53          setDocSearchUrl(PropertyUtil.getPropertyUtil().getProperty("docSearchURL"));
54      }
55  
56      public String search(SearchParams searchParams) {
57          String response = "";
58          LOG.debug("in search1");
59          String searchType = searchParams.getSearchType();
60          LOG.debug("searchType " + searchType);
61          StringBuffer query = new StringBuffer();
62          query.append(SolrServerManager.getInstance().getSolrCoreURL() + "/select");
63          if (searchType.equals(SEARCH_TYPE_MORE_FACET)) {
64              String facetPrefix = searchParams.getFacetPrefix();
65              String facetPageSize = searchParams.getFacetPageSize();
66              String facetSort = searchParams.getFacetSort();
67              String facetOffset = searchParams.getFacetOffset();
68              buildInitialQuery(query, searchParams);
69              query.append("&facet=true");
70  
71              query.append("&facet.mincount=1");
72  
73              query.append("&facet.prefix=" + facetPrefix);
74  
75              query.append("&facet.offset=" + facetOffset);
76  
77              query.append("&facet.limit=" + facetPageSize);
78  
79              query.append("&facet.sort=" + facetSort);
80  
81              query.append("&facet.field=" + searchParams.getFacetField());
82  
83              Map<String, String> facetTermsMap = searchParams.getFacetTermsMap();
84              query.append(buildFilterQuery(facetTermsMap));
85          }
86          else {
87              if (searchParams.getSearchFieldsList() != null && searchParams.getSearchFieldsList().size() <= 0 && (
88                      searchType != null && !searchType.equalsIgnoreCase(SEARCH_TYPE_LINK))) {
89                  buildInitialQuery(query, searchParams);
90                  searchParams.setSearchTerms("");
91              }
92              else if (searchType != null && (searchType.equalsIgnoreCase(SEARCH_TYPE_ADVANCED)
93                                              || searchType.equalsIgnoreCase(SEARCH_TYPE_FACET) || searchType
94                      .equalsIgnoreCase(SEARCH_TYPE_FACET_DELETE))) {
95                  buildInitialQuery(query, searchParams);
96                  if (searchParams.getSearchFieldsList().size() > 0) {
97                      query.append("AND(");
98                  }
99                  query.append(buildQueryWithSearchParameters(searchParams.getSearchFieldsList()));
100                 LOG.debug("query for search terms............." + query.toString());
101                 String searchTerms = buildQueryWithSearchParameters(searchParams.getSearchFieldsList())
102                         .replaceAll("_search", "");
103                 try {
104                     searchTerms = URLDecoder.decode(searchTerms, "UTF-8");
105                 }
106                 catch (UnsupportedEncodingException e) {
107                     e.printStackTrace();
108                 }
109                 searchParams.setSearchTerms(searchTerms.substring(0, searchTerms.lastIndexOf(")")));
110             }
111             if (SEARCH_TYPE_LINK.equals(searchType)) {
112                 query.append("?q=id:");
113                 query.append(searchParams.getLinkValue());
114             }
115             query.append("&rows=" + searchParams.getResultPageSize());
116             String docType = searchParams.getDocType();
117             LOG.info("docType-->" + docType);
118 
119             query.append("&start=" + searchParams.getResultFromIndex());
120             List<String> facetList = new ArrayList<String>();
121             facetList.add(AUTHOR_FACET);
122             facetList.add(SUBJECT_FACET);
123             facetList.add(FORMAT_FACET);
124             facetList.add(LANGUAGE_FACET);
125             facetList.add(PUBLICATION_DATE_FACET);
126             facetList.add(GENRE_FACET);
127             query.append(buildQueryWithFacetParameters(facetList, 1, 10));
128             LOG.debug("sort terms buildQueryWithSortFields" + searchParams.getSortByTerms());
129             LOG.debug("sort Field buildQueryWithSortFields" + searchParams.getSortField());
130             LOG.debug("sort Order buildQueryWithSortFields" + searchParams.getSortOrder());
131             query.append(buildQueryWithSortFields(searchParams.getSortField(), searchParams.getSortOrder()));
132             query.append(buildQueryWithFieldListParameters(searchParams.getFieldList()));
133             Map<String, String> facetTermsMap = searchParams.getFacetTermsMap();
134             query.append(buildFilterQuery(facetTermsMap));
135             String holdingFields
136                     = "Uri_display,HoldingsNote_display,ReceiptStatus_display,CallNumber_display,CallNumberPrefix_display,CallNumberType_display,ClassificationPart_display";
137             String itemFields
138                     = "ItemBarcode_display,ItemTypeFullValue_display,VendorLineItemIdentifier_display,ShelvingOrderValue_display,ShelvingSchemeValue_display,PurchaseOrderLineItemIdentifier_display,CopyNumber_display,VolumeNumber_display";
139             String instanceFields = "Source_display";
140             String patronFields
141                     = "RecordNumber_display,BeginDate_display,Name_display,BorrowerType_display,BarCodeNumber_display,BarCodeStatus_display,";
142             String onixplFields
143                     = "ContractNumber_display,Title_display,Method_display,Status_display,Type_display,Licensor_display,Licensee_display";
144             String licenseBinaryFields
145                     = "Name_display,FileName_display,DateUploaded_display,Owner_display,Notes_display";
146             //query.append("&fl=" + fieldList);
147             query.append(
148                     "&fl=Title_display,Author_display,Publisher_display,Description_display,Subject_display,Location_display,PublicationDate_display,Format_display,DocType,DocFormat,id,ItemLinks,BibliographicLinks,Barcode_display,instanceIdentifier,holdingsIdentifier,itemIdentifier,bibIdentifier"
149                     /*
150                                     + "," + "245a,245b"
151                                     + "," + "100a,110a,111a,700a,710a,711a,800a,810a,811a,400a,410a,411a"
152                                     + "," + "600a,610a,611a,630a,650a,651a,653a"
153                                     + "," + "505a"
154                                     + "," + "856u"
155                                     + "," + "260b"
156                     */ + "," + holdingFields + "," + itemFields + "," + instanceFields + "," + patronFields
157                     + "," + onixplFields + "," + licenseBinaryFields);
158         }
159         LOG.debug("query---> " + query);
160         try {
161             String queryStr = query.toString().replaceAll(" ", "+");
162 
163             searchParams.setSearchQuery(queryStr);
164             URL url = new URL(queryStr);
165             URLConnection urlc = null;
166             urlc = url.openConnection();
167             urlc.setDoOutput(true);
168             urlc.setAllowUserInteraction(false);
169             BufferedReader br = new BufferedReader(new InputStreamReader(urlc.getInputStream()));
170             StringBuilder sb = new StringBuilder();
171             String line;
172             while ((line = br.readLine()) != null) {
173                 sb.append(line);
174                 sb.append("\n");
175             }
176             br.close();
177             response = sb.toString();
178         }
179         catch (Exception e) {
180 
181         }
182         return response;
183     }
184 
185     public String getFieldList(String docType) {
186         String fieldList = "";
187         String holdingFields = HOLDINGS_FIELDS;
188         String itemFields = ITEM_FIELDS;
189         String instanceFields = INSTANCE_FIELDS;
190         String bibFields = BIB_FIELDS;
191 
192         if (docType.equalsIgnoreCase(BIBLIOGRAPHIC)) {
193             fieldList = bibFields;
194 
195         }
196         else if (docType.equalsIgnoreCase(INSTANCE)) {
197             fieldList = instanceFields;
198 
199         }
200         else if (docType.equalsIgnoreCase(HOLDINGS)) {
201             fieldList = holdingFields;
202 
203         }
204         else if (docType.equalsIgnoreCase(ITEM)) {
205             fieldList = itemFields;
206         }
207         return fieldList;
208     }
209 
210 
211     public static void setDocSearchUrl(String docSearchUrl) {
212     }
213 
214     public static String getDocSearchUrl() {
215         return docSearchUrl;
216     }
217 
218     public String buildQuery(SearchParams searchParams) {
219         StringBuffer query = new StringBuffer();
220         String searchType = searchParams.getSearchType();
221         query.append(SolrServerManager.getInstance().getSolrCoreURL() + "/select");
222         buildInitialQuery(query, searchParams);
223         if (searchParams.getSearchFieldsList().size() > 0) {
224             query.append("AND(");
225         }
226         query.append(buildQueryWithSearchParameters(searchParams.getSearchFieldsList()));
227         if (searchParams.getResultPageSize() != null) {
228             query.append("&rows=" + searchParams.getResultPageSize());
229         }
230         if (searchParams.getResultFromIndex() != null) {
231             query.append("&start=" + searchParams.getResultFromIndex());
232         }
233         List<String> facetFieldList = searchParams.getFacetFieldList();
234         query.append(buildQueryWithFacetParameters(facetFieldList, 1, 10));
235         query.append(buildQueryWithSortFields(searchParams.getSortField(), searchParams.getSortOrder()));
236         query.append(buildQueryWithFieldListParameters(searchParams.getFieldList()));
237         Map<String, String> facetTermsMap = searchParams.getFacetTermsMap();
238         query.append(buildFilterQuery(facetTermsMap));
239 
240         return query.toString();
241     }
242 
243 
244     public String buildQueryWithSearchParameters(List<SearchCondition> searchFieldsList) {
245         SearchCondition docSearchFieldsDTO = null;
246         StringBuffer queryStringbuffer = new StringBuffer();
247         StringBuffer highlightBuffer = new StringBuffer("&hl.fl=");
248         if (searchFieldsList != null && searchFieldsList.size() > 0) {
249 
250             for (int i = 0; i < searchFieldsList.size(); i++) {
251                 int searchScopeAddLimit = i;
252                 docSearchFieldsDTO = searchFieldsList.get(i);
253                 if (docSearchFieldsDTO.getOperator() != null) {
254                     //queryStringbuffer.append(docSearchFieldsDTO.getOperator());
255                 }
256                 queryStringbuffer.append("(");
257                 if (docSearchFieldsDTO.getDocField().equalsIgnoreCase("all")) {
258                     queryStringbuffer.append("all_text");
259                     highlightBuffer.append("*");
260 
261                 }
262                 else {
263                     queryStringbuffer.append(docSearchFieldsDTO.getDocField());
264                     highlightBuffer.append(docSearchFieldsDTO.getDocField());
265 
266                     if (i != searchFieldsList.size() - 1) {
267                         highlightBuffer.append(",");
268                     }
269                 }
270                 queryStringbuffer.append(":");
271                 String searchScope = docSearchFieldsDTO.getSearchScope();
272                 String searchText = docSearchFieldsDTO.getSearchText();
273                 String searchOperator = docSearchFieldsDTO.getOperator();
274                 searchText = searchText.toLowerCase();
275                 LOG.debug("searchText-->" + searchText);
276                 searchText = searchText.replaceAll("[~!(){}\\[\\]':]+"," ");
277                 String searchTextVal = null;
278                 if (searchText.length() > 0) {
279                     queryStringbuffer.append("(");
280                     if (searchScope.equalsIgnoreCase("AND")) {
281                         searchText = searchText.replaceAll("\\s+", " ");
282                         searchTextVal = searchText.trim().replace(" ", " AND ");
283                     }
284                     else if (searchScope.equalsIgnoreCase("OR")) {
285                         searchText = searchText.replaceAll("\\s+", " ");
286                         searchTextVal = searchText.trim().replace(" ", " OR ");
287                     }
288                     else if (searchScope.equalsIgnoreCase("phrase")) {
289                         searchTextVal = "\"" + searchText + "\"";
290                     }
291                     try {
292                         searchTextVal = URLEncoder.encode(searchTextVal, "UTF-8");
293                     }
294                     catch (UnsupportedEncodingException e) {
295                         e.printStackTrace();
296                     }
297                     queryStringbuffer.append(searchTextVal);
298                     LOG.debug("searchTextVal............" + searchTextVal + "........" + queryStringbuffer.toString());
299                     queryStringbuffer.append(")");
300                 }
301                 queryStringbuffer.append(")");
302                 ++searchScopeAddLimit;
303                 if (searchScopeAddLimit != searchFieldsList.size()) {
304                     queryStringbuffer.append(searchOperator);
305                 }
306             }
307             queryStringbuffer.append(")");
308             queryStringbuffer.append(highlightBuffer.toString());
309 
310             queryStringbuffer.append("&hl=true");
311         }
312 
313 
314         return queryStringbuffer.toString();
315     }
316 
317     public String buildQueryWithFacetParameters(List<String> facetsParametersList, int facetMinCount, int facetLimit) {
318         String facetFieldName = "";
319         String queryWithFacetParameters = "";
320         if (facetsParametersList != null) {
321             StringBuffer facetsQueryStringbuffer = new StringBuffer();
322 
323             facetsQueryStringbuffer.append("&facet=true");
324 
325             facetsQueryStringbuffer.append("&facet.mincount=" + facetMinCount);
326 
327             facetsQueryStringbuffer.append("&");
328 
329             for (int i = 0; i < facetsParametersList.size(); i++) {
330                 facetFieldName = facetsParametersList.get(i);
331                 facetsQueryStringbuffer.append("facet.field=" + facetFieldName);
332                 facetsQueryStringbuffer.append("&");
333 
334             }
335             queryWithFacetParameters = facetsQueryStringbuffer.substring(0, facetsQueryStringbuffer.length() - 1);
336         }
337         return queryWithFacetParameters;
338     }
339 
340 
341     public String buildQueryWithSortFields(String sortField, String sortOrder) {
342         StringBuffer sortFieldsQuery = new StringBuffer();
343         if (null != sortField) {
344             sortFieldsQuery.append("&");
345             sortFieldsQuery.append("sort=");
346             sortFieldsQuery.append(sortField);
347             if (null != sortOrder) {
348                 sortFieldsQuery.append(" ");
349                 sortFieldsQuery.append(sortOrder);
350             }
351         }
352         return sortFieldsQuery.toString();
353     }
354 
355     public String buildQueryWithFieldListParameters(List<String> fieldsList) {
356         String queryWithFieldListParameters = "";
357         if (fieldsList != null) {
358             StringBuffer fieldsListQueryStringbuffer = new StringBuffer();
359             fieldsListQueryStringbuffer.append("&");
360             fieldsListQueryStringbuffer.append("fl=");
361             for (int i = 0; i < fieldsList.size(); i++) {
362                 fieldsListQueryStringbuffer.append(fieldsList.get(i));
363                 fieldsListQueryStringbuffer.append(",");
364             }
365             queryWithFieldListParameters = fieldsListQueryStringbuffer
366                     .substring(0, fieldsListQueryStringbuffer.length() - 1);
367         }
368         return queryWithFieldListParameters;
369     }
370 
371     public static String convertListToStringFieldValues(Map<String, String> map) {
372         StringBuffer sb = new StringBuffer();
373         Set set = map.keySet();
374         Iterator<String> ite = set.iterator();
375         while (ite.hasNext()) {
376             sb.append(ite.next());
377             sb.append("|");
378         }
379         String str = sb.toString();
380         if (str != null && str.length() > 0) {
381             str = str.substring(0, str.length() - 1);
382         }
383         return str;
384     }
385 
386     public String buildFilterQuery(Map<String, String> facetTermsMap) {
387         String filterQuery = "";
388         int temp = 0;
389         int tokenInt = 0;
390         if ((null != facetTermsMap) && (facetTermsMap.size() > 0)) {
391 
392             String facetTerms = convertListToStringFieldValues(facetTermsMap);
393             StringBuffer facetQueryTemp = new StringBuffer();
394             facetQueryTemp.append("&terms=" + facetTerms);
395             facetQueryTemp.append("&fq=");
396             StringTokenizer sttoken = new StringTokenizer(facetTerms, "|");
397             String token;
398             while (sttoken.hasMoreElements()) {
399                 token = sttoken.nextToken();
400                 facetQueryTemp.append("(");
401                 facetQueryTemp.append(facetTermsMap.get(token));
402                 facetQueryTemp.append(":\"");
403                 facetQueryTemp.append(token);
404                 facetQueryTemp.append("\")");
405                 facetQueryTemp.append("AND");
406             }
407             if (facetQueryTemp.length() > 0) {
408                 filterQuery = (facetQueryTemp.toString().substring(0, facetQueryTemp.toString().length() - 3));
409             }
410         }
411         return filterQuery;
412     }
413 
414 
415     /**
416      * @param query
417      * @param searchParams Usage: This method builds initial SOLR query with DocType and DocFormat as SolrParams
418      */
419     private void buildInitialQuery(StringBuffer query, SearchParams searchParams) {
420         query.append("?q=");
421         //query.append("(DocType:" + searchParams.getDocType() + ")");
422         if (searchParams.getDocFormat().equalsIgnoreCase("marc")) {
423             query.append("((DocType:" + searchParams.getDocType() + ")" + "OR(DocType:item))");
424         }
425         else {
426             query.append("(DocType:" + searchParams.getDocType() + ")");
427         }
428 
429         if (searchParams.getDocFormat() != null && !searchParams.getDocFormat().equalsIgnoreCase("all")) {
430             if ("dublin".equals(searchParams.getDocFormat())) {
431                 searchParams.setDocFormat("dublin");
432             }
433             query.append("AND(DocFormat:" + searchParams.getDocFormat() + ")");
434         }
435     }
436 
437 }