/* * This is a common dao with basic CRUD operations and is not limited to any * persistent layer implementation * * Copyright (C) 2010 Imran M Yousuf (imyousuf@smartitengineering.com) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package com.smartitengineering.common.dao.search.solr; import com.google.inject.Inject; import com.google.inject.name.Named; import com.smartitengineering.common.dao.search.CommonFreeTextPersistentDao; import com.smartitengineering.common.dao.search.solr.spi.ObjectIdentifierQuery; import com.smartitengineering.dao.solr.MultivalueMap; import com.smartitengineering.dao.solr.SolrWriteDao; import com.smartitengineering.util.bean.adapter.GenericAdapter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * * @author imyousuf */ public class SolrFreeTextPersistentDao<T> implements CommonFreeTextPersistentDao<T> { @Inject private GenericAdapter<T, MultivalueMap<String, Object>> adapter; @Inject(optional = true) private GenericAdapter<T, List<MultivalueMap<String, Object>>> multiAdapter; @Inject protected SolrWriteDao writeDao; @Inject private ObjectIdentifierQuery<T> query; @Inject private ExecutorService executorService; @Inject @Named("waitTime") private long waitTime; @Inject @Named("waitTimeUnit") private TimeUnit waitTimeUnit; protected final Logger logger = LoggerFactory.getLogger(getClass()); @Override public void save(final T... data) { List<Future<Status<T>>> deletes = new ArrayList<Future<Status<T>>>(data.length); deletes.add(executorService.submit(new Callable<Status<T>>() { @Override public Status<T> call() throws Exception { List<MultivalueMap<String, Object>> docs = new ArrayList<MultivalueMap<String, Object>>(); List<MultivalueMap<String, Object>> mDocs; int i = 0; for (final T datum : data) { MultivalueMap<String, Object> doc = adapter.convert(datum); if (doc != null) { docs.add(doc); } if (multiAdapter != null) { mDocs = multiAdapter.convert(datum); if (mDocs != null && !mDocs.isEmpty()) { docs.addAll(mDocs); } } } final boolean success; MultivalueMap<String, Object> fields[] = docs.toArray(new MultivalueMap[docs.size()]); success = writeDao.add(fields); Status<T> status = new Status<T>(); status.success = success; status.queryStr = Arrays.toString(fields); return status; } })); List<Status<T>> failures = new ArrayList<Status<T>>(); for (Future<Status<T>> future : deletes) { try { Status<T> status = future.get(waitTime, waitTimeUnit); if (!status.success) { failures.add(status); } } catch (Exception ex) { logger.warn("Could not get add status!", ex); } } if (!failures.isEmpty()) { throw new IllegalStateException(new StringBuilder("Could add all data: ").append(Arrays.toString( failures.toArray())).toString()); } } @Override public void update(T... data) { delete(data); save(data); } @Override public void delete(final T... data) { List<Future<Status<T>>> deletes = new ArrayList<Future<Status<T>>>(); deletes.add(executorService.submit(new Callable<Status<T>>() { @Override public Status<T> call() throws Exception { final boolean success; String[] queries = new String[data.length]; int i = 0; for (final T datum : data) { queries[i++] = query.getQuery(datum); } success = writeDao.deleteByQuery(queries); Status<T> status = new Status<T>(); status.success = success; status.queryStr = Arrays.toString(queries); return status; } })); List<Status<T>> failures = new ArrayList<Status<T>>(); for (Future<Status<T>> future : deletes) { try { Status<T> status = future.get(waitTime, waitTimeUnit); if (!status.success) { failures.add(status); } } catch (Exception ex) { logger.warn("Could not get delete status!", ex); } } if (!failures.isEmpty()) { throw new IllegalStateException(new StringBuilder("Could delete all data: ").append(Arrays.toString(failures. toArray())).toString()); } } private static class Status<T> { boolean success; String queryStr; @Override public String toString() { return "Status{" + "success=" + success + ", queryStr=" + queryStr + '}'; } } public GenericAdapter<T, MultivalueMap<String, Object>> getAdapter() { return adapter; } public void setAdapter(GenericAdapter<T, MultivalueMap<String, Object>> adapter) { this.adapter = adapter; } public ExecutorService getExecutorService() { return executorService; } public void setExecutorService(ExecutorService executorService) { this.executorService = executorService; } public ObjectIdentifierQuery<T> getQuery() { return query; } public void setQuery(ObjectIdentifierQuery<T> query) { this.query = query; } public SolrWriteDao getWriteDao() { return writeDao; } public void setWriteDao(SolrWriteDao writeDao) { this.writeDao = writeDao; } public long getWaitTime() { return waitTime; } public void setWaitTime(long waitTime) { this.waitTime = waitTime; } public TimeUnit getWaitTimeUnit() { return waitTimeUnit; } public void setWaitTimeUnit(TimeUnit waitTimeUnit) { this.waitTimeUnit = waitTimeUnit; } }