Java tutorial
/* * Copyright (C) 2007-2013 Crafter Software Corporation. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.craftercms.commerce.server.solr; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.SolrServer; import org.apache.solr.client.solrj.beans.DocumentObjectBinder; import org.apache.solr.client.solrj.response.FacetField; import org.apache.solr.client.solrj.response.FacetField.Count; 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.craftercms.commerce.api.BaseType; import org.craftercms.commerce.api.CrafterCommerceConstants; import org.craftercms.commerce.api.CrafterCommerceException; import org.craftercms.commerce.api.facet.Facet; import org.craftercms.commerce.api.facet.FacetValue; import org.craftercms.commerce.api.service.ServiceResponse; import org.craftercms.commerce.server.BaseCRUDService; import org.craftercms.commerce.server.QueryConverter; import org.craftercms.commerce.server.ReturnMessageProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; public abstract class AbstractSolrCRUDService<T extends BaseType> extends BaseCRUDService<T> { private static final Logger LOGGER = LoggerFactory .getLogger("org.craftercms.commerce.solr.AbstractSolrCRUDService"); @Autowired private SolrServer solrServer; @Autowired private QueryConverter queryConverter; private DocumentBaseTypeBinder documentObjectBinder = new DocumentBaseTypeBinder(); // ---------- Getters & setters ---------- protected SolrServer getSolrServer() { return solrServer; } protected void setSolrServer(SolrServer solrServer) { this.solrServer = solrServer; } protected QueryConverter getQueryConverter() { return queryConverter; } protected void setQueryConverter(QueryConverter queryConverter) { this.queryConverter = queryConverter; } protected DocumentObjectBinder getDocumentObjectBinder() { return documentObjectBinder; } // ---------- Implementation ---------- public ServiceResponse<T> save(@RequestBody T entity) throws CrafterCommerceException { if (LOGGER.isDebugEnabled()) { LOGGER.debug("About to save entity: " + entity.toString()); } prepareEntityForSaving(entity); validate(entity); try { SolrInputDocument inputDoc = documentObjectBinder.toSolrInputDocument(entity); solrServer.add(inputDoc); solrServer.commit(); return new ServiceResponse<T>(getTypeArgument(), true, entity, ReturnMessageProvider.saveMessage(getTypeArgument())); } catch (Exception e) { LOGGER.error("Failed to save entity", e); return new ServiceResponse<T>(getTypeArgument(), false, e.getMessage()); } } public ServiceResponse<T> saveAll(@RequestBody T[] entities) throws CrafterCommerceException { try { for (T entity : entities) { prepareEntityForSaving(entity); validate(entity); } List<SolrInputDocument> inputDocs = new ArrayList<SolrInputDocument>(entities.length); for (T _entity : entities) { inputDocs.add(documentObjectBinder.toSolrInputDocument(_entity)); } solrServer.add(inputDocs); solrServer.commit(); return new ServiceResponse<T>(getTypeArgument(), true, new HashSet<T>(Arrays.asList(entities)), ReturnMessageProvider.saveAllMessage(getTypeArgument(), entities)); } catch (Exception e) { LOGGER.error("Failed to save entities", e); return new ServiceResponse<T>(getTypeArgument(), false, e.getMessage()); } } public ServiceResponse<T> findById(@PathVariable String id) throws CrafterCommerceException { if (LOGGER.isDebugEnabled()) { LOGGER.debug("About to find entity for id: " + id); } try { T entity = null; SolrQuery solrQuery = new SolrQuery(BaseType.SOLR_ID_FIELD + ":" + id); SolrDocumentList solrDocList = solrServer.query(solrQuery).getResults(); if (solrDocList.size() > 0) { entity = documentObjectBinder.getBean(getTypeArgument(), solrDocList.get(0)); } boolean found = (entity == null ? false : true); return new ServiceResponse<T>(getTypeArgument(), true, entity, ReturnMessageProvider.findByIdMessage(getTypeArgument(), id, found)); } catch (Exception e) { LOGGER.error("Failed to find entity by id for id = " + id, e); return new ServiceResponse<T>(getTypeArgument(), false, e.getMessage()); } } public ServiceResponse<T> findByQuery(@PathVariable String query, @PathVariable int offset, @PathVariable int maxResults) throws CrafterCommerceException { if (LOGGER.isDebugEnabled()) { LOGGER.debug("About to find entities for query: " + query); } try { String solrQueryStr = queryConverter.toSolrQuery(query); SolrQuery solrQuery = new SolrQuery(solrQueryStr); solrQuery.setStart(offset); solrQuery.setRows(maxResults); QueryResponse qResponse = solrServer.query(solrQuery); Set<T> entities = toEntities(qResponse); ServiceResponse<T> sResponse = new ServiceResponse<T>(); sResponse.setReturnedClass(getTypeArgument()); sResponse.setSuccess(true); sResponse.setEntities(entities); sResponse.setCount(qResponse.getResults().getNumFound()); String message = ReturnMessageProvider.findByQueryMessage(getTypeArgument(), query, entities.size()); sResponse.setMessage(message); return sResponse; } catch (Exception e) { LOGGER.error("Failed to find entities by query for query = " + query, e); return new ServiceResponse<T>(getTypeArgument(), false, e.getMessage()); } } public ServiceResponse<T> findByQuery(String query, int offset, int maxResults, String... facet) throws CrafterCommerceException { try { String solrQueryStr = queryConverter.toSolrQuery(query); SolrQuery solrQuery = new SolrQuery(solrQueryStr); solrQuery.setStart(offset); solrQuery.setRows(maxResults); // construct facet parameters if (facet.length > 0) { solrQuery.setFacet(true); solrQuery.setFacetMinCount(2); // only get the facet if there are 2 or more values for (String _facet : facet) { solrQuery.addFacetField(_facet); } } // execute Solr query QueryResponse response = solrServer.query(solrQuery); Set<T> entities = toEntities(response); Set<Facet> facets = toFacets(response); // create the service response ServiceResponse<T> serviceResponse = new ServiceResponse<T>(); serviceResponse.setSuccess(true); serviceResponse.setEntities(entities); serviceResponse.setCount(response.getResults().getNumFound()); serviceResponse.setFacets(facets); String msg = ReturnMessageProvider.findByQueryMessage(getTypeArgument(), query, entities.size()); serviceResponse.setMessage(msg); // return the response return serviceResponse; } catch (Exception e) { LOGGER.error("Failed to find entities by query for query = " + query, e); return new ServiceResponse<T>(getTypeArgument(), false, e.getMessage()); } } /** * A proxy method * * @param query * @param offset * @param maxResults * @param facets A string with field names for creating facets, separated by a comma (,) * @return * @throws CrafterCommerceException */ @RequestMapping(CrafterCommerceConstants.FIND_BY_QUERY_WITH_FACETS_ACTION_REST_MAPPING) public ServiceResponse<T> findByQueryWithFacets(@PathVariable String query, @PathVariable int offset, @PathVariable int maxResults, @PathVariable String facets) throws CrafterCommerceException { String[] facetsArray = facets.split(","); return findByQuery(query, offset, maxResults, facetsArray); } public ServiceResponse<T> findAll() throws CrafterCommerceException { try { String solrQueryStr = BaseType.SOLR_TYPE_FIELD + ":" + getTypeArgument().getName(); SolrQuery solrQuery = new SolrQuery(solrQueryStr); solrQuery.setRows((int) count().getCount()); SolrDocumentList solrDocList = solrServer.query(solrQuery).getResults(); Set<T> entities = new LinkedHashSet<T>(solrDocList.size()); for (SolrDocument _solrDoc : solrDocList) { entities.add(documentObjectBinder.getBean(getTypeArgument(), _solrDoc)); } ServiceResponse<T> sResponse = new ServiceResponse<T>(); sResponse.setSuccess(true); sResponse.setReturnedClass(getTypeArgument()); sResponse.setEntities(entities); sResponse.setMessage(ReturnMessageProvider.findAllMessage(getTypeArgument(), entities)); return sResponse; } catch (Exception e) { LOGGER.error("Failed to find all entities", e); return new ServiceResponse<T>(getTypeArgument(), false, e.getMessage()); } } public ServiceResponse<T> count() throws CrafterCommerceException { try { String solrQueryStr = BaseType.SOLR_TYPE_FIELD + ":" + getTypeArgument().getName(); SolrQuery solrQuery = new SolrQuery(solrQueryStr); solrQuery.setRows(0); long numfound = solrServer.query(solrQuery).getResults().getNumFound(); ServiceResponse<T> sResponse = new ServiceResponse<T>(); sResponse.setSuccess(true); sResponse.setReturnedClass(getTypeArgument()); sResponse.setCount(numfound); sResponse.setMessage(ReturnMessageProvider.countMessage(getTypeArgument(), numfound)); return sResponse; } catch (Exception e) { LOGGER.error("Failed to count all entities", e); return new ServiceResponse<T>(getTypeArgument(), false, e.getMessage()); } } public ServiceResponse<T> delete(@RequestBody T entity) throws CrafterCommerceException { try { solrServer.deleteByQuery(BaseType.SOLR_ID_FIELD + ":" + entity.getId()); solrServer.commit(); return new ServiceResponse<T>(getTypeArgument(), true, ReturnMessageProvider.deleteMessage(entity)); } catch (Exception e) { LOGGER.error("Failed to delete entity", e); return new ServiceResponse<T>(getTypeArgument(), false, e.getMessage()); } } public ServiceResponse<T> deleteAll() throws CrafterCommerceException { try { solrServer.deleteByQuery(BaseType.SOLR_TYPE_FIELD + ":" + getTypeArgument().getName()); solrServer.commit(); return new ServiceResponse<T>(getTypeArgument(), true, ReturnMessageProvider.deleteAllMessage(getTypeArgument())); } catch (Exception e) { LOGGER.error("Failed to delete all entities", e); return new ServiceResponse<T>(getTypeArgument(), false, e.getMessage()); } } public ServiceResponse<T> exists(@PathVariable String id) throws CrafterCommerceException { try { SolrQuery solrQuery = new SolrQuery(BaseType.SOLR_ID_FIELD + ":" + id); solrQuery.setRows(0); long numfound = solrServer.query(solrQuery).getResults().getNumFound(); boolean exists = (numfound != 0) ? true : false; return new ServiceResponse<T>(getTypeArgument(), true, exists, ReturnMessageProvider.existsMessage(getTypeArgument(), id, exists)); } catch (Exception e) { LOGGER.error("Failed check if entity exists for id = " + id, e); return new ServiceResponse<T>(getTypeArgument(), false, e.getMessage()); } } // ---------- Utility methods ---------- private Set<T> toEntities(QueryResponse response) { SolrDocumentList solrDocList = response.getResults(); Set<T> entities = new LinkedHashSet<T>(solrDocList.size()); for (SolrDocument _solrDoc : solrDocList) { entities.add(documentObjectBinder.getBean(getTypeArgument(), _solrDoc)); } return entities; } private Set<Facet> toFacets(QueryResponse response) { List<FacetField> facetFields = response.getFacetFields(); Set<Facet> facets = new LinkedHashSet<Facet>(facetFields.size()); Facet newFacet; FacetValue newFacetValue; for (FacetField _facetField : facetFields) { newFacet = new Facet(_facetField.getName()); for (Count _count : _facetField.getValues()) { newFacetValue = new FacetValue(_count.getName(), _count.getCount()); newFacet.getFacetValues().add(newFacetValue); } facets.add(newFacet); } return facets; } }