/** * ESUP-Portail Helpdesk - Copyright (c) 2004-2009 ESUP-Portail consortium. */ package org.esupportail.helpdesk.services.indexing; import java.sql.Timestamp; import java.util.List; import org.esupportail.commons.services.logging.Logger; import org.esupportail.commons.services.logging.LoggerImpl; import org.esupportail.commons.utils.Assert; import org.esupportail.helpdesk.domain.beans.ArchivedTicket; import org.esupportail.helpdesk.domain.beans.DeletedItem; import org.esupportail.helpdesk.domain.beans.Faq; import org.esupportail.helpdesk.domain.beans.Ticket; import org.esupportail.helpdesk.web.controllers.AbstractDomainAwareBean; /** * An abstract indexer to help in writing new indexers. */ @SuppressWarnings("serial") public abstract class AbstractIndexer extends AbstractDomainAwareBean implements Indexer { /** * The maximum number of documents to index at the same time. */ private static final int BATCH_SIZE = 500; /** * A logger. */ private final Logger logger = new LoggerImpl(getClass()); /** * The index id provider. */ private IndexIdProvider indexIdProvider; /** * Bean constructor. */ protected AbstractIndexer() { super(); } /** * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() */ @Override public void afterPropertiesSetInternal() { super.afterPropertiesSetInternal(); Assert.notNull(indexIdProvider, "property indexIdProvider of class " + this.getClass().getName() + " can not be null"); } /** * Update the index with the given elements. * @param tickets * @param removeBefore */ protected abstract void updateIndexTickets( List<Ticket> tickets, final boolean removeBefore); /** * Update the index with the given elements. * @param faqs * @param removeBefore */ protected abstract void updateIndexFaqs( List<Faq> faqs, final boolean removeBefore); /** * Update the index with the given elements. * @param archivedTickets * @param removeBefore */ protected abstract void updateIndexArchivedTickets( List<ArchivedTicket> archivedTickets, final boolean removeBefore); /** * Optimize the index. */ protected abstract void optimizeIndex(); /** * Remove the index. */ protected abstract void removeIndexInternal(); /** * @see org.esupportail.helpdesk.services.indexing.Indexer#removeIndex() */ @Override public void removeIndex() { logger.info("removing any existing indexing data..."); if (isIndexLocked()) { throw new IndexException("Lucene index is locked, try again later!"); } removeIndexInternal(); getDomainService().deleteAllDeletedItems(); getDomainService().resetIndexTimes(); logger.info("done."); } /** * Remove from the index the documents that correspond to entities that have been deleted. * @param deletedItems */ protected abstract void removeDeletedEntities(List<DeletedItem> deletedItems); /** * @see org.esupportail.helpdesk.services.indexing.Indexer#updateIndex(boolean) */ @Override public int updateIndex( final boolean removeBefore) { if (isIndexLocked()) { throw new IndexException("Lucene index is locked, try again later!"); } List<DeletedItem> deletedItems = getDomainService().getDeletedItems(); if (!deletedItems.isEmpty()) { removeDeletedEntities(deletedItems); for (DeletedItem deletedItem : deletedItems) { getDomainService().deleteDeletedItem(deletedItem); } } Timestamp now = new Timestamp(System.currentTimeMillis()); Timestamp lastUpdate; lastUpdate = getDomainService().getTicketsLastIndexTime(); if (lastUpdate == null) { lastUpdate = new Timestamp(0); } if (logger.isDebugEnabled()) { logger.debug("looking for tickets updated after [" + lastUpdate + "]..."); } List<Ticket> tickets = getDomainService().getTicketsChangedAfter(lastUpdate, BATCH_SIZE); if (tickets.size() != BATCH_SIZE) { getDomainService().setTicketsLastIndexTime(now); } else { getDomainService().setTicketsLastIndexTime( tickets.get(tickets.size() - 1).getLastActionDate()); } if (!tickets.isEmpty()) { logger.info("found " + tickets.size() + " ticket(s) updated after [" + lastUpdate + "], indexing..."); updateIndexTickets(tickets, removeBefore); return tickets.size(); } if (logger.isDebugEnabled()) { logger.debug("no ticket updated after [" + lastUpdate + "]"); } lastUpdate = getDomainService().getFaqsLastIndexTime(); if (lastUpdate == null) { lastUpdate = new Timestamp(0); } if (logger.isDebugEnabled()) { logger.debug("looking for FAQs updated after [" + lastUpdate + "]..."); } List<Faq> faqs = getDomainService().getFaqsChangedAfter(lastUpdate, BATCH_SIZE); if (faqs.size() != BATCH_SIZE) { getDomainService().setFaqsLastIndexTime(now); } else { getDomainService().setFaqsLastIndexTime( faqs.get(faqs.size() - 1).getLastUpdate()); } if (!faqs.isEmpty()) { logger.info("found " + faqs.size() + " FAQ(s) updated after [" + lastUpdate + "], indexing..."); updateIndexFaqs(faqs, removeBefore); return faqs.size(); } if (logger.isDebugEnabled()) { logger.debug("no FAQ updated after [" + lastUpdate + "]"); } getDomainService().setFaqsLastIndexTime(now); lastUpdate = getDomainService().getArchivedTicketsLastIndexTime(); if (lastUpdate == null) { lastUpdate = new Timestamp(0); } if (logger.isDebugEnabled()) { logger.debug("looking for archived tickets updated after [" + lastUpdate + "]..."); } List<ArchivedTicket> archivedTickets = getDomainService().getTicketsArchivedAfter(lastUpdate, BATCH_SIZE); if (archivedTickets.size() != BATCH_SIZE) { getDomainService().setArchivedTicketsLastIndexTime(now); } else { getDomainService().setArchivedTicketsLastIndexTime( archivedTickets.get(archivedTickets.size() - 1).getArchivingDate()); } if (!archivedTickets.isEmpty()) { logger.info("found " + archivedTickets.size() + " archived ticket(s) updated after [" + lastUpdate + "], indexing..."); updateIndexArchivedTickets(archivedTickets, removeBefore); return archivedTickets.size(); } if (logger.isDebugEnabled()) { logger.debug("no archived ticket updated after [" + lastUpdate + "]"); } getDomainService().setArchivedTicketsLastIndexTime(now); logger.info("optimizing..."); optimizeIndex(); logger.info("indexing completed."); return 0; } /** * @return True if the Lucene index is locked. */ protected abstract boolean isIndexLocked(); /** * @return the indexIdProvider */ protected IndexIdProvider getIndexIdProvider() { return indexIdProvider; } /** * @param indexIdProvider the indexIdProvider to set */ public void setIndexIdProvider(final IndexIdProvider indexIdProvider) { this.indexIdProvider = indexIdProvider; } /** * @see org.esupportail.helpdesk.services.indexing.Indexer#test() */ @Override public void test() { throw new UnsupportedOperationException(); } }