package org.sothis.dal.solr; import java.beans.PropertyDescriptor; import java.io.Serializable; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.SolrServer; import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrDocumentList; import org.apache.solr.common.SolrInputDocument; import org.apache.solr.common.SolrInputField; import org.sothis.core.util.Pager; import org.sothis.dal.AbstractJpaCompatibleDao; import org.sothis.dal.QueryException; import org.sothis.dal.query.Chain; import org.sothis.dal.query.Cnd; public abstract class AbstractSolrDao<E extends SolrEntity, K extends Serializable> extends AbstractJpaCompatibleDao<E, K> implements SolrDao<E, K> { private final SolrQueryBuilder queryBuilder; private SolrServer solrServer; public AbstractSolrDao() { super(); queryBuilder = new SolrQueryBuilder(this.getPropertyMap()); } private List<E> find(Cnd cnd, Pager pager, Chain chain, boolean count) { try { SolrQuery query = this.queryBuilder.buildQuery(cnd, chain); if (null != pager) { query.setStart(pager.getStartRow()); query.setRows(pager.getPageSize()); } QueryResponse response = solrServer.query(query); SolrDocumentList docList = response.getResults(); if (count && null != pager) { pager.setTotalRows((int) docList.getNumFound()); } if (docList.isEmpty()) { return Collections.emptyList(); } List<E> list = new ArrayList<E>(docList.size()); for (SolrDocument document : docList) { list.add(this.documentToEntity(document)); } return list; } catch (SolrServerException e) { throw new QueryException(e); } } @Override public List<E> find(Cnd cnd, Pager pager, Chain chain) { return find(cnd, pager, chain, false); } @Override public int update(Cnd cnd, Chain chain) { throw new UnsupportedOperationException("update by cnd is not supported."); } @Override public E update(E entity) { SolrInputDocument document = this.entityToDocument(entity); try { this.solrServer.add(document); this.solrServer.commit(); } catch (Exception e) { throw new QueryException(e); } return entity; } @Override public int delete(Cnd cnd) { SolrQuery query = this.queryBuilder.buildQuery(cnd, null); try { this.solrServer.deleteByQuery(query.toString()); this.solrServer.commit(); } catch (Exception e) { throw new QueryException(e); } return 0; } @Override public E insert(E entity) { return update(entity); } @Override public int count(Cnd cnd) { Pager pager = new Pager(0); find(cnd, pager, null, true); return pager.getTotalRows(); } @Override public List<E> findAndCount(Cnd cnd, Pager pager, Chain chain) { return find(cnd, pager, chain, true); } private E documentToEntity(SolrDocument document) { try { E entity = this.getEntityClass().newInstance(); for (Map.Entry<String, Object> entry : document.entrySet()) { PropertyInfo propertyInfo = this.getPropertyInfoByField(entry.getKey()); if (null == propertyInfo) { throw new QueryException("un-mapped field '" + entry.getKey() + "' of entity class " + this.getEntityClass()); } PropertyDescriptor descriptor = propertyInfo.getPropertyDescriptor(); Method writeMethod = descriptor.getWriteMethod(); writeMethod.invoke(entity, entry.getValue()); } return entity; } catch (Exception e) { throw new QueryException(e); } } private SolrInputDocument entityToDocument(E entity) { try { SolrInputDocument document = new SolrInputDocument(); Map<String, PropertyInfo> propertyMap = this.getPropertyMap(); for (Map.Entry<String, PropertyInfo> entry : propertyMap.entrySet()) { PropertyInfo pi = entry.getValue(); Object value = pi.getPropertyDescriptor().getReadMethod().invoke(entity, (Object[]) null); if (null != value) { SolrInputField field = new SolrInputField(pi.getColumn().name()); field.setValue(value, 1); } } return document; } catch (Exception e) { throw new QueryException(e); } } public void setSolrServer(SolrServer solrServer) { this.solrServer = solrServer; } public SolrServer getSolrServer() { return solrServer; } }