001/**
002 * Copyright 2014 Tampere University of Technology, Pori Department
003 * 
004 * Licensed under the Apache 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.apache.org/licenses/LICENSE-2.0
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 core.tut.pori.dao;
017
018import java.io.IOException;
019import java.util.ArrayList;
020import java.util.Collection;
021import java.util.Iterator;
022import java.util.List;
023
024import org.apache.log4j.Logger;
025import org.apache.solr.client.solrj.SolrClient;
026import org.apache.solr.client.solrj.SolrRequest.METHOD;
027import org.apache.solr.client.solrj.SolrServerException;
028import org.apache.solr.client.solrj.response.QueryResponse;
029import org.apache.solr.client.solrj.response.UpdateResponse;
030import org.apache.solr.common.SolrDocument;
031import org.apache.solr.common.SolrDocumentList;
032import org.apache.solr.common.SolrException;
033import org.apache.solr.common.SolrException.ErrorCode;
034import org.apache.solr.common.params.SolrParams;
035
036/**
037 * Simplified Solr Template. 
038 *
039 */
040public class SimpleSolrTemplate{
041  private static final Logger LOGGER = Logger.getLogger(SimpleSolrTemplate.class);
042  private SolrClient _server = null;
043
044  /**
045   * 
046   * @param solrServer
047   */
048  public SimpleSolrTemplate(SolrClient solrServer) {
049    _server = solrServer;
050  }
051
052  /**
053   * @param obj
054   * @return response
055   * @throws SolrException
056   */
057  public UpdateResponse addBean(Object obj) throws SolrException {
058    try {
059      return _server.addBean(obj, SolrDAO.SOLR_COMMIT_WITHIN);
060    } catch (IOException | SolrServerException ex) {
061      LOGGER.error(ex, ex);
062      throw new SolrException(ErrorCode.UNKNOWN, "Failed to add bean.");
063    }
064  }
065
066  /**
067   * @param beans
068   * @return response
069   * @throws SolrException
070   */
071  public UpdateResponse addBeans(Collection<?> beans) throws SolrException {
072    try {
073      return _server.addBeans(beans, SolrDAO.SOLR_COMMIT_WITHIN);
074    } catch (SolrServerException | IOException ex) {
075      LOGGER.error(ex, ex);
076      throw new SolrException(ErrorCode.UNKNOWN, "Failed to add beans.");
077    }
078  }
079
080  /**
081   * @param ids
082   * @return response
083   * @throws SolrException
084   * @see org.apache.solr.client.solrj.SolrClient#deleteById(java.util.List)
085   */
086  public UpdateResponse deleteById(List<String> ids) throws SolrException {
087    try {
088      return _server.deleteById(ids, SolrDAO.SOLR_COMMIT_WITHIN);
089    } catch (SolrServerException | IOException ex) {
090      LOGGER.error(ex, ex);
091      throw new SolrException(ErrorCode.UNKNOWN, "Failed to delete.");
092    }
093  }
094  
095  /**
096   * Overloaded convenience method for passing a Collection instead of a list.
097   * 
098   * @param ids
099   * @return response
100   * @throws SolrException
101   */
102  public UpdateResponse deleteById(Collection<String> ids) throws SolrException {
103    return deleteById(new ArrayList<>(ids));
104  }
105
106  /**
107   * Invokes a "hard commit" to Solr index. 
108   * Generally there should not be need for calling this because Solr cores should be configured to do &lt;autoCommit&gt;s on their own.
109   * See <a href="https://wiki.apache.org/solr/NearRealtimeSearch">Solr Near Realtime Search (NRT)</a> for more information.
110   * @return response
111   * @throws SolrException
112   */
113  public UpdateResponse commit() throws SolrException {
114    try {
115      return _server.commit();
116    } catch (SolrServerException | IOException ex) {
117      LOGGER.error(ex, ex);
118      throw new SolrException(ErrorCode.UNKNOWN, "Failed to add beans.");
119    }
120  }
121
122  /**
123   * @param params
124   * @return response
125   * @throws SolrException
126   * @see org.apache.solr.client.solrj.SolrClient#query(org.apache.solr.common.params.SolrParams)
127   */
128  public QueryResponse query(SolrParams params) throws SolrException {
129    try {
130      return _server.query(params, METHOD.POST);
131    } catch (SolrServerException | IOException ex) {
132      LOGGER.error(ex, ex);
133      throw new SolrException(ErrorCode.UNKNOWN, "Query Failed.");
134    }
135  }
136  
137  /**
138   * 
139   * @param params
140   * @param fieldName
141   * @param cls
142   * @return All values for the given field or null if none
143   * @throws SolrException
144   */
145  public <T> List<T> queryForObjects(SolrParams params, String fieldName, Class<T> cls) throws SolrException{
146    try {
147      return getObjects(_server.query(params, METHOD.POST), fieldName, cls);
148    } catch (SolrServerException | IllegalArgumentException | IOException ex) {
149      LOGGER.error(ex, ex);
150      throw new SolrException(ErrorCode.UNKNOWN, "Query failed.");
151    }
152  }
153  
154  /**
155   * 
156   * @param response
157   * @param fieldName
158   * @param cls
159   * @return All values for the given field or null if none
160   * @throws IllegalArgumentException
161   */
162  @SuppressWarnings("unchecked")
163  public static <T> List<T> getObjects(QueryResponse response, String fieldName, Class<T> cls) throws IllegalArgumentException{
164    if(response == null){
165      LOGGER.debug("Null response.");
166      return null;
167    }
168    if(fieldName == null){
169      throw new IllegalArgumentException("Field name was null.");
170    }
171    SolrDocumentList list = response.getResults();
172    if(list.isEmpty()){
173      LOGGER.debug("No documents.");
174      return null;
175    }
176    
177    List<T> results = new ArrayList<>(list.size());
178    for(Iterator<SolrDocument> iter = list.iterator(); iter.hasNext();){
179      Object o = iter.next().getFieldValue(fieldName);
180      if(o == null){
181        LOGGER.debug("Ignored null value for field: "+fieldName);
182      }else{
183        results.add((T) o); // ignore type-safety, the objects returned SHOULD be simple objects (not arrays or complex types), and even if they aren't the user should not pass invalid object class
184      }
185    }
186    
187    return (results.isEmpty() ? null : results);
188  }
189  
190  /**
191   * @param params
192   * @param cls type of the beans
193   * @return the list of beans of the requested type or null if none was found
194   * @throws SolrException
195   */
196  public <T> List<T> queryForList(SolrParams params, Class<T> cls) throws SolrException {
197    try {
198      return getList(_server.query(params, METHOD.POST), cls);
199    } catch (SolrServerException | IOException ex) {
200      LOGGER.error(ex, ex);
201      throw new SolrException(ErrorCode.UNKNOWN, "Query Failed.");
202    }
203  }
204  
205  /**
206   * 
207   * @param response
208   * @param cls
209   * @return list of objects of the given class or null if none found in the class or the response is null
210   */
211  public static <T> List<T> getList(QueryResponse response, Class<T> cls){
212    if(response == null){
213      LOGGER.debug("null response.");
214      return null;
215    }
216    List<T> list = response.getBeans(cls);
217    if(list == null || list.isEmpty()){
218      return null;
219    }else{
220      return list;
221    }
222  }
223}