content: /**
   * Copyright 2010 Karthik Kumar
   * 
   * 
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you 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.
   */
  package org.hbasene.index.search;
  
  import java.io.IOException;
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.LinkedList;
  import java.util.List;
  import java.util.Map;
  import java.util.TreeMap;
  
  import junit.framework.Assert;
  
  import org.apache.log4j.Logger;
  import org.apache.lucene.analysis.standard.StandardAnalyzer;
  import org.apache.lucene.document.Document;
  import org.apache.lucene.document.Field;
  import org.apache.lucene.index.CorruptIndexException;
  import org.apache.lucene.index.Term;
  import org.apache.lucene.search.IndexSearcher;
  import org.apache.lucene.search.ScoreDoc;
  import org.apache.lucene.search.Sort;
  import org.apache.lucene.search.SortField;
  import org.apache.lucene.search.TermQuery;
  import org.apache.lucene.search.TopDocs;
  import org.apache.lucene.util.Version;
  import org.hbasene.index.AbstractHBaseneTest;
  import org.hbasene.index.search.HBaseIndexSearcher;
  import org.junit.Test;
  
  
  public class TestHBaseIndexSearcher extends AbstractHBaseneTest {
  
    private static final Logger LOG = Logger
        .getLogger(TestHBaseIndexSearcher.class.getName());
  
    private static final String[] AIRPORTS = { "NYC", "JFK", "EWR", "SEA", "SFO",
        "OAK", "SJC" };
  
    private final Map<String, List<Integer>> airportMap = new TreeMap<String, List<Integer>>();
  
    private HBaseIndexSearcher indexSearcher;
  
    @Override
    protected void doSetupDerived() throws CorruptIndexException, IOException {
      this.indexSearcher = new HBaseIndexSearcher(this.indexReader);
    }
  
    @Override
    protected void doInitDocs() throws CorruptIndexException, IOException {
      for (int i = 100; i >= 0; --i) {
        Document doc = this.getDocument(i);
        indexWriter.addDocument(doc, new StandardAnalyzer(Version.LUCENE_30));
      }
    }
  
    private Document getDocument(int i) {
      Document doc = new Document();
      doc.add(new Field("id", "doc" + i, Field.Store.YES, Field.Index.NO));
      int randomIndex = (int) (Math.random() * 7.0f);
      doc.add(new Field("airport", AIRPORTS[randomIndex], Field.Store.NO,
          Field.Index.ANALYZED_NO_NORMS));
      doc.add(new Field("searchterm", Math.random() > 0.5f ? "always" : "never",
          Field.Store.NO, Field.Index.ANALYZED_NO_NORMS));
      recordRandomIndex(100 - i, randomIndex);
      return doc;
    }
  
    private void recordRandomIndex(final int docIndex, final int airportIndex) {
      List<Integer> docs = airportMap.get(AIRPORTS[airportIndex]);
      if (docs == null) {
        docs = new LinkedList<Integer>();
        airportMap.put(AIRPORTS[airportIndex], docs);
      }
      docs.add(docIndex);
    }
  
    @Test
    public void testSortFieldAsc() throws IOException {
      LOG.info(this.airportMap.toString());
      TermQuery termQuery = new TermQuery(new Term("searchterm", "always"));
      Sort sort = new Sort(new SortField("airport", SortField.STRING));
      TopDocs docs = this.indexSearcher.search(termQuery
          .createWeight(indexSearcher), null, 25, sort, false);
      LOG.info("Total results are " + docs.scoreDocs.length);
      this.printScoreDocs(docs.scoreDocs, "Sorted ");
      assertSortOrderAsc(docs.scoreDocs);
  
    }
  
    @Test
    public void testSortFieldDesc() throws IOException {
      LOG.info(this.airportMap.toString());
      TermQuery termQuery = new TermQuery(new Term("searchterm", "always"));
      Sort sort = new Sort(new SortField("airport", SortField.STRING, true));
      //sort by reverse
      TopDocs docs = this.indexSearcher.search(termQuery
          .createWeight(indexSearcher), null, 25, sort, false);
      LOG.info("Total results are " + docs.scoreDocs.length);
      this.printScoreDocs(docs.scoreDocs, "Sorted ");
      assertSortOrderDesc(docs.scoreDocs);
    }
  
    
    public void tistNonExistentSortField() throws IOException {
      LOG.info(this.airportMap.toString());
      IndexSearcher searcher = new IndexSearcher(this.indexReader);
      try {
        TopDocs docs = searcher.search(new TermQuery(new Term("searchterm",
            "always")), 90);
        LOG.info("Total results are " + docs.scoreDocs.length);
        this.printScoreDocs(docs.scoreDocs, "Original Order ");
        // ScoreDoc[] result = this.metaReader.sort(docs.scoreDocs, "airport1");
        // TODO: This method should throw an exception for an invalid field to be
        // sorted.
  
      } finally {
        searcher.close();
      }
    }
  
    void printScoreDocs(final ScoreDoc[] scoreDocs, final String prefix) {
      List<Integer> originalOrder = new ArrayList<Integer>();
      for (ScoreDoc scoreDoc : scoreDocs) {
        originalOrder.add(scoreDoc.doc);
      }
      LOG.info(prefix + " is " + originalOrder);
    }
  
    void assertSortOrderAsc(final ScoreDoc[] result) {
      Map<Integer, String> reverseMap = new HashMap<Integer, String>();
      for (final Map.Entry<String, List<Integer>> entry : this.airportMap
          .entrySet()) {
        for (final Integer docId : entry.getValue()) {
          reverseMap.put(docId, entry.getKey());
        }
      }
      String previousAirport = "000";
      for (final ScoreDoc scoreDoc : result) {
        String currentAirport = reverseMap.get(scoreDoc.doc);
        Assert.assertTrue(currentAirport + " vs " + previousAirport,
            currentAirport.compareTo(previousAirport) >= 0);
        previousAirport = currentAirport;
      }
    }
  
    void assertSortOrderDesc(final ScoreDoc[] result) {
      Map<Integer, String> reverseMap = new HashMap<Integer, String>();
      for (final Map.Entry<String, List<Integer>> entry : this.airportMap
          .entrySet()) {
        for (final Integer docId : entry.getValue()) {
          reverseMap.put(docId, entry.getKey());
        }
      }
      String previousAirport = "zzz";
      for (final ScoreDoc scoreDoc : result) {
        String currentAirport = reverseMap.get(scoreDoc.doc);
        Assert.assertTrue(currentAirport + " vs " + previousAirport,
            currentAirport.compareTo(previousAirport) <= 0);
        previousAirport = currentAirport;
      }
    }
  }
  