/**
 * Copyright 2005 The Apache Software Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.io.IOException;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.FuzzyQuery;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Searcher;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.WildcardQuery;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.Scorer;

/**
 * Die Code-Beispiele aus dem c't-Artikel ueber Lucene.
 * 
 * Created on 30.01.2005
 * @author Daniel Naber (daniel.naber at intrafind.de)
 */

public class ArtikelBeispiele {

  // in diesem Verzeichnis wird der Index abgelegt:
  private static final String LUCENE_INDEX = "luceneindex";

  public static void main(String[] args) throws IOException, ParseException {
    ArtikelBeispiele prg = new ArtikelBeispiele();
    prg.simpleIndex();
    prg.searchDocument();
    prg.highlightMatches();
    prg.makeQuery();
    prg.makeQuery2();
  }
  
  private void simpleIndex() throws IOException {
    // Listing 1: ------------------------------------------------------
    Analyzer analyzer = new StandardAnalyzer();
    IndexWriter writer = new IndexWriter(LUCENE_INDEX, analyzer, true);
    writer.maxFieldLength = 200000;
    Document doc = new Document();
    Field fld = new Field("body", "This is a test: $100, foo-bar, ...",
        true, true, true);
    doc.add(fld);
    writer.addDocument(doc);
    // Hier könnten weitere Document-Objekte erstellt und dem IndexWriter
    // übergeben werden...
    writer.optimize();
    writer.close();
    // Ende Listing 1 --------------------------------------------------
  }

  private void searchDocument() throws IOException, ParseException {
    // Listing 2: ------------------------------------------------------
    IndexReader indexReader = IndexReader.open(LUCENE_INDEX);
    Searcher searcher = new IndexSearcher(indexReader);
    Analyzer analyzer = new StandardAnalyzer();
    QueryParser qparser = new QueryParser("body", analyzer);
    qparser.setOperator(QueryParser.DEFAULT_OPERATOR_AND);
    Query query = qparser.parse("foo test");
    System.out.println("Query: " + query);
    Hits hits = searcher.search(query);
    for (int i = 0; i < hits.length(); i++) {
      Document hitDoc = hits.doc(i);
      System.out.println("Relevanz: " + hits.score(i));
      System.out.println("Dokument: " + hitDoc.get("body"));
    }
    searcher.close();
    indexReader.close();
    // Ende Listing 2 --------------------------------------------------
  }
  
  private void highlightMatches() throws IOException, ParseException {

    IndexReader indexReader = IndexReader.open(LUCENE_INDEX);
    Searcher searcher = new IndexSearcher(indexReader);
    Analyzer analyzer = new StandardAnalyzer();
    QueryParser qparser = new QueryParser("body", analyzer);
    qparser.setOperator(QueryParser.DEFAULT_OPERATOR_AND);
    Query query = qparser.parse("foo test");
    Hits hits = searcher.search(query);
    
    // Listing 4: ------------------------------------------------------
    Scorer scorer = new QueryScorer(query.rewrite(indexReader));
    Highlighter highlighter = new Highlighter(scorer);
    for (int i = 0; i < hits.length(); i++) {
      Document hitDoc = hits.doc(i);
      String bodyText = hitDoc.get("body");
      String snippet = highlighter.getBestFragment(analyzer, "field", bodyText);
      System.out.println("Summary: " + snippet);
    }
    // Ende Listing 4 --------------------------------------------------

    searcher.close();
    indexReader.close();
  }

  private void makeQuery() throws IOException {
    
    Analyzer analyzer = new StandardAnalyzer();
    IndexWriter writer = new IndexWriter(LUCENE_INDEX, analyzer, true);
    writer.maxFieldLength = 200000;
    Document doc = new Document();
    Field fld = new Field("body", "Schmidt... Meier", true, true, true);
    doc.add(fld);
    writer.addDocument(doc);
    doc = new Document();
    fld = new Field("body", "Schmidt... Maier", true, true, true);
    doc.add(fld);
    writer.addDocument(doc);
    writer.close();
    Searcher searcher = new IndexSearcher(LUCENE_INDEX);

    // Listing 3: ------------------------------------------------------
    BooleanQuery query = new BooleanQuery();
    query.add(new TermQuery(new Term("body", "schmidt")), true, false);
    query.add(new WildcardQuery(new Term("body", "m?ier")), true, false);
    // Ende Listing 3 --------------------------------------------------
    
    Hits hits = searcher.search(query);
    System.out.println("query.toString()=" + query);
    System.out.println("hits.length()=" + hits.length());
  }

  private void makeQuery2() throws ParseException {

    String input = "(m??er AND NOT maier) OR (helmut AND schmidt~)";

    Query query1 = QueryParser.parse(input, "body", new StandardAnalyzer());
    System.out.println("Parsing der folgenden Suchanfrage mit dem QueryParser:");
    System.out.println(input);
    System.out.println("Ausgabe von Query.toString();");
    System.out.println(query1);

    BooleanQuery subQuery1 = new BooleanQuery();
    subQuery1.add(new WildcardQuery(new Term("body", "m??er")), true, false);
    subQuery1.add(new TermQuery(new Term("body", "maier")), false, true);
    
    BooleanQuery subQuery2 = new BooleanQuery();
    subQuery2.add(new TermQuery(new Term("body", "helmut")), true, false);
    subQuery2.add(new FuzzyQuery(new Term("body", "schmidt")), true, false);

    BooleanQuery query2 = new BooleanQuery();
    query2.add(subQuery1, false, false);
    query2.add(subQuery2, false, false);

    System.out.println("Die gleiche Query, diesmal programmatisch erstellt:");
    System.out.println(query2);
    
  }

}
