001/*
002 * Copyright 2011 The Kuali Foundation.
003 * 
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 * 
008 * http://www.opensource.org/licenses/ecl2.php
009 * 
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.ole.select.service.impl;
017
018import org.apache.commons.collections.CollectionUtils;
019import org.apache.commons.lang3.StringUtils;
020import org.kuali.ole.docstore.common.client.DocstoreClientLocator;
021import org.kuali.ole.docstore.common.document.Bib;
022import org.kuali.ole.docstore.common.document.Holdings;
023import org.kuali.ole.docstore.common.document.Item;
024import org.kuali.ole.docstore.common.document.ItemOleml;
025import org.kuali.ole.docstore.common.document.content.enums.DocType;
026import org.kuali.ole.docstore.common.search.SearchResponse;
027import org.kuali.ole.docstore.common.search.SearchResult;
028import org.kuali.ole.docstore.common.search.SearchResultField;
029import org.kuali.ole.docstore.engine.service.index.solr.BibConstants;
030import org.kuali.ole.docstore.engine.service.index.solr.ItemConstants;
031import org.kuali.ole.select.OleSelectConstant;
032import org.kuali.ole.select.businessobject.DocInfoBean;
033import org.kuali.ole.select.lookup.DocData;
034import org.kuali.ole.select.service.BibInfoWrapperService;
035import org.kuali.ole.sys.OLEConstants;
036import org.kuali.ole.sys.context.SpringContext;
037import org.kuali.ole.sys.service.NonTransactional;
038import org.kuali.rice.core.api.config.property.ConfigurationService;
039import org.kuali.rice.core.framework.persistence.ojb.dao.PlatformAwareDaoBaseOjb;
040import org.kuali.rice.krad.util.GlobalVariables;
041import org.kuali.rice.krad.util.KRADConstants;
042
043import java.util.*;
044
045/**
046 * This class is the implementation class for OleDocStoreSearchService
047 * to integrate docstore search with database search.
048 */
049@NonTransactional
050public class OleDocStoreSearchService extends PlatformAwareDaoBaseOjb implements org.kuali.ole.select.service.OleDocStoreSearchService {
051
052    private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(OleDocStoreSearchService.class);
053    static HashMap<String, String> cache = new HashMap<String, String>();
054    private static transient BibInfoWrapperService bibInfoWrapperService;
055    private DocstoreClientLocator docstoreClientLocator;
056
057    public static BibInfoWrapperService getBibInfoWrapperService() {
058        if (bibInfoWrapperService == null) {
059            bibInfoWrapperService = SpringContext.getBean(BibInfoWrapperService.class);
060        }
061        return bibInfoWrapperService;
062    }
063
064    public DocstoreClientLocator getDocstoreClientLocator() {
065
066        if (docstoreClientLocator == null) {
067            docstoreClientLocator = SpringContext.getBean(DocstoreClientLocator.class);
068
069        }
070        return docstoreClientLocator;
071    }
072    
073/*    public boolean createCriteria(Object arg0, String arg1, String arg2, Object arg3) {
074        // TODO Auto-generated method stub
075        return false;
076    }
077
078    
079    public boolean createCriteria(Object arg0, String arg1, String arg2, boolean arg3, boolean arg4, Object arg5) {
080        // TODO Auto-generated method stub
081        return false;
082    }
083*/
084
085
086    /**
087     * This method returns list of docdata populated through docstore search
088     *
089     * @param arg1
090     * @return
091     * @throws Exception
092     */
093    public List<DocData> getDocResult(Map arg1) throws Exception {
094        BibInfoWrapperService docStore = SpringContext.getBean(BibInfoWrapperServiceImpl.class);
095        // changed for jira 2144 starts
096        List<DocInfoBean> docStoreResult = docStore.searchBibInfo(arg1);
097        // changed for jira 2144 ends
098        List<DocData> ress = new ArrayList<DocData>(0);
099        ress = getDocResult(docStoreResult);
100        return ress;
101    }
102
103
104
105    public List<DocData> getDocSearchResults(Map<String,String> criteria,String attr, List<Object> vals,boolean isMultiValuedSearch){
106        int maxLimit = Integer.parseInt(SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString(OLEConstants.DOCSEARCH_ORDERQUEUE_LIMIT_KEY));
107        String title="";
108        if (criteria != null) {
109            for (Map.Entry<String, String> entry : criteria.entrySet()) {
110                if (entry.getKey().equals("title")) {
111                    title = entry.getValue();
112                }
113            }
114        }
115        List<DocData> results=new ArrayList<DocData>();
116        try {
117            org.kuali.ole.docstore.common.document.Item item = new ItemOleml();
118            org.kuali.ole.docstore.common.search.SearchParams searchParams = new org.kuali.ole.docstore.common.search.SearchParams();
119            searchParams.setPageSize(maxLimit);
120            SearchResponse searchResponse = null;
121            HashMap titleIdMap = new HashMap();
122            //searchParams.getSearchConditions().add(searchParams.buildSearchCondition("", searchParams.buildSearchField(org.kuali.ole.docstore.common.document.content.enums.DocType.ITEM.getCode(), "Title_display", title), ""));
123            if(isMultiValuedSearch){
124                boolean isTitleExist=false;
125                if (StringUtils.isNotBlank(title)) {
126                    searchParams.getSearchConditions().add(searchParams.buildSearchCondition("AND", searchParams.buildSearchField(org.kuali.ole.docstore.common.document.content.enums.DocType.ITEM.getCode(),BibConstants.TITLE_SEARCH, title), "AND"));
127                    isTitleExist=true;
128                }
129                if(CollectionUtils.isNotEmpty(vals)){
130                    int loop = 0;
131                    for (Object iv : vals) {
132                        String id = iv.toString();
133                        boolean isIdExists = titleIdMap.containsValue(id);
134                        if(isTitleExist){
135                            searchParams.getSearchConditions().add(searchParams.buildSearchCondition("phrase", searchParams.buildSearchField(org.kuali.ole.docstore.common.document.content.enums.DocType.ITEM.getCode(), ItemConstants.BIB_IDENTIFIER, id), "AND"));
136                        } else {
137                            searchParams.getSearchConditions().add(searchParams.buildSearchCondition("phrase", searchParams.buildSearchField(org.kuali.ole.docstore.common.document.content.enums.DocType.ITEM.getCode(), ItemConstants.BIB_IDENTIFIER, id), "OR"));
138                        }
139
140                        loop++;
141                        if (loop == maxLimit)
142                            break;
143                    }
144                }
145
146                //searchParams.getSearchConditions().add(searchParams.buildSearchCondition("", searchParams.buildSearchField(org.kuali.ole.docstore.common.document.content.enums.DocType.ITEM.getCode(), BibConstants.TITLE_SEARCH, title), ""));
147            } else {
148                if (StringUtils.isNotBlank(title)) {
149                    searchParams.getSearchConditions().add(searchParams.buildSearchCondition("any", searchParams.buildSearchField(org.kuali.ole.docstore.common.document.content.enums.DocType.ITEM.getCode(),BibConstants.TITLE_SEARCH, title), ""));
150                }
151            }
152
153            searchParams.getSearchResultFields().add(searchParams.buildSearchResultField(DocType.ITEM.getCode(), ItemConstants.BIB_IDENTIFIER));
154            searchParams.getSearchResultFields().add(searchParams.buildSearchResultField(DocType.ITEM.getCode(), Bib.TITLE));
155            searchParams.getSearchResultFields().add(searchParams.buildSearchResultField(DocType.ITEM.getCode(), Bib.AUTHOR));
156            searchParams.getSearchResultFields().add(searchParams.buildSearchResultField(DocType.ITEM.getCode(), BibConstants.PUBLICATIONDATE_DISPLAY));
157            searchParams.getSearchResultFields().add(searchParams.buildSearchResultField(DocType.ITEM.getCode(), BibConstants.PUBLISHER_DISPLAY));
158            searchParams.getSearchResultFields().add(searchParams.buildSearchResultField(DocType.ITEM.getCode(), BibConstants.ISBN_DISPLAY));
159            searchParams.getSearchResultFields().add(searchParams.buildSearchResultField(DocType.ITEM.getCode(), BibConstants.LOCALID_DISPLAY));
160            searchParams.getSearchResultFields().add(searchParams.buildSearchResultField(DocType.ITEM.getCode(), BibConstants.UNIQUE_ID));
161            searchParams.getSearchResultFields().add(searchParams.buildSearchResultField(DocType.ITEM.getCode(), Item.ID));
162            searchParams.getSearchResultFields().add(searchParams.buildSearchResultField(DocType.ITEM.getCode(), BibConstants.FORMAT_DISPLAY));
163            searchParams.getSearchResultFields().add(searchParams.buildSearchResultField(DocType.ITEM.getCode(), BibConstants.DOC_FORMAT));
164            searchParams.getSearchResultFields().add(searchParams.buildSearchResultField(DocType.ITEM.getCode(), BibConstants.DOC_CATEGORY));
165            searchParams.getSearchResultFields().add(searchParams.buildSearchResultField(DocType.ITEM.getCode(), BibConstants.DOC_TYPE));
166            searchParams.getSearchResultFields().add(searchParams.buildSearchResultField(DocType.ITEM.getCode(), "format"));
167
168
169            searchResponse = getDocstoreClientLocator().getDocstoreClient().search(searchParams);
170            for (SearchResult searchResult : searchResponse.getSearchResults()) {
171                DocData docData=new DocData();
172                docData=buildDocInfoBean(docData,searchResult);
173                results.add(docData);
174            }
175        } catch (Exception ex) {
176            GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_ERRORS, "Item Exists");
177            LOG.error(org.kuali.ole.OLEConstants.ITEM_EXIST + ex);
178        }
179        return results;
180    }
181
182    private DocData buildDocInfoBean(DocData data, SearchResult searchResult) {
183
184        if (CollectionUtils.isNotEmpty(searchResult.getSearchResultFields())) {
185            for (SearchResultField searchResultField : searchResult.getSearchResultFields()) {
186                if (StringUtils.isNotBlank(searchResultField.getFieldName())) {
187                    if (searchResultField.getFieldName().equalsIgnoreCase(Bib.BIBIDENTIFIER)) {
188                        data.setBibIdentifier(searchResultField.getFieldValue());
189                        data.setUniqueId(searchResultField.getFieldValue());
190                    } else if (searchResultField.getFieldName().equalsIgnoreCase(Bib.TITLE)) {
191                        data.setTitle(searchResultField.getFieldValue());
192                    } else if (searchResultField.getFieldName().equalsIgnoreCase(Bib.AUTHOR)) {
193                        data.setAuthor(searchResultField.getFieldValue());
194                    } else if (searchResultField.getFieldName().equalsIgnoreCase(BibConstants.ISBN_DISPLAY)) {
195                        data.setIsbn(searchResultField.getFieldValue());
196                    } else if (searchResultField.getFieldName().equalsIgnoreCase(BibConstants.LOCALID_DISPLAY)) {
197                        data.setLocalIdentifier(searchResultField.getFieldValue());
198                    } else if (searchResultField.getFieldName().equalsIgnoreCase(BibConstants.UNIQUE_ID)) {
199                        //data.setUniqueId(searchResultField.getFieldValue());
200                    } else if (searchResultField.getFieldName().equalsIgnoreCase(BibConstants.PUBLICATIONDATE_DISPLAY)) {
201                        data.setPublicationDate(searchResultField.getFieldValue());
202                    }else if (searchResultField.getFieldName().equalsIgnoreCase(BibConstants.PUBLISHER_DISPLAY)) {
203                        data.setPublisher(searchResultField.getFieldValue());
204                    } else if (searchResultField.getFieldName().equalsIgnoreCase(BibConstants.FORMAT_DISPLAY)) {
205                        data.setFormat(searchResultField.getFieldValue());
206                    }else if (searchResultField.getFieldName().equalsIgnoreCase(BibConstants.DOC_FORMAT)) {
207                        data.setFormat(searchResultField.getFieldValue());
208                    }
209                }
210            }
211        }
212        return data;
213    }
214
215    /**
216     * This method populates and returns a list of DocData from docstore search result
217     *
218     * @param docInfoBeanList
219     * @return
220     * @throws Exception
221     */
222    private List<DocData> getDocResult(List<DocInfoBean> docInfoBeanList) throws Exception {
223        LOG.debug("Inside getDocResult of OleDocStoreSearchService");
224        List<DocData> ress = new ArrayList<DocData>(0);
225        DocData res = new DocData();
226        for (DocInfoBean docInfoBean : docInfoBeanList) {
227            res = new DocData(docInfoBean.getAuthor_display(), docInfoBean.getTitle_display(), docInfoBean.getIsbn_display(), docInfoBean.getLocalIdentifier_search(), docInfoBean.getPublisher_search(), docInfoBean.getPublicationPlace_search(), docInfoBean.getPublicationDate_search(), docInfoBean.getDocType(), docInfoBean.getPrice_f(), docInfoBean.getTitleId(), docInfoBean.getUniqueId(), docInfoBean.getBibIdentifier());
228            ress.add(res);
229        }
230        LOG.debug("Leaving getDocResult of OleDocStoreSearchService");
231        return ress;
232    }
233
234    /**
235     * This method invokes search with bib fields.
236     * @see org.kuali.rice.krad.dao.LookupDao#findCollectionBySearchHelper(java.lang.Class, java.util.Map, boolean, boolean)
237     */
238  /*  public Collection findCollectionBySearchHelper(Class arg0, Map arg1, boolean arg2, boolean arg3) {
239        if ( LOG.isDebugEnabled() ) {
240            LOG.debug("Inside findCollectionBySearchHelper of OleDocStoreSearchService");
241        }
242        try{
243            return getDocResult(arg1);
244        }catch(Exception e){
245            return null;
246        }
247    }
248
249    *//**
250     * This method invokes search with bib fields.
251     * @see org.kuali.rice.krad.dao.LookupDao#findCollectionBySearchHelper(java.lang.Class, java.util.Map, boolean, boolean, java.lang.Object)
252     *//*
253    public Collection findCollectionBySearchHelper(Class arg0, Map arg1, boolean arg2, boolean arg3, Object arg4) {
254        if ( LOG.isDebugEnabled() ) {
255            LOG.debug("Inside findCollectionBySearchHelper of OleDocStoreSearchService");
256        }
257        try{
258            return getDocResult(arg1);
259        }catch(Exception e){
260            return null;
261        }
262    }*/
263
264    
265/*    public Long findCountByMap(Object arg0, Map arg1) {
266        // TODO Auto-generated method stub
267        return null;
268    }
269
270    
271    public Object findObjectByMap(Object arg0, Map arg1) {
272        // TODO Auto-generated method stub
273        return null;
274    }*/
275
276    /**
277     * This method invokes docstore search query with multiple document uuids
278     *
279     * @param cl
280     * @param attr
281     * @param vals
282     * @return
283     * @throws Exception
284     */
285    public List getResult(Class cl, String attr, List<Object> vals) throws Exception {
286        LOG.debug("Inside getResult of OleDocStoreSearchService");
287        List result = new ArrayList(0);
288        int maxLimit = Integer.parseInt(SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString(OLEConstants.DOCSEARCH_ORDERQUEUE_LIMIT_KEY));
289
290        List<DocInfoBean> docInfoBeanList = new ArrayList<DocInfoBean>(0);
291
292        StringBuilder query = new StringBuilder("q=");
293        query.append("(DocType:bibliographic AND (");
294        HashMap titleIdMap = new HashMap();
295        int loop = 0;
296        for (Object iv : vals) {
297            String id = iv.toString();
298            boolean isIdExists = titleIdMap.containsValue(id);
299            titleIdMap.put(id, id);
300            if (!isIdExists) {
301                if (loop != 0) query.append(" OR ");
302                query.append("id:" + id + " ");
303                loop++;
304            }
305            if (loop == maxLimit)
306                break;
307        }
308        query.append("))");
309        // Changes to include userId in docstore URl.
310        if (GlobalVariables.getUserSession() != null) {
311            query.append("&userId=" + GlobalVariables.getUserSession().getPerson().getPrincipalName());
312        }
313        query.append("&rows=" + loop);
314        if (LOG.isDebugEnabled())
315            LOG.debug("Doc Store Query :" + query.toString());
316
317        if (loop > 0) {
318            docInfoBeanList = getResponse(query.toString());
319            result = getDocResult(docInfoBeanList);
320        }
321        LOG.debug("Leaving getResult of OleDocStoreSearchService");
322        return result;
323    }
324
325    /**
326     * This method populates bib related values based on the document uuids using docstore search.
327     *
328     * @see org.kuali.ole.select.service.OleDocStoreSearchService#getResult(java.lang.Class, java.util.Map)
329     */
330    public List getResult(Class cl, Map<String, List<Object>> val) {
331        LOG.debug("Inside getResult of OleDocStoreSearchService");
332        List resul = new ArrayList(0);
333        for (String key : val.keySet()) {
334            List ll;
335            try {
336                ll = getResult(cl, key, val.get(key));
337                if (ll != null && ll.size() > 0)
338                    resul.addAll(ll);
339            } catch (Exception e) {
340                e.printStackTrace();
341            }
342
343
344        }
345        LOG.debug("Leaving getResult of OleDocStoreSearchService");
346        return resul;
347
348    }
349
350    /**
351     * This method invokes getResult when there is no search based on bib
352     * and invokes getDocResult when we have any bib related fields in search.
353     *
354     * @see org.kuali.ole.select.service.OleDocStoreSearchService#getResult(java.lang.Class, java.lang.String, java.util.List, java.util.Map)
355     */
356    public List getResult(Class cl, String attr, List<Object> val, Map vas) {
357        LOG.debug("Inside getResult of OleDocStoreSearchService");
358        try {
359            if (vas == null || vas.size() < 1) {
360                return getResult(cl, attr, val);
361            } else {
362                return getDocResult(vas);
363            }
364        } catch (Exception e) {
365            return null;
366        }
367    }
368
369    /**
370     * This method invokes docstore call for multiple document uuids
371     *
372     * @param query
373     * @return
374     */
375    private List<DocInfoBean> getResponse(String query) {
376        LOG.debug("Inside getResponse of OleDocStoreSearchService");
377        List<DocInfoBean> docInfoBeanList = new ArrayList<DocInfoBean>(0);
378        BuildDocInfoBean buildDocInfoBean = new BuildDocInfoBean();
379        docInfoBeanList = buildDocInfoBean.getDocInfoBeanList(query);
380        LOG.debug("Leaving getResponse of OleDocStoreSearchService");
381        return docInfoBeanList;
382    }
383
384    public String getBibUUID(String itemTitleId) {
385        String uuid = null;
386        if (itemTitleId != null) {
387            HashMap<String, String> queryMap = new HashMap<String, String>();
388            queryMap.put(OleSelectConstant.DocStoreDetails.ITEMLINKS_KEY, itemTitleId);
389            List<DocInfoBean> docStoreResult;
390            try {
391                docStoreResult = getBibInfoWrapperService().searchBibInfo(queryMap);
392                Iterator bibIdIterator = docStoreResult.iterator();
393                if (bibIdIterator.hasNext()) {
394                    DocInfoBean docInfoBean = (DocInfoBean) bibIdIterator.next();
395                    if (docInfoBean.getBibIdentifier() == null) {
396                        uuid = docInfoBean.getUniqueId();
397                        return uuid;
398
399                    } else {
400                        uuid = docInfoBean.getBibIdentifier();
401                        return uuid;
402                    }
403                }
404            } catch (Exception ex) {
405                // TODO Auto-generated catch block
406                throw new RuntimeException();
407            }
408        }
409        return uuid;
410    }
411
412
413}