001package org.kuali.ole.docstore.discovery.service;
002
003import org.apache.solr.client.solrj.SolrQuery;
004import org.apache.solr.client.solrj.SolrServer;
005import org.apache.solr.client.solrj.response.QueryResponse;
006import org.apache.solr.common.SolrDocument;
007import org.apache.solr.common.SolrDocumentList;
008import org.kuali.ole.docstore.model.bo.OleDocument;
009import org.kuali.ole.docstore.model.bo.WorkBibDocument;
010import org.kuali.ole.docstore.model.bo.WorkEInstanceDocument;
011import org.kuali.ole.docstore.model.bo.WorkInstanceDocument;
012import org.slf4j.Logger;
013import org.slf4j.LoggerFactory;
014import java.util.ArrayList;
015import java.util.List;
016import java.util.Map;
017import java.util.Set;
018
019/**
020 * Created with IntelliJ IDEA.
021 * User: ?
022 * Date: 8/6/12
023 * Time: 11:42 AM
024 * To change this template use File | Settings | File Templates.
025 */
026public class SRUCQLQueryServiceImpl implements SRUCQLQueryService {
027
028    private Logger LOG = LoggerFactory.getLogger(this.getClass());
029
030    private static SRUCQLQueryServiceImpl srucqlQueryService = null;
031
032    private SRUCQLQueryServiceImpl() {
033    }
034
035    public static SRUCQLQueryServiceImpl getInstance() {
036        if (srucqlQueryService == null)
037            srucqlQueryService = new SRUCQLQueryServiceImpl();
038        return srucqlQueryService;
039    }
040
041    /**
042     * @param solrQuery
043     * @return return list of bib id values
044     * @throws Exception
045     */
046    @Override
047    public List<OleDocument> queryForBibDocs(Map reqParamMap, String solrQuery) throws Exception {
048        LOG.info("Inside queryForBibDocs method");
049        List<OleDocument> oleDocuments;
050        List<Map<String, Object>> solrHits;
051        solrQuery = getSolrReqQuery(reqParamMap, solrQuery);
052        solrHits = getSolrHitsForQuery(solrQuery, reqParamMap);
053        oleDocuments = buildOleDocuments(solrHits);
054        return oleDocuments;
055
056    }
057
058
059    /**
060     * @param term
061     * @param relation
062     * @param index
063     * @param solrQueryFlag
064     * @return solr query
065     * @throws Exception
066     */
067    @Override
068    public String getQuery(String term, String relation, String index, boolean solrQueryFlag) throws Exception {
069
070        if (term != null) {
071            if (term.contains(":")) {
072                solrQueryFlag = false;
073                return null;
074            }
075        }
076
077        if (index.contains(DC) || (index.contains(OLE)) || (index.contains(BATH)) || (index.contains(REC))) {
078            if(index.contains(REC_ID) || (index.contains(OLE_ID)) || (index.contains(BATH_ID)) || (index.contains(DC_ID))){
079                index = index.replaceAll(REC_ID,LOCAL_Id);
080                index = index.replaceAll(OLE_ID,LOCAL_Id);
081                index = index.replaceAll(BATH_ID,LOCAL_Id);
082                index = index.replaceAll(DC_ID,LOCAL_Id);
083            }
084            else{
085            index = index.replaceAll(REC,"");
086            index = index.replaceAll(DC, "");
087            index = index.replaceAll(OLE,"");
088            index = index.replaceAll(BATH,"");
089            }
090           }
091
092        if(SRU_QUERY_ADJ_RELATION.equals(relation) ) {
093            StringBuffer query = new StringBuffer("");
094            String[] terms = term.split(" ");
095            query.append(getIndex(index) + "(" + "\"");
096            for (int i = 0; i < terms.length ; i++){
097                if(i == terms.length -1) {
098                    query.append(terms[i].toLowerCase());
099                }
100                else{
101                    query.append(terms[i].toLowerCase() + "+");
102                }
103            }
104            query.append("\"" + "))");
105            return query.toString();
106        }
107
108        if(SRU_QUERY_EQUALS_RELATION.equals(relation)) {
109            StringBuffer query = new StringBuffer("");
110            String[] terms = term.split(" ");
111            query.append(getExactIndex(index) + "(" + "\"");
112            for (int i = 0; i < terms.length ; i++){
113                if(i == terms.length -1) {
114                    query.append(terms[i].toLowerCase());
115                }
116                else{
117                    query.append(terms[i].toLowerCase() + "+");
118                }
119            }
120            query.append("\"" + "))");
121            return query.toString();
122        }
123
124/*        if ( SRU_QUERY_SRC_RELATION.equals(relation)) {
125            return "(all_text:(" + term + "))";
126        }*/
127        if (SRU_QUERY_ALL_RELATION.equals(relation)) {
128            StringBuffer query = new StringBuffer("");
129            String[] terms = term.split(" ");
130            for (int i = 0; i < terms.length - 1; i++)
131                query.append(getIndex(index) + "(" + terms[i].toLowerCase() + ")) AND ");
132            query.append(getIndex(index) + "(" + terms[terms.length - 1].toLowerCase() + "))");
133            return query.toString();
134        }
135        if (SRU_QUERY_EXACT_RELATION.equals(relation)) {
136            return getExactIndex(index) + "(\"" + term + "\"))";
137        }
138        if (SRU_QUERY_WITHIN_RELATION.equals(relation)) {
139            return getExactIndex(index) +getWithinQuery(term);
140        }
141        if (SRU_QUERY_ANY_RELATION.equals(relation)) {
142            StringBuffer query = new StringBuffer("");
143            String[] terms = term.split(" ");
144            for (int i = 0; i < terms.length - 1; i++)
145                query.append(getIndex(index) + "(" + terms[i].toLowerCase() + ")) OR ");
146            query.append(getIndex(index) + "(" + terms[terms.length - 1].toLowerCase() + "))");
147            return query.toString();
148        }
149        if (relation.contains(SRU_QUERY_LESSERTHAN_RELATION)) {
150            StringBuffer query = new StringBuffer("");
151            if (SRU_QUERY_LESSERTHAN_EQUAL_RELATION.equals(relation))
152                query.append(getIndex(index) + "[0 TO " + term + "])");
153            else {
154                int pubDate = Integer.parseInt(term) - 1;
155                query.append(getIndex(index) + "[0 TO " + pubDate + "])");
156            }
157            return query.toString();
158        }
159
160        if (relation.contains(SRU_QUERY_GREATERTHAN_RELATION)) {
161            StringBuffer query = new StringBuffer("");
162            if (SRU_QUERY_GREATERTHAN_EQUAL_RELATION.equals(relation))
163                query.append(getIndex(index) + "[" + term + " TO NOW])");
164            else {
165                int pubDate = Integer.parseInt(term) + 1;
166                query.append(getIndex(index) + "[" + pubDate + " TO NOW])");
167            }
168            return query.toString();
169        }
170
171        if (SRU_QUERY_TITLE.equalsIgnoreCase(index))
172            return getIndex(index) + "(" + term.toLowerCase() + "))";
173        if (SRU_QUERY_AUTHOR.equalsIgnoreCase(index) || SRU_QUERY_CREATOR.equals(index))
174            return getIndex(index) + "(" + term.toLowerCase() + "))";
175        if (SRU_QUERY_PUBLICATION_DATE.equalsIgnoreCase(index) || SRU_QUERY_DATE.equalsIgnoreCase(index))
176            return getIndex(index) + "(" + term.toLowerCase() + "))";
177        if (SRU_QUERY_ISBN.equalsIgnoreCase(index))
178            return getIndex(index) + "(" + term.toLowerCase() + "))";
179        if (SRU_QUERY_PUBLISHER.equalsIgnoreCase(index))
180            return getIndex(index) + "(" + term.toLowerCase() + "))";
181        if (SRU_QUERY_ISSN.equalsIgnoreCase(index))
182            return getIndex(index) + "(" + term.toLowerCase() + "))";
183        if (SRU_QUERY_LOCAL_ID.equalsIgnoreCase(index))
184            return getIndex(index) + "(" + term.toLowerCase() + "))";
185        if (SRU_QUERY_OCLC.equalsIgnoreCase(index))
186            return getIndex(index) + "(" + term.toLowerCase() + "))";
187        if (SRU_QUERY_SUBJECT.equalsIgnoreCase(index))
188            return getIndex(index) + "(" + term.toLowerCase() + "))";
189        if(SRU_QUERY_SERVER_CHOICE.equalsIgnoreCase(index))
190            return getIndex(index) + "(" + term.toLowerCase() + "))";
191        if(SRU_QUERY_CQL_KEYWORDS.equalsIgnoreCase(index))
192            return getIndex(index) + "(" + term.toLowerCase() + "))";
193        return "";
194
195    }
196
197    /**
198     * @param index
199     * @return query fields string
200     */
201    public String getIndex(String index) {
202
203        if (SRU_QUERY_TITLE.equalsIgnoreCase(index))
204            return "(Title_search:";
205        if (SRU_QUERY_AUTHOR.equalsIgnoreCase(index) || SRU_QUERY_CREATOR.equals(index))
206            return "(Author_search:";
207        if (SRU_QUERY_PUBLICATION_DATE.equalsIgnoreCase(index) || SRU_QUERY_DATE.equalsIgnoreCase(index))
208            return "(PublicationDate_search:";
209        if (SRU_QUERY_ISBN.equalsIgnoreCase(index))
210            return "(ISBN_search:";
211        if (SRU_QUERY_PUBLISHER.equalsIgnoreCase(index))
212            return "(Publisher_search:";
213        if (SRU_QUERY_ISSN.equalsIgnoreCase(index))
214            return "(ISSN_search:";
215        if (SRU_QUERY_LOCAL_ID.equalsIgnoreCase(index))
216            return "(LocalId_search:";
217        if (SRU_QUERY_OCLC.equalsIgnoreCase(index))
218            return "(035a:";
219        if (SRU_QUERY_SUBJECT.equalsIgnoreCase(index))
220            return "(Subject_search:";
221        if(SRU_QUERY_SERVER_CHOICE.equalsIgnoreCase(index))
222            return "(all_text:";
223        if(SRU_QUERY_CQL_KEYWORDS.equalsIgnoreCase(index))
224            return "(all_text:";
225        return "";
226    }
227
228    /**
229     * @param index
230     * @return query fields string
231     */
232    public String getExactIndex(String index) {
233
234        if (SRU_QUERY_TITLE.equalsIgnoreCase(index))
235            return "(Title_display:";
236        if (SRU_QUERY_AUTHOR.equalsIgnoreCase(index) || SRU_QUERY_CREATOR.equals(index))
237            return "(Author_display:";
238        if (SRU_QUERY_PUBLICATION_DATE.equalsIgnoreCase(index) || SRU_QUERY_DATE.equalsIgnoreCase(index))
239            return "(PublicationDate_display:";
240        if (SRU_QUERY_ISBN.equalsIgnoreCase(index))
241            return "(ISBN_display:";
242        if (SRU_QUERY_PUBLISHER.equalsIgnoreCase(index))
243            return "(Publisher_display:";
244        if (SRU_QUERY_ISSN.equalsIgnoreCase(index))
245            return "(ISSN_display:";
246        if (SRU_QUERY_LOCAL_ID.equalsIgnoreCase(index))
247            return "(LocalId_display:";
248        if (SRU_QUERY_OCLC.equalsIgnoreCase(index))
249            return "(035a:";
250        if (SRU_QUERY_SUBJECT.equalsIgnoreCase(index))
251            return "(Subject_display:";
252        return "";
253    }
254
255    /**
256     * @param sortKey
257     * @return
258     */
259    public String getSortKeyValue(String sortKey) {
260
261        String sortKeys[] = sortKey.split(",");
262        if (SRU_QUERY_TITLE.equalsIgnoreCase(sortKeys[0]))
263            return "Title_sort asc";
264        if (SRU_QUERY_AUTHOR.equalsIgnoreCase(sortKeys[0]))
265            return "Author_sort asc";
266        if (SRU_QUERY_PUBLICATION_DATE.equalsIgnoreCase(sortKeys[0]))
267            return "PublicationDate_sort asc";
268        if (SRU_QUERY_ISBN.equalsIgnoreCase(sortKeys[0]))
269            return "ISBN_sort asc";
270        if (SRU_QUERY_PUBLISHER.equalsIgnoreCase(sortKeys[0]))
271            return "Publisher_sort asc";
272
273        return "";
274    }
275
276    /**
277     * @param hitsOnPage
278     * @return List of OleDocuments
279     */
280    public List<OleDocument> buildOleDocuments(List<Map<String, Object>> hitsOnPage) {
281        List<OleDocument> oleDocuments = new ArrayList<OleDocument>();
282        for (Map<String, Object> hitsOnPageItr : hitsOnPage) {
283            WorkBibDocument workBibDocument = new WorkBibDocument();
284            Map map = hitsOnPageItr;
285            Set keys = map.keySet();
286            for (Object key : keys) {
287                if ("id".equalsIgnoreCase(key.toString())) {
288                    workBibDocument.setId((String) map.get(key));
289                }
290                if ("instanceIdentifier".equalsIgnoreCase(key.toString())) {
291                    Object object = map.get(key);
292                    List<WorkInstanceDocument> workInstanceDocuments = new ArrayList<WorkInstanceDocument>();
293                    List<WorkEInstanceDocument> workEInstanceDocuments = new ArrayList<WorkEInstanceDocument>();
294                    if (object instanceof String) {
295                        String id = (String) object;
296                        if(id.startsWith("wen")){
297                            WorkEInstanceDocument workEInstanceDocument = new WorkEInstanceDocument();
298                            workEInstanceDocument.setInstanceIdentifier(id);
299                            workEInstanceDocuments.add(workEInstanceDocument);
300                        }else{
301                            WorkInstanceDocument workInstanceDocument = new WorkInstanceDocument();
302                            workInstanceDocument.setInstanceIdentifier((String) object);
303                            workInstanceDocuments.add(workInstanceDocument);
304                        }
305                    } else if (object instanceof List) {
306                        List<String> instanceIds = (List<String>) object;
307                        for (String id : instanceIds) {
308                            if(id.startsWith("wen")){
309                                WorkEInstanceDocument workEInstanceDocument = new WorkEInstanceDocument();
310                                workEInstanceDocument.setInstanceIdentifier(id);
311                                workEInstanceDocuments.add(workEInstanceDocument);
312                            }else{
313                                WorkInstanceDocument workInstanceDocument = new WorkInstanceDocument();
314                                workInstanceDocument.setInstanceIdentifier(id);
315                                workInstanceDocuments.add(workInstanceDocument);
316                            }
317                        }
318                    }
319                    workBibDocument.setWorkInstanceDocumentList(workInstanceDocuments);
320                    workBibDocument.setWorkEInstanceDocumentList(workEInstanceDocuments);
321                }
322            }
323            oleDocuments.add(workBibDocument);
324        }
325        return oleDocuments;
326    }
327
328    /**
329     * @param inputQuery
330     * @return hitsOnPage
331     * @throws Exception Usage: Gets Solr response for input query and builds List of Maps holding Solr Doc Data
332     */
333    public List<Map<String, Object>> getSolrHitsForQuery(String inputQuery, Map reqParamMap) throws Exception {
334        SolrServer server;
335        List<Map<String, Object>> hitsOnPage = new ArrayList<Map<String, Object>>();
336        server = SolrServerManager.getInstance().getSolrServer();
337        SolrQuery solrQuery = new SolrQuery();
338        solrQuery.setQuery(inputQuery);
339        solrQuery.setIncludeScore(true);
340        solrQuery.set("fl", "id,instanceIdentifier");
341        solrQuery.set("start", reqParamMap.get(START_RECORD).toString());
342        solrQuery.set("rows", reqParamMap.get(MAXIMUM_RECORDS).toString());
343        solrQuery.set("sort", getSortKeyValue(reqParamMap.get(SORTKEYS).toString()));
344        QueryResponse queryResponse = server.query(solrQuery);
345        SolrDocumentList solrDocumentList = queryResponse.getResults();
346        reqParamMap.put("numberOfRecords", queryResponse.getResults().getNumFound());
347        for (SolrDocument solrDocument : solrDocumentList) {
348            hitsOnPage.add(solrDocument);
349        }
350        return hitsOnPage;
351    }
352
353    public String getSolrReqQuery(Map reqParamMap, String solrQuery) {
354        StringBuffer query = new StringBuffer("");
355        String recordSchema= (String)reqParamMap.get(RECORD_SCHEMA);
356        if (recordSchema != null) {
357            if (recordSchema.equalsIgnoreCase("OPAC")) {
358                query.append("(DocFormat:marc AND staffOnlyFlag:false) AND DocType:bibliographic AND  ");
359            } else {
360                query.append("(DocFormat:" + reqParamMap.get(RECORD_SCHEMA).toString() + "AND staffOnlyFlag:false) AND DocType:bibliographic AND ");
361            }
362        }
363        query.append(solrQuery);
364        LOG.info("solr Query SRUCQLQueryServiceImpl"+query);
365        query = new StringBuffer(query.toString().replace("+", " "));
366        return query.toString();
367    }
368    public String getWithinQuery(String term){
369        String range[]=term.split("[' ']");
370        return "[" + range[0] +" TO "+range[1] + "])";
371    }
372}