/*********************************************************************************************************************
 * Copyright (c) 2008, 2015 Empolis Information Management GmbH and brox IT Solutions GmbH. All rights reserved.
 * This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 
 * which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html
**********************************************************************************************************************/
package org.eclipse.smila.solr.search;

import java.util.ArrayList;
import java.util.List;

import junit.framework.TestCase;

import org.apache.solr.client.solrj.impl.CloudSolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.SolrResponseBase;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.params.CursorMarkParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.eclipse.smila.datamodel.AnyMap;
import org.eclipse.smila.datamodel.AnySeq;
import org.eclipse.smila.datamodel.DataFactory;
import org.eclipse.smila.datamodel.Record;
import org.eclipse.smila.search.api.SearchResultConstants;
import org.eclipse.smila.solr.SolrConfig;
import org.eclipse.smila.solr.SolrConstants;
import org.eclipse.smila.solr.params.SolrParams;

public class SolrResponseParser_Test extends TestCase {

  private final String ID_FIELD = "_recordid";

  private final DataFactory _factory = DataFactory.DEFAULT;

  private SolrConfig getSolrConfig() {
    final AnyMap config = _factory.createAnyMap();
    final AnyMap idFields = config.getMap(SolrConfig.ID_FIELDS, true);
    idFields.put(ID_FIELD, ID_FIELD);
    final SolrConfig solrConfig = new SolrConfig(config);
    return solrConfig;
  }

  public void test_toRecordResponseBaseDefault() {
    final SolrResponseBase solrResponse = new SolrResponseBase();
    {
      final NamedList<Object> response = new NamedList<>();
      final NamedList<Object> responseHeader = new NamedList<>();
      responseHeader.add("key", "val");
      responseHeader.add("key2", "val2");
      response.add(SolrConstants.RESPONSE_HEADER, responseHeader);
      solrResponse.setResponse(response);
    }
    final ResponseParser parser = new ResponseParser(_factory.createRecord(), getSolrConfig(), ID_FIELD);
    final Record result = parser.toRecord(solrResponse);
    final AnyMap responseHeader =
      result.getMetadata().getMap(SolrParams.SOLR_PARAMETER_ATTRIBUTE).getMap(ResponseAccessor.RESPONSE)
        .getMap(SolrConstants.RESPONSE_HEADER);
    assertNotNull(responseHeader);
    assertEquals("val", responseHeader.getStringValue("key"));
    assertEquals("val2", responseHeader.getStringValue("key2"));
  }

  public void test_parseFieldFacets() {
    final NamedList<Object> response = new NamedList<>();
    {
      final NamedList<Object> facetCounts = new NamedList<>();
      response.add("facet_counts", facetCounts);

      final NamedList<NamedList<Number>> facetFields = new NamedList<>();
      facetCounts.add("facet_fields", facetFields);
      final NamedList<Number> facetField = new NamedList<>();
      facetFields.add("field", facetField);
      facetField.add("from", 1);
      facetField.add("to", 2);

    }
    final QueryResponse queryResponse = new QueryResponse(response, new CloudSolrServer("localhost"));
    final ResponseParser parser = new ResponseParser(_factory.createRecord(), getSolrConfig(), ID_FIELD);
    {
      final Record result = parser.toRecord(queryResponse);
      final AnyMap facets = result.getMetadata().getMap(SearchResultConstants.FACETS);
      assertNotNull(facets);
      final AnyMap from = facets.getSeq("field").getMap(0);
      final AnyMap to = facets.getSeq("field").getMap(1);
      assertNotNull(from);
      assertNotNull(to);
      assertEquals("from", from.getStringValue(SearchResultConstants.VALUE));
      assertEquals(1, from.getLongValue(SearchResultConstants.COUNT).intValue());
      assertEquals("to", to.getStringValue(SearchResultConstants.VALUE));
      assertEquals(2, to.getLongValue(SearchResultConstants.COUNT).intValue());
    }
  }

  public void test_parseRangeFacets() {
    final NamedList<Object> response = new NamedList<>();
    {
      final NamedList<Object> facetCounts = new NamedList<>();
      response.add("facet_counts", facetCounts);

      final NamedList<NamedList<Object>> facetRanges = new NamedList<>();
      facetCounts.add("facet_ranges", facetRanges);
      final NamedList<Object> facetRange = new NamedList<>();
      facetRanges.add(SolrConstants.RANGE, facetRange);
      facetRange.add(SolrConstants.GAP, 5);
      facetRange.add(SolrConstants.START, 1);
      facetRange.add(SolrConstants.END, 10);
      facetRange.add("before", 2);
      facetRange.add("after", 3);
      facetRange.add("between", 4);
      final NamedList<Integer> counts = new NamedList<>();
      counts.add("one", 1);
      counts.add("two", 2);
      facetRange.add("counts", counts);
    }
    final QueryResponse queryResponse = new QueryResponse(response, new CloudSolrServer("localhost"));
    final ResponseParser parser = new ResponseParser(_factory.createRecord(), getSolrConfig(), ID_FIELD);
    {
      final Record result = parser.toRecord(queryResponse);
      final AnySeq range = result.getMetadata().getMap(SolrConstants.FACETS).getSeq(SolrConstants.RANGE);
      assertNotNull(range);
      final AnyMap one = range.getMap(0);
      final AnyMap two = range.getMap(1);
      assertEquals("one", one.getStringValue(SearchResultConstants.VALUE));
      assertEquals(1, one.getLongValue(SearchResultConstants.COUNT).intValue());
      assertEquals("two", two.getStringValue(SearchResultConstants.VALUE));
      assertEquals(2, two.getLongValue(SearchResultConstants.COUNT).intValue());
    }
  }

  public void test_parseQueryFacets() {
    final NamedList<Object> response = new NamedList<>();
    {
      final NamedList<Object> facetCounts = new NamedList<>();
      response.add("facet_counts", facetCounts);

      final NamedList<Integer> facetQueries = new NamedList<>();
      facetCounts.add("facet_queries", facetQueries);
      facetQueries.add("query1", 1);
      facetQueries.add("query2", 2);
    }
    final QueryResponse queryResponse = new QueryResponse(response, new CloudSolrServer("localhost"));
    final ResponseParser parser = new ResponseParser(_factory.createRecord(), getSolrConfig(), ID_FIELD);
    {
      final Record result = parser.toRecord(queryResponse);
      final AnySeq queries = result.getMetadata().getMap(SolrConstants.FACETS).getSeq(SolrConstants.QUERIES);
      assertNotNull(queries);
      final AnyMap one = queries.getMap(0);
      final AnyMap two = queries.getMap(1);
      assertNotNull(one);
      assertNotNull(two);
      assertEquals("query1", one.getStringValue(SearchResultConstants.VALUE));
      assertEquals(1, one.getLongValue(SearchResultConstants.COUNT).intValue());
      assertEquals("query2", two.getStringValue(SearchResultConstants.VALUE));
      assertEquals(2, two.getLongValue(SearchResultConstants.COUNT).intValue());
    }
  }

  public void test_parseIntervalFacets() {
    final NamedList<Object> response = new NamedList<>();
    {
      final NamedList<Object> facetCounts = new NamedList<>();
      response.add("facet_counts", facetCounts);

      final NamedList<NamedList<Object>> facetIntervals = new NamedList<>();
      facetCounts.add("facet_intervals", facetIntervals);
      final NamedList<Object> facetInterval = new NamedList<>();
      facetIntervals.add("title", facetInterval);
      facetInterval.add("0-5", 2);
      facetInterval.add("6-10", 3);
    }
    final QueryResponse queryResponse = new QueryResponse(response, new CloudSolrServer("localhost"));
    final ResponseParser parser = new ResponseParser(_factory.createRecord(), getSolrConfig(), ID_FIELD);
    {
      final Record result = parser.toRecord(queryResponse);
      final AnySeq title = result.getMetadata().getMap(SearchResultConstants.FACETS).getSeq("title");
      assertNotNull(title);
      assertEquals("0-5", title.getMap(0).getStringValue(SearchResultConstants.VALUE));
      assertEquals(2, title.getMap(0).getLongValue(SearchResultConstants.COUNT).intValue());
      assertEquals("6-10", title.getMap(1).getStringValue(SearchResultConstants.VALUE));
      assertEquals(3, title.getMap(1).getLongValue(SearchResultConstants.COUNT).intValue());
    }
  }

  public void test_grouping() {
    final NamedList<Object> response = new NamedList<>();
    {
      final NamedList<Object> grouped = new NamedList<>();
      response.add("grouped", grouped);

      final String fieldName = "author";
      final SimpleOrderedMap<Object> fieldGroups = new SimpleOrderedMap<>();
      grouped.add(fieldName, fieldGroups);

      final Integer matches = 3;
      final Integer nGroups = 2;
      final ArrayList<SimpleOrderedMap<Object>> groups = new ArrayList<>();
      final SimpleOrderedMap<Object> groupsMap = new SimpleOrderedMap<>();
      groups.add(groupsMap);
      groupsMap.add("groupValue", "Mann");
      groupsMap.add("doclist", new SolrDocumentList());
      final SolrDocumentList docList = new SolrDocumentList();

      fieldGroups.add(SearchResultConstants.MATCHES, matches);
      fieldGroups.add(SolrConstants.NGROUPS, nGroups);
      fieldGroups.add(SearchResultConstants.GROUPS, groups);
      fieldGroups.add("doclist", docList);
    }

    final QueryResponse queryResponse = new QueryResponse(response, new CloudSolrServer("localhost"));

    final ResponseParser parser = new ResponseParser(_factory.createRecord(), getSolrConfig(), ID_FIELD);
    {
      final Record result = parser.toRecord(queryResponse);
      final Long matches =
        result.getMetadata().getMap(SearchResultConstants.GROUPS).getLongValue(SearchResultConstants.MATCHES);
      assertEquals(3, matches.intValue());
      final AnyMap author = result.getMetadata().getMap(SearchResultConstants.GROUPS).getSeq("author").getMap(0);
      assertEquals("Mann", author.getStringValue(SearchResultConstants.VALUE));
      assertEquals(0, author.getLongValue(SearchResultConstants.COUNT).intValue());
      assertEquals(0, author.getSeq(SearchResultConstants.RESULTS).size());
    }

  }

  public void test_parseTerms() {
    final NamedList<Object> response = new NamedList<>();
    {
      final NamedList<NamedList<Number>> terms = new NamedList<>();
      response.add(SolrConstants.TERMS, terms);

      final NamedList<Number> fieldName1 = new NamedList<>();
      final NamedList<Number> fieldName2 = new NamedList<>();
      terms.add("fieldName1", fieldName1);
      terms.add("fieldName2", fieldName2);

      fieldName1.add("name1", 23);
      fieldName1.add("name2", 32);

      fieldName2.add("name3", 5);
      fieldName2.add("name4", 12);
    }
    final QueryResponse queryResponse = new QueryResponse(response, new CloudSolrServer("localhost"));
    final ResponseParser parser = new ResponseParser(_factory.createRecord(), getSolrConfig(), ID_FIELD);
    {
      final Record result = parser.toRecord(queryResponse);
      final AnyMap terms =
        result.getMetadata().getMap(SolrParams.SOLR_PARAMETER_ATTRIBUTE).getMap(ResponseAccessor.RESPONSE)
          .getMap(SolrConstants.TERMS);
      assertNotNull(terms.get("fieldName1"));
      assertNotNull(terms.get("fieldName2"));
      assertEquals(23, terms.getMap("fieldName1").getLongValue("name1").intValue());
      assertEquals(32, terms.getMap("fieldName1").getLongValue("name2").intValue());
      assertEquals(5, terms.getMap("fieldName2").getLongValue("name3").intValue());
      assertEquals(12, terms.getMap("fieldName2").getLongValue("name4").intValue());
    }
  }

  public void test_parseSpellcheck() {
    final NamedList<Object> response = new NamedList<>();
    {
      final NamedList<NamedList<Object>> spellcheck = new NamedList<>();
      response.add(SolrConstants.SPELLCHECK, spellcheck);
      final NamedList<Object> suggestions = new NamedList<>();
      spellcheck.add(SolrConstants.SUGGESTIONS, suggestions);
      final NamedList<Object> sugg = new NamedList<>();
      sugg.add(SolrConstants.START_OFFSET, 1);
      sugg.add(SolrConstants.END_OFFSET, 2);
      sugg.add(SolrConstants.ORIG_FREQ, 3);
      final List<String> alternatives = new ArrayList<>();
      alternatives.add("Oldtimer");
      alternatives.add("oldtimern");
      sugg.add("suggestion", alternatives);
      suggestions.add("Olktimer", sugg);
    }
    final QueryResponse queryResponse = new QueryResponse(response, new CloudSolrServer("localhost"));
    final ResponseParser parser = new ResponseParser(_factory.createRecord(), getSolrConfig(), ID_FIELD);
    {
      final Record result = parser.toRecord(queryResponse);
      final AnyMap suggestions =
        result.getMetadata().getMap(SolrParams.SOLR_PARAMETER_ATTRIBUTE).getMap(ResponseAccessor.RESPONSE)
          .getMap(SolrConstants.SPELLCHECK).getMap(SolrConstants.SUGGESTIONS);
      assertNotNull(suggestions);
      final AnyMap olktimer = suggestions.getMap("Olktimer");
      assertNotNull(olktimer);
      assertEquals(0, olktimer.getLongValue(SolrConstants.NUM_FOUND).intValue());
      assertEquals(1, olktimer.getLongValue(SolrConstants.START_OFFSET).intValue());
      assertEquals(2, olktimer.getLongValue(SolrConstants.END_OFFSET).intValue());
      assertEquals(3, olktimer.getLongValue(SolrConstants.ORIG_FREQ).intValue());
      final AnySeq suggestion = olktimer.getSeq(SolrConstants.SUGGESTION);
      assertEquals("Oldtimer", suggestion.getStringValue(0));
      assertEquals("oldtimern", suggestion.getStringValue(1));
    }
  }

  @SuppressWarnings("unchecked")
  public void test_parseSpellcheckExtendedResults() {
    final NamedList<Object> response = new NamedList<>();
    {
      final NamedList<NamedList<Object>> spellcheck = new NamedList<>();
      response.add(SolrConstants.SPELLCHECK, spellcheck);
      final NamedList<Object> suggestions = new NamedList<>();
      spellcheck.add(SolrConstants.SUGGESTIONS, suggestions);
      final NamedList<Object> sugg = new NamedList<>();
      sugg.add(SolrConstants.START_OFFSET, 1);
      sugg.add(SolrConstants.END_OFFSET, 2);
      sugg.add(SolrConstants.ORIG_FREQ, 3);
      @SuppressWarnings("rawtypes")
      final List<NamedList> alternatives = new ArrayList<>();
      @SuppressWarnings("rawtypes")
      final NamedList oldtimer = new NamedList<>();
      oldtimer.add(SolrConstants.WORD, "Oldtimer");
      oldtimer.add(SolrConstants.FREQ, 3);
      alternatives.add(oldtimer);
      @SuppressWarnings("rawtypes")
      final NamedList oltimern = new NamedList<>();
      oltimern.add(SolrConstants.WORD, "oldtimern");
      oltimern.add(SolrConstants.FREQ, 2);
      alternatives.add(oltimern);
      sugg.add(SolrConstants.SUGGESTION, alternatives);
      suggestions.add("Olktimer", sugg);
    }
    final QueryResponse queryResponse = new QueryResponse(response, new CloudSolrServer("localhost"));
    final ResponseParser parser = new ResponseParser(_factory.createRecord(), getSolrConfig(), ID_FIELD);
    {
      final Record result = parser.toRecord(queryResponse);
      final AnyMap suggestions =
        result.getMetadata().getMap(SolrParams.SOLR_PARAMETER_ATTRIBUTE).getMap(ResponseAccessor.RESPONSE)
          .getMap(SolrConstants.SPELLCHECK).getMap(SolrConstants.SUGGESTIONS);
      assertNotNull(suggestions);
      final AnyMap olktimer = suggestions.getMap("Olktimer");
      assertNotNull(olktimer);
      assertEquals(0, olktimer.getLongValue(SolrConstants.NUM_FOUND).intValue());
      assertEquals(1, olktimer.getLongValue(SolrConstants.START_OFFSET).intValue());
      assertEquals(2, olktimer.getLongValue(SolrConstants.END_OFFSET).intValue());
      assertEquals(3, olktimer.getLongValue(SolrConstants.ORIG_FREQ).intValue());
      final AnySeq suggestion = olktimer.getSeq(SolrConstants.SUGGESTION);
      final AnyMap oldtimer = suggestion.getMap(0);
      assertEquals("Oldtimer", oldtimer.getStringValue(SolrConstants.WORD));
      assertEquals(3, oldtimer.getLongValue(SolrConstants.FREQ).intValue());
      final AnyMap oldtimern = suggestion.getMap(1);
      assertEquals("oldtimern", oldtimern.getStringValue(SolrConstants.WORD));
      assertEquals(2, oldtimern.getLongValue(SolrConstants.FREQ).intValue());

    }
  }

  public void test_parseSpellcheckExtendedCollations() {
    final NamedList<Object> response = new NamedList<>();
    {
      final NamedList<NamedList<Object>> spellcheck = new NamedList<>();
      response.add(SolrConstants.SPELLCHECK, spellcheck);
      final NamedList<Object> suggestions = new NamedList<>();
      spellcheck.add(SolrConstants.SUGGESTIONS, suggestions);
      final NamedList<Object> expandedCollation = new NamedList<>();
      suggestions.add(SolrConstants.COLLATION, expandedCollation);
      expandedCollation.add(SolrConstants.COLLATION_QUERY, "q=query");
      expandedCollation.add(SolrConstants.HITS, 9);
      final NamedList<String> misspellingsAndCorrections = new NamedList<>();
      expandedCollation.add(SolrConstants.MISSPELLINGS_AND_CORRECTIONS, misspellingsAndCorrections);
      misspellingsAndCorrections.add("Olktimer", "Oldtimer");
      misspellingsAndCorrections.add("Oldtimern", "oldtimern");

    }
    final QueryResponse queryResponse = new QueryResponse(response, new CloudSolrServer("localhost"));
    final ResponseParser parser = new ResponseParser(_factory.createRecord(), getSolrConfig(), ID_FIELD);
    {
      final Record result = parser.toRecord(queryResponse);
      final AnyMap spellcheck =
        result.getMetadata().getMap(SolrParams.SOLR_PARAMETER_ATTRIBUTE).getMap(ResponseAccessor.RESPONSE)
          .getMap(SolrConstants.SPELLCHECK);
      assertNotNull(spellcheck);
      final AnyMap collations = spellcheck.getSeq(SolrConstants.COLLATIONS).getMap(0);
      assertEquals("q=query", collations.getStringValue(SolrConstants.COLLATION_QUERY));
      assertEquals(9, collations.getLongValue(SolrConstants.HITS).intValue());
      final AnyMap misspellingsAndCorrections = collations.getMap(SolrConstants.MISSPELLINGS_AND_CORRECTIONS);
      assertEquals("Oldtimer", misspellingsAndCorrections.getStringValue("Olktimer"));
      assertEquals("oldtimern", misspellingsAndCorrections.getStringValue("Oldtimern"));
    }
  }

  public void test_moreLikeThis() {
    final NamedList<Object> response = new NamedList<>();
    {
      final NamedList<SolrDocumentList> relatedDocuments = new NamedList<>();
      response.add(SolrConstants.MORE_LIKE_THIS, relatedDocuments);
      final SolrDocumentList documentList = new SolrDocumentList();
      documentList.setNumFound(2);
      documentList.setStart(1);
      final SolrDocument document1 = new SolrDocument();
      document1.setField(ID_FIELD, "doc1");
      final SolrDocument document2 = new SolrDocument();
      document2.setField(ID_FIELD, "doc2");
      documentList.add(document1);
      documentList.add(document2);
      relatedDocuments.add("docs", documentList);
    }
    final QueryResponse queryResponse = new QueryResponse(response, new CloudSolrServer("localhost"));
    final ResponseParser parser = new ResponseParser(_factory.createRecord(), getSolrConfig(), ID_FIELD);
    {
      final Record result = parser.toRecord(queryResponse);
      final AnyMap docs =
        result.getMetadata().getMap(SolrParams.SOLR_PARAMETER_ATTRIBUTE).getMap(ResponseAccessor.RESPONSE)
          .getMap(SolrConstants.MORE_LIKE_THIS).getMap("docs");
      assertNotNull(docs);
      assertEquals(2, docs.getLongValue(SolrConstants.NUM_FOUND).intValue());
      assertEquals(1, docs.getLongValue(SolrConstants.START).intValue());
      final AnySeq related = docs.getSeq(SolrConstants.RELATED);
      assertNotNull(related);
      assertEquals("doc1", related.getMap(0).getStringValue(ID_FIELD));
      assertEquals("doc2", related.getMap(1).getStringValue(ID_FIELD));
    }
  }

  public void test_parseCursorMark() {
    final NamedList<Object> response = new NamedList<>();
    final String cursorMarkNext = "thisIsTheNextCursorMark";
    {
      response.add(CursorMarkParams.CURSOR_MARK_NEXT, cursorMarkNext);
    }
    final QueryResponse queryResponse = new QueryResponse(response, new CloudSolrServer("localhost"));
    final ResponseParser parser = new ResponseParser(_factory.createRecord(), getSolrConfig(), ID_FIELD);
    {
      final Record result = parser.toRecord(queryResponse);
      final AnyMap responseMap =
        result.getMetadata().getMap(SolrParams.SOLR_PARAMETER_ATTRIBUTE).getMap(ResponseAccessor.RESPONSE);
      assertNotNull(responseMap);
      assertEquals(cursorMarkNext, responseMap.getStringValue(SolrConstants.NEXT_CURSOR_MARK));
    }
  }

  public void test_parseDebug() {
    final NamedList<Object> response = new NamedList<>();
    {
      final NamedList<Object> debug = new NamedList<>();
      response.add(SolrConstants.DEBUG, debug);
      debug.add("key1", "value1");
      debug.add("key2", "value2");
      final NamedList<String> explain = new NamedList<>();
      debug.add("explain", explain);
      explain.add("explain", "this");
    }
    final QueryResponse queryResponse = new QueryResponse(response, new CloudSolrServer("localhost"));
    final ResponseParser parser = new ResponseParser(_factory.createRecord(), getSolrConfig(), ID_FIELD);
    {
      final Record result = parser.toRecord(queryResponse);
      final AnyMap debug =
        result.getMetadata().getMap(SolrParams.SOLR_PARAMETER_ATTRIBUTE).getMap(ResponseAccessor.RESPONSE)
          .getMap(SolrConstants.DEBUG);
      assertNotNull(debug);
      assertEquals("value1", debug.getStringValue("key1"));
      assertEquals("value2", debug.getStringValue("key2"));
      final AnyMap explain = debug.getMap("explain");
      assertEquals("this", explain.getStringValue("explain"));
    }
  }

  public void test_parseStats() {
    final NamedList<Object> response = new NamedList<>();
    {
      final NamedList<Object> stats = new NamedList<>();
      response.add(SolrConstants.STATS, stats);
      final NamedList<NamedList<Object>> statsFields = new NamedList<>();
      stats.add("stats_fields", statsFields);
      final NamedList<Object> statsFieldsEntry = new NamedList<>();
      statsFields.add("statsFieldEntry", statsFieldsEntry);
      statsFieldsEntry.add(SolrConstants.MIN, -1);
      statsFieldsEntry.add(SolrConstants.MAX, 2);
      statsFieldsEntry.add(SolrConstants.COUNT, new Long(5));
      statsFieldsEntry.add(SolrConstants.MISSING, new Long(7));
      statsFieldsEntry.add(SolrConstants.SUM, 42);
      statsFieldsEntry.add(SolrConstants.MEAN, 9);
      statsFieldsEntry.add(SolrConstants.STDDEV, 2.4);
      final NamedList<Object> facets = new NamedList<>();
      statsFieldsEntry.add(SolrConstants.FACETS, facets);
      final NamedList<NamedList<Object>> field = new NamedList<>();
      facets.add("author", field);
      final NamedList<Object> author = new NamedList<>();
      field.add("values", author);
      author.add(SolrConstants.MIN, -1);
      author.add(SolrConstants.MAX, 2);
      author.add(SolrConstants.COUNT, new Long(5));
      author.add(SolrConstants.MISSING, new Long(7));
      author.add(SolrConstants.SUM, 42);
      author.add(SolrConstants.MEAN, 9);
      author.add(SolrConstants.STDDEV, 2.4);

    }
    final QueryResponse queryResponse = new QueryResponse(response, new CloudSolrServer("localhost"));
    final ResponseParser parser = new ResponseParser(_factory.createRecord(), getSolrConfig(), ID_FIELD);
    {
      final Record result = parser.toRecord(queryResponse);
      final AnyMap statsFieldEntry =
        result.getMetadata().getMap(SolrParams.SOLR_PARAMETER_ATTRIBUTE).getMap(ResponseAccessor.RESPONSE)
          .getMap(SolrConstants.STATS).getMap("statsFieldEntry");
      assertNotNull(statsFieldEntry);
      assertEquals(-1, statsFieldEntry.getLongValue(SolrConstants.MIN).intValue());
      assertEquals(2, statsFieldEntry.getLongValue(SolrConstants.MAX).intValue());
      assertEquals(5, statsFieldEntry.getLongValue(SolrConstants.COUNT).intValue());
      assertEquals(7, statsFieldEntry.getLongValue(SolrConstants.MISSING).intValue());
      assertEquals(42, statsFieldEntry.getLongValue(SolrConstants.SUM).intValue());
      assertEquals(9, statsFieldEntry.getLongValue(SolrConstants.MEAN).intValue());
      assertEquals(2.4, statsFieldEntry.getDoubleValue(SolrConstants.STDDEV).doubleValue());
      final AnyMap authorFacet = statsFieldEntry.getMap(SolrConstants.FACETS).getMap("author");
      assertEquals(-1, authorFacet.getLongValue(SolrConstants.MIN).intValue());
      assertEquals(2, authorFacet.getLongValue(SolrConstants.MAX).intValue());
      assertEquals(5, authorFacet.getLongValue(SolrConstants.COUNT).intValue());
      assertEquals(7, authorFacet.getLongValue(SolrConstants.MISSING).intValue());
      assertEquals(42, authorFacet.getLongValue(SolrConstants.SUM).intValue());
      assertEquals(9, authorFacet.getLongValue(SolrConstants.MEAN).intValue());
      assertEquals(2.4, authorFacet.getDoubleValue(SolrConstants.STDDEV).doubleValue());
    }
  }

  public void test_parseHighlighting() {
    final NamedList<Object> response = new NamedList<>();
    {
      final NamedList<Object> highlighting = new NamedList<>();
      response.add("highlighting", highlighting);
      final NamedList<List<String>> doc = new NamedList<>();
      highlighting.add("document1", doc);
      final List<String> values = new ArrayList<>();
      doc.add("values", values);
      values.add("highlight1");
      values.add("highlight2");

      final SolrDocumentList solrDocumentList = new SolrDocumentList();
      solrDocumentList.setNumFound(1);
      final SolrDocument document1 = new SolrDocument();
      document1.setField(ID_FIELD, "document1");
      solrDocumentList.add(document1);
      response.add(ResponseAccessor.RESPONSE, solrDocumentList);

    }
    final QueryResponse queryResponse = new QueryResponse(response, new CloudSolrServer("localhost"));
    final ResponseParser parser = new ResponseParser(_factory.createRecord(), getSolrConfig(), ID_FIELD);
    {
      final Record result = parser.toRecord(queryResponse);
      assertEquals(1, result.getMetadata().getLongValue(SearchResultConstants.COUNT).intValue());
      final AnyMap record = result.getMetadata().getSeq(SearchResultConstants.RECORDS).getMap(0);
      assertEquals("document1", record.getStringValue(ID_FIELD));
      final AnySeq text =
        record.getMap(SearchResultConstants.HIGHLIGHT).getMap("values")
          .getSeq(SearchResultConstants.HIGHLIGHT_TEXT);
      assertNotNull(text);
      assertEquals("highlight1", text.getStringValue(0));
      assertEquals("highlight2", text.getStringValue(1));
    }
  }

}
