001package org.kuali.ole.serviceimpl;
002
003import org.kuali.ole.OleSRUConstants;
004import org.kuali.ole.bo.cql.CQLResponseBO;
005import org.kuali.ole.bo.diagnostics.OleSRUDiagnostics;
006import org.kuali.ole.bo.serachRetrieve.OleSRUData;
007import org.kuali.ole.bo.serachRetrieve.OleSRUSearchRetrieveResponse;
008import org.kuali.ole.docstore.common.client.DocstoreClient;
009import org.kuali.ole.docstore.common.document.BibTree;
010import org.kuali.ole.docstore.common.document.HoldingsTree;
011import org.kuali.ole.docstore.common.search.*;
012import org.kuali.ole.docstore.engine.client.DocstoreLocalClient;
013import org.kuali.ole.docstore.engine.service.index.solr.BibConstants;
014import org.kuali.ole.docstore.model.enums.DocType;
015import org.kuali.ole.handler.OleSRUOpacXMLResponseHandler;
016import org.kuali.ole.service.OleCQLQueryParserService;
017import org.kuali.ole.service.OleDiagnosticsService;
018import org.kuali.ole.service.OleSRUDataService;
019import org.kuali.ole.service.OleSearchRetrieveOperationService;
020import org.kuali.rice.core.api.config.property.Config;
021import org.kuali.rice.core.api.config.property.ConfigContext;
022import org.slf4j.Logger;
023import org.slf4j.LoggerFactory;
024import java.util.ArrayList;
025import java.util.List;
026import java.util.Map;
027
028/**
029 * Created with IntelliJ IDEA.
030 * User: ?
031 * Date: 7/9/12
032 * Time: 6:50 PM
033 * To change this template use File | Settings | File Templates.
034 */
035public class OleSearchRetrieveOperationServiceImpl implements OleSearchRetrieveOperationService {
036
037    private Logger LOG = LoggerFactory.getLogger(this.getClass());
038    public OleSRUDataService oleSRUDataService;
039    public OleDiagnosticsService oleDiagnosticsService;
040    public OleCQLQueryParserService oleCQLQueryParserService;
041    private Config currentContextConfig;
042    private SearchParams searchParams = new SearchParams();
043    private SearchCondition searchCondition = null;
044    private SearchField searchField = null;
045    private DocstoreClient docstoreClient;
046    private SearchResultField searchResultFields = null;
047
048    public OleSearchRetrieveOperationServiceImpl() {
049        oleSRUDataService = new OleSRUDataServiceImpl();
050        oleDiagnosticsService = new OleDiagnosticsServiceImpl();
051        oleCQLQueryParserService = new OleCQLQueryParserServiceImpl();
052    }
053
054    /**
055     * it will return a OPAC response xml  ( overall xml )
056     *
057     * @param reqParamMap
058     * @param cqlParseBO
059     * @return OPAC xml response
060     */
061    public String getSearchRetriveResponse(Map reqParamMap, CQLResponseBO cqlParseBO) {
062
063        SearchParams searchParams = createSearchParams(cqlParseBO, true);
064        buildSearchConditions(searchParams);
065        /*SearchCondition condition = new SearchCondition();
066        condition.setOperator("AND");
067        SearchField field = new SearchField();
068        field.setFieldName("DocFormat");
069        String format = (String)reqParamMap.get(OleSRUConstants.RECORD_SCHEMA);
070        if(format.equalsIgnoreCase("OPAC")){
071            format = "marc";
072        }
073        field.setFieldValue(format);
074        condition.setSearchField(field);
075        searchParams.getSearchConditions().add(condition);*/
076        searchParams.setStartIndex(Integer.parseInt(reqParamMap.get("startRecord").toString()));
077        searchParams.setPageSize(Integer.parseInt(reqParamMap.get("maximumRecords").toString()));
078        if (searchParams == null) {
079            OleSRUDiagnostics oleSRUDiagnostics = oleDiagnosticsService.getDiagnosticResponse(getCurrentContextConfig().getProperty(OleSRUConstants.INVALID_QUERY_DIAGNOSTIC_MSG));
080            OleSRUSearchRetrieveResponse oleSRUSearchRetrieveResponse = new OleSRUSearchRetrieveResponse();
081            oleSRUSearchRetrieveResponse.setVersion((String) reqParamMap.get(OleSRUConstants.VERSION));
082            oleSRUSearchRetrieveResponse.setOleSRUDiagnostics(oleSRUDiagnostics);
083            OleSRUOpacXMLResponseHandler oleSRUOpacXMLResponseHandler = new OleSRUOpacXMLResponseHandler();
084            return oleSRUOpacXMLResponseHandler.toXML(oleSRUSearchRetrieveResponse, (String) reqParamMap.get("recordSchema"));
085
086        }
087        // add q=staffOnlyFlag:false to search
088        FacetCondition staffOnlyFacet = new FacetCondition();
089        staffOnlyFacet.setFieldName(BibConstants.STAFF_ONLY_FLAG);
090        staffOnlyFacet.setFieldValue(OleSRUConstants.SRU_STAFF_ONLY_FLAG);
091        searchParams.getFacetConditions().add(staffOnlyFacet);
092
093        // add fq=DocType:bibliographic to search
094        FacetCondition docTypeFacet = new FacetCondition();
095        docTypeFacet.setFieldName(BibConstants.DOC_TYPE);
096        docTypeFacet.setFieldValue(OleSRUConstants.BIBLIOGRAPHIC);
097        searchParams.getFacetConditions().add(docTypeFacet);
098
099        OleSRUSearchRetrieveResponse oleSRUSearchRetrieveResponse = new OleSRUSearchRetrieveResponse();
100        oleSRUSearchRetrieveResponse.setVersion((String) reqParamMap.get(OleSRUConstants.VERSION));
101        OleSRUOpacXMLResponseHandler oleSRUOpacXMLResponseHandler = new OleSRUOpacXMLResponseHandler();
102        List oleSRUBibIdList = getBibIds(reqParamMap, searchParams);
103        /*if(oleSRUBibIdList!=null && oleSRUBibIdList.size()>0 && oleSRUBibIdList.get(0) instanceof String){
104            if(oleSRUBibIdList.get(0).equals("Invalid Local Id")){
105                OleSRUDiagnostics oleSRUDiagnostics = oleDiagnosticsService.getDiagnosticResponse("Local Id Value Should be a Number");
106                oleSRUSearchRetrieveResponse.setOleSRUDiagnostics(oleSRUDiagnostics);
107                return oleSRUOpacXMLResponseHandler.toXML(oleSRUSearchRetrieveResponse,(String)reqParamMap.get("recordSchema"));
108            }
109            OleSRUDiagnostics oleSRUDiagnostics = oleDiagnosticsService.getDiagnosticResponse(getCurrentContextConfig().getProperty(OleSRUConstants.INVALID_QUERY_DIAGNOSTIC_MSG));
110            oleSRUSearchRetrieveResponse.setOleSRUDiagnostics(oleSRUDiagnostics);
111            return oleSRUOpacXMLResponseHandler.toXML(oleSRUSearchRetrieveResponse,(String)reqParamMap.get("recordSchema"));
112        }*/
113        if (oleSRUBibIdList == null) {
114            OleSRUDiagnostics oleSRUDiagnostics = oleDiagnosticsService.getDiagnosticResponse(getCurrentContextConfig().getProperty(OleSRUConstants.SERVER_DIAGNOSTIC_MSG));
115            oleSRUSearchRetrieveResponse.setOleSRUDiagnostics(oleSRUDiagnostics);
116            return oleSRUOpacXMLResponseHandler.toXML(oleSRUSearchRetrieveResponse, (String) reqParamMap.get("recordSchema"));
117
118        }
119
120        String opacXML = oleSRUDataService.getOPACXMLSearchRetrieveResponse(oleSRUBibIdList, reqParamMap);
121        String styleSheet = (String) reqParamMap.get(OleSRUConstants.STYLE_SHEET);
122        if (styleSheet != null) {
123            opacXML = opacXML.replace("<?xml version=\"1.0\" encoding=\"UTF-8\"?>", "<?xml version=\"1.0\" encoding=\"UTF-8\"?> \n <?xml-stylesheet type=\"text/xsl\" href=\"" + styleSheet + "\"?>");
124        }
125        opacXML = opacXML.replace("<collection xmlns=\"http://www.loc.gov/MARC21/slim\">", "");
126        opacXML = opacXML.replace("<collection>","");
127        opacXML = opacXML.replace("</collection>", "");
128        LOG.info("opac xml response ---->  " + opacXML);
129        return opacXML;
130    }
131
132
133    private void buildSearchConditions(SearchParams searchParams) {
134
135        List<SearchCondition> searchConditions = searchParams.getSearchConditions();
136        if (searchConditions.size() >1 && searchConditions.size() <= 2) {
137            if(searchConditions.get(0)!=null && searchConditions.get(1)!=null){
138                searchConditions.get(0).setOperator(searchConditions.get(1).getOperator());
139            }
140        } else if (searchConditions.size() > 2) {
141            for (int i = 0; i < searchConditions.size() - 1; i++) {
142                if(searchConditions.get(i)!=null && searchConditions.get(i)!=null){
143                    SearchCondition sc1 = searchConditions.get(i);
144                    SearchCondition sc2 = searchConditions.get(i + 1);
145                    sc1.setOperator(sc2.getOperator());
146                }
147            }
148        }
149    }
150
151    private Config getCurrentContextConfig() {
152        if (null == currentContextConfig) {
153            currentContextConfig = ConfigContext.getCurrentContextConfig();
154        }
155        return currentContextConfig;
156    }
157
158    public void setCurrentContextConfig(Config currentContextConfig) {
159        this.currentContextConfig = currentContextConfig;
160    }
161
162    /**
163     * .
164     * this will get the proper query from the oleCQLQueryParserService
165     *
166     * @param cqlResponseBO object
167     * @return query as a string
168     */
169    /*public String getSolrQueryFromCQLParseBO(CQLResponseBO cqlResponseBO) {
170        String solrQuery = null;
171        solrQuery = oleCQLQueryParserService.getSolrQueryFromCQLBO(cqlResponseBO);
172        LOG.info("solr Query ------> " + solrQuery);
173        return "(" + solrQuery + ")";
174    }*/
175    private SearchParams createSearchParams(CQLResponseBO cqlResponseBO, boolean flag) {
176        searchResultFields = new SearchResultField();
177        if (cqlResponseBO.getLeftOperand() != null) {
178            CQLResponseBO leftOperand = cqlResponseBO.getLeftOperand();
179            createSearchParams(leftOperand, false);
180            searchField = setSearchField(cqlResponseBO.getLeftOperand());
181            if (searchField != null) {
182                searchCondition = setSearchCondition(cqlResponseBO.getLeftOperand(), searchField);
183            }
184            if (null != cqlResponseBO.getLeftOperand().getBooleanTagValue() && null != cqlResponseBO.getLeftOperand().getBooleanTagValue().getValue()) {
185                searchCondition.setOperator(cqlResponseBO.getBooleanTagValue().getValue());
186            }
187            if (searchCondition != null && searchField != null) {
188                searchParams.getSearchConditions().add(searchCondition);
189            }
190        }
191        if (cqlResponseBO.getRightOperand() != null) {
192            CQLResponseBO rightOperand = cqlResponseBO.getRightOperand();
193            createSearchParams(rightOperand, false);
194            searchField = setSearchField(cqlResponseBO.getRightOperand());
195            if (searchField != null) {
196                searchCondition = setSearchCondition(cqlResponseBO.getRightOperand(), searchField);
197            }
198            if (null != cqlResponseBO.getBooleanTagValue() && null != cqlResponseBO.getBooleanTagValue().getValue()) {
199                searchCondition.setOperator(cqlResponseBO.getBooleanTagValue().getValue());
200            }
201            if (searchCondition != null && searchField != null) {
202                searchParams.getSearchConditions().add(searchCondition);
203            }
204        }
205        if (cqlResponseBO.getTriple() != null) {
206            CQLResponseBO triple = cqlResponseBO.getTriple();
207            if (triple != null) {
208                createSearchParams(triple, false);
209                searchField = setSearchField(triple);
210                if (searchField != null)
211                    searchCondition = setSearchCondition(triple, searchField);
212            }
213            if (null != cqlResponseBO.getBooleanTagValue() && null != triple.getBooleanTagValue().getValue()) {
214                searchCondition.setOperator(triple.getBooleanTagValue().getValue());
215            }
216            if (searchCondition != null && searchField != null) {
217                searchParams.getSearchConditions().add(searchCondition);
218            }
219        }
220        if (cqlResponseBO.getSearchClauseTag() != null) {
221            SearchField searchField = setSearchField(cqlResponseBO);
222            SearchCondition searchCondition = setSearchCondition(cqlResponseBO, searchField);
223            SearchParams searchParams = new SearchParams();
224            searchResultFields.setDocType(OleSRUConstants.BIBLIOGRAPHIC);
225            searchResultFields.setFieldName("id");
226            searchParams.getSearchResultFields().add(searchResultFields);
227            searchParams.getSearchConditions().add(searchCondition);
228            return searchParams;
229        }
230
231        if (flag) {
232            searchResultFields.setDocType(OleSRUConstants.BIBLIOGRAPHIC);
233            searchResultFields.setFieldName("id");
234            searchParams.getSearchResultFields().add(searchResultFields);
235            return searchParams;
236        }
237        return null;
238    }
239
240    private List getBibIds(Map reqParamMap, SearchParams searchParams) {
241        SearchResponse searchResponse = getDocstoreClient().search(searchParams);
242        List bibIds = new ArrayList();
243        List<OleSRUData> oleSRUDataList = new ArrayList<>();
244        for (SearchResult searchResult : searchResponse.getSearchResults()) {
245            OleSRUData oleSRUData ;
246            for (SearchResultField searchResultField : searchResult.getSearchResultFields()) {
247                if (searchResultField.getDocType().equalsIgnoreCase(DocType.BIB.getCode())) {
248                    if (searchResultField.getFieldName().equalsIgnoreCase("id")) {
249                        bibIds.add(searchResultField.getFieldValue());
250                        oleSRUData = new OleSRUData();
251                        oleSRUData.setBibId(searchResultField.getFieldValue());
252                        BibTree bib = getDocstoreClient().retrieveBibTree(searchResultField.getFieldValue());
253                        List<HoldingsTree> holdingsTrees = bib.getHoldingsTrees();
254                        List<String> ids = new ArrayList<>();
255                        for(HoldingsTree holdingsTree:holdingsTrees){
256                            ids.add(holdingsTree.getHoldings().getId());
257                        }
258                        /*ListIterator<HoldingsTree> holdingsTreeListIterator = holdingsTrees.listIterator();
259                        List<String> ids = new ArrayList<>();
260                        while(holdingsTreeListIterator.hasNext()){
261                            ids.add(holdingsTreeListIterator.next().getId());
262                        }*/
263                        oleSRUData.setInstanceIds(ids);
264                        oleSRUDataList.add(oleSRUData);
265                    }
266                }
267            }
268        }
269        Integer size = searchResponse.getTotalRecordCount();
270        reqParamMap.put("numberOfRecords", size.longValue());
271        return oleSRUDataList;
272    }
273
274    private DocstoreClient getDocstoreClient() {
275
276        if (docstoreClient == null) {
277            docstoreClient = new DocstoreLocalClient();
278        }
279        return docstoreClient;
280    }
281
282    private SearchField setSearchField(CQLResponseBO cqlResponseBO) {
283        searchField = null;
284        if (cqlResponseBO != null) {
285            if (cqlResponseBO.getSearchClauseTag() != null) {
286                searchField = new SearchField();
287                if (cqlResponseBO.getSearchClauseTag().getIndex().equalsIgnoreCase(OleSRUConstants.TITLE) ||
288                                cqlResponseBO.getSearchClauseTag().getIndex().equalsIgnoreCase(OleSRUConstants.CS_TITLE)) {
289                    searchField.setFieldName(OleSRUConstants.TITLE_SEARCH);
290                } else if (cqlResponseBO.getSearchClauseTag().getIndex().equalsIgnoreCase(OleSRUConstants.AUTHOR) ||
291                                cqlResponseBO.getSearchClauseTag().getIndex().equalsIgnoreCase(OleSRUConstants.CS_AUTHOR)) {
292                    searchField.setFieldName(OleSRUConstants.AUTHOR_SEARCH);
293                } else if (cqlResponseBO.getSearchClauseTag().getIndex().equalsIgnoreCase(OleSRUConstants.PUBLISHER) ||
294                                cqlResponseBO.getSearchClauseTag().getIndex().equalsIgnoreCase(OleSRUConstants.CS_PUBLISHER)) {
295                    searchField.setFieldName(OleSRUConstants.PUBLISHER_SEARCH);
296                } else if (cqlResponseBO.getSearchClauseTag().getIndex().equalsIgnoreCase(OleSRUConstants.PUBLICATION_DATE) ||
297                                cqlResponseBO.getSearchClauseTag().getIndex().equalsIgnoreCase(OleSRUConstants.PUB_DATE) ||
298                                cqlResponseBO.getSearchClauseTag().getIndex().equalsIgnoreCase(OleSRUConstants.CS_PUBLICATION_DATE) ||
299                                cqlResponseBO.getSearchClauseTag().getIndex().equalsIgnoreCase(OleSRUConstants.CS_PUB_DATE)) {
300                    searchField.setFieldName(OleSRUConstants.PUBLICATION_DATE_SEARCH);
301                } else if (cqlResponseBO.getSearchClauseTag().getIndex().equalsIgnoreCase(OleSRUConstants.ISBN) ||
302                                cqlResponseBO.getSearchClauseTag().getIndex().equalsIgnoreCase(OleSRUConstants.CS_ISBN)) {
303                    searchField.setFieldName(OleSRUConstants.ISBN_SEARCH);
304                } else if (cqlResponseBO.getSearchClauseTag().getIndex().equalsIgnoreCase(OleSRUConstants.ISSN) ||
305                                cqlResponseBO.getSearchClauseTag().getIndex().equalsIgnoreCase(OleSRUConstants.CS_ISSN)) {
306                    searchField.setFieldName(OleSRUConstants.ISSN_SEARCH);
307                } else if (cqlResponseBO.getSearchClauseTag().getIndex().equalsIgnoreCase(OleSRUConstants.LOCALID) ||
308                                cqlResponseBO.getSearchClauseTag().getIndex().equalsIgnoreCase(OleSRUConstants.CS_LOCALID)) {
309                    searchField.setFieldName(OleSRUConstants.LOCALID_SEARCH);
310                } else if (cqlResponseBO.getSearchClauseTag().getIndex().equalsIgnoreCase(OleSRUConstants.SUBJECT) ||
311                                cqlResponseBO.getSearchClauseTag().getIndex().equalsIgnoreCase(OleSRUConstants.CS_SUBJECT)) {
312                    searchField.setFieldName(OleSRUConstants.SUBJECT_SEARCH);
313                } else if (cqlResponseBO.getSearchClauseTag().getIndex().equalsIgnoreCase(OleSRUConstants.CHOICE) ||
314                                cqlResponseBO.getSearchClauseTag().getIndex().equalsIgnoreCase(OleSRUConstants.CS_CHOICE)) {
315                    searchField.setFieldName(OleSRUConstants.ALL_TEXT);
316                }
317            }
318            if (cqlResponseBO.getSearchClauseTag() != null && cqlResponseBO.getSearchClauseTag().getTerm() != null) {
319                searchField.setFieldValue(cqlResponseBO.getSearchClauseTag().getTerm());
320            }
321        }
322        return searchField;
323    }
324
325    private SearchCondition setSearchCondition(CQLResponseBO cqlResponseBO, SearchField searchField) {
326        searchCondition = new SearchCondition();
327        if (cqlResponseBO.getSearchClauseTag() != null && cqlResponseBO.getSearchClauseTag().getRelationTag() != null && cqlResponseBO.getSearchClauseTag().getRelationTag().getValue() != null && cqlResponseBO.getSearchClauseTag().getRelationTag().getValue().equalsIgnoreCase("any")) {
328            searchCondition.setSearchScope("or");
329        } else if (cqlResponseBO.getSearchClauseTag() != null && cqlResponseBO.getSearchClauseTag().getRelationTag() != null && cqlResponseBO.getSearchClauseTag().getRelationTag().getValue() != null && cqlResponseBO.getSearchClauseTag().getRelationTag().getValue().equalsIgnoreCase("all")) {
330            searchCondition.setSearchScope("and");
331        }else if (cqlResponseBO.getSearchClauseTag() != null && cqlResponseBO.getSearchClauseTag().getRelationTag() != null && cqlResponseBO.getSearchClauseTag().getRelationTag().getValue() != null && cqlResponseBO.getSearchClauseTag().getRelationTag().getValue().equalsIgnoreCase("adj")) {
332            searchCondition.setSearchScope("phrase");
333        } else {
334            searchCondition.setSearchScope("and");
335        }
336        if (null != searchField)
337            searchCondition.setSearchField(searchField);
338        if (null != cqlResponseBO && null != cqlResponseBO.getBooleanTagValue()) {
339            searchCondition.setOperator(cqlResponseBO.getBooleanTagValue().getValue());
340        }
341        return searchCondition;
342    }
343}