/** * Mad-Advertisement * Copyright (C) 2011 Thorsten Marx <thmarx@gmx.net> * * 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 net.mad.ads.db.db.index; import java.io.IOException; import java.util.ArrayList; import java.util.BitSet; import java.util.List; import org.apache.lucene.analysis.KeywordAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.index.Term; import org.apache.lucene.index.IndexWriterConfig.OpenMode; import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.TermQuery; import org.apache.lucene.search.BooleanClause.Occur; import org.apache.lucene.store.Directory; import org.apache.lucene.store.RAMDirectory; import org.apache.lucene.util.Version; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import net.mad.ads.db.AdDBConstants; import net.mad.ads.db.db.AdDB; import net.mad.ads.db.db.request.AdRequest; import net.mad.ads.db.db.search.BannerCollector; import net.mad.ads.db.definition.BannerDefinition; import net.mad.ads.db.enums.BannerFormat; import net.mad.ads.db.enums.BannerType; import net.mad.ads.db.utils.DocumentHelper; import net.mad.ads.db.utils.QueryHelper; public class AdDBLuceneIndex implements AdDBIndex { private static final Logger logger = LoggerFactory .getLogger(AdDBLuceneIndex.class); private Directory index = null; private IndexWriter writer = null; private IndexReader reader = null; private IndexSearcher searcher = null; private AdDB addb = null; public AdDBLuceneIndex(AdDB db) { this.addb = db; } @Override public void open() throws IOException { index = new RAMDirectory(); IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_33, new KeywordAnalyzer()); config.setOpenMode(OpenMode.CREATE); writer = new IndexWriter(index, config); this.reader = IndexReader.open(this.writer, true); this.searcher = new IndexSearcher(this.reader); } @Override public void close() throws IOException { this.writer.commit(); this.writer.optimize(); this.writer.close(); this.searcher.close(); this.reader.close(); this.index.close(); } @Override public void reopen() throws IOException { this.writer.optimize(); this.writer.commit(); IndexReader newReader = this.reader.reopen(); if (this.reader != newReader) { synchronized (this.reader) { this.reader.close(); this.reader = newReader; } synchronized (searcher) { this.searcher.close(); this.searcher = new IndexSearcher(this.reader); } } } @Override public void addBanner(BannerDefinition banner) throws IOException { Document doc = DocumentHelper.getInstance().getBannerDocument(banner); this.writer.addDocument(doc, new KeywordAnalyzer()); } @Override public void deleteBanner(String id) throws IOException { this.writer.deleteDocuments(new Term(AdDBConstants.ADDB_BANNER_ID, id)); } @Override public List<BannerDefinition> search(AdRequest request) throws IOException { // Collector für die Banner BannerCollector collector = new BannerCollector(this.reader.numDocs()); // MainQuery BooleanQuery mainQuery = new BooleanQuery(); // Query für den/die BannerTypen BooleanQuery typeQuery = new BooleanQuery(); for (BannerType type : request.getTypes()) { TermQuery tq = new TermQuery(new Term( AdDBConstants.ADDB_BANNER_TYPE, type.name())); typeQuery.add(tq, Occur.SHOULD); } mainQuery.add(typeQuery, Occur.MUST); // Query für den/die BannerFormate BooleanQuery formatQuery = new BooleanQuery(); for (BannerFormat format : request.getFormats()) { TermQuery tq = new TermQuery(new Term( AdDBConstants.ADDB_BANNER_FORMAT, format.getCompoundName())); formatQuery.add(tq, Occur.SHOULD); } mainQuery.add(formatQuery, Occur.MUST); // Query für die Bedingungen unter denen ein Banner angezeigt werden soll Query cq = QueryHelper.getInstance().getConditionalQuery(request); if (cq != null) { mainQuery.add(cq, Occur.MUST); } /* * Es sollen nur Produkte geliefert werden */ if (request.isProducts()) { mainQuery.add(new TermQuery(new Term(AdDBConstants.ADDB_BANNER_PRODUCT, AdDBConstants.ADDB_BANNER_PRODUCT_TRUE)), Occur.MUST); } else { mainQuery.add(new TermQuery(new Term(AdDBConstants.ADDB_BANNER_PRODUCT, AdDBConstants.ADDB_BANNER_PRODUCT_FALSE)), Occur.MUST); } logger.debug(mainQuery.toString()); // System.out.println(mainQuery.toString()); this.searcher.search(mainQuery, collector); BitSet hits = collector.getHits(); // Ergebnis List<BannerDefinition> result = new ArrayList<BannerDefinition>(); for (int i = hits.nextSetBit(0); i != -1; i = hits.nextSetBit(i + 1)) { Document doc = this.reader.document(i); result.add(addb.getBanner(doc.get(AdDBConstants.ADDB_BANNER_ID))); } return result; } @Override public int size() { if (this.reader != null) { return this.reader.numDocs(); } return 0; } }