Example usage for org.apache.lucene.search.vectorhighlight SimpleFragListBuilder SimpleFragListBuilder

List of usage examples for org.apache.lucene.search.vectorhighlight SimpleFragListBuilder SimpleFragListBuilder

Introduction

In this page you can find the example usage for org.apache.lucene.search.vectorhighlight SimpleFragListBuilder SimpleFragListBuilder.

Prototype

public SimpleFragListBuilder() 

Source Link

Usage

From source file:aos.lucene.tools.FastVectorHighlighterSample.java

License:Apache License

static FastVectorHighlighter getHighlighter() {
    FragListBuilder fragListBuilder = new SimpleFragListBuilder(); // #F
    FragmentsBuilder fragmentBuilder = // #F
            new ScoreOrderFragmentsBuilder( // #F
                    BaseFragmentsBuilder.COLORED_PRE_TAGS, // #F
                    BaseFragmentsBuilder.COLORED_POST_TAGS); // #F
    return new FastVectorHighlighter(true, true, // #F
            fragListBuilder, fragmentBuilder); // #F
}

From source file:invertedindex.SearchIndex.java

public ArrayList<SearchResults> search(String keyword) throws IOException {

    String indexLocation = this.getIndexLocation();
    //    System.out.println("Inside search method");

    //        indexLocation = "";
    //        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    //        while (true) {
    try {/*from w w  w  .j  a v  a 2 s . com*/
        IndexReader reader = DirectoryReader.open(FSDirectory.open(new File(indexLocation)));
        IndexSearcher searcher = new IndexSearcher(reader);
        TopScoreDocCollector collector = TopScoreDocCollector.create(topDocs, true);

        String query = keyword;

        query = "\"" + query + "\"";

        Query q = new QueryParser(Version.LUCENE_47, "contents", analyzer).parse(query);

        SimpleFragListBuilder fragListBuilder = new SimpleFragListBuilder();
        ScoreOrderFragmentsBuilder fragBuilder = new ScoreOrderFragmentsBuilder();
        FastVectorHighlighter fvh = new FastVectorHighlighter(FastVectorHighlighter.DEFAULT_PHRASE_HIGHLIGHT,
                FastVectorHighlighter.DEFAULT_FIELD_MATCH, fragListBuilder, fragBuilder);
        fvh = new FastVectorHighlighter(FastVectorHighlighter.DEFAULT_PHRASE_HIGHLIGHT,
                FastVectorHighlighter.DEFAULT_FIELD_MATCH, fragListBuilder, fragBuilder);

        //      System.out.println(q);

        //                

        searcher.search(q, collector);
        //                searcher.search(q, null,topDocs);
        ScoreDoc[] hits = collector.topDocs().scoreDocs;

        // 4. display results
        System.out.println("Found " + hits.length + " hits.");
        totalHits = hits.length;
        searchResulsAL = new ArrayList<>();

        for (int i = 0; i < hits.length; ++i) {
            int docId = hits[i].doc;
            FieldQuery fq = fvh.getFieldQuery(q);
            //                    System.out.println("fq "+fq);

            String[] fragments = fvh.getBestFragments(fq, searcher.getIndexReader(), docId, "contents", 50, 10);
            //String[] lineFragments = fvh.getBestFragments(fq, searcher.getIndexReader(), docId, "contents", 18,10);

            Document d = searcher.doc(docId);

            String filePath = d.get("path");

            for (int j = 0; j < fragments.length; j++) {
                //                                    System.out.println("FRAGMENT iS "+fragments[j]);
                //                                int k=0;
                //                                for(k=0;k<lineFragments.length;k++){
                //                                    fragments[j].getSc
                String temp = Jsoup.parse(fragments[j]).text();
                //                                    
                LineNumberSearcher lns = new LineNumberSearcher();

                //lineNumbersList = new ArrayList<>();
                lineNumberArrayList = new ArrayList<>();
                lineNumber = "null";
                boolean g = Pattern.compile("\\n").matcher(fragments[j]).find();
                if (!g) {
                    //                                        System.out.println("NO G");
                    lineNumbersList = lns.search(temp, filePath);
                    //                                        for(String s : lineNumbersList){
                    //                                            System.out.println("s is "+s);
                    //                                        }
                    //                                        if(lineNumbersList.get(0).isEmpty()){
                    //                                            lineNumber = "Not Found";
                    //                                        }else {
                    if (!lineNumbersList.isEmpty()) {
                        //                                                System.out.println("in line number");
                        lineNumber = lineNumbersList.get(0);
                    }

                    //                                        }

                }

                //here is the tried code for enter space
                /*       
                else{
                  System.out.println("YES G");
                   String lines[] = fragments[j].split("\\r?\\n");
                //                                         ArrayList<String> newLines = new ArrayList<>();
                  ArrayList<String> newLines = new ArrayList<>(Arrays.asList(lines));
                  System.out.println("Here 3");
                  int special = 0;
                   for(String line : newLines){
                       if(Pattern.compile("^$").matcher(line).find()){
                           newLines.remove(line);
                           special++;
                       }
                   }
                   System.out.println("Here 4");
                //                                          List<String> list = Arrays.asList(lines);
                //                                          if(list.contains(temp)){
                //                                              
                //                                          }
                          
                //                                        for(String line: newLines){
                //                                            System.out.println("LINE IS "+line);
                //                                        }
                  if(newLines.size()==1){
                //                                            System.out.println("Yes G but NOT G");
                      lineNumbersList = lns.search(temp,filePath);
                      if(!lineNumberArrayList.isEmpty()){
                          lineNumber = lineNumbersList.get(0);
                      }
                      System.out.println("Here 1");
                  }else{
                      System.out.println("Here 2");
                          ArrayList<String> a0 = lns.search(Jsoup.parse(newLines.get(0)).text(),filePath);
                  ArrayList<String> a1 = lns.search(Jsoup.parse(newLines.get(1)).text(),filePath);
                  int k,l;
                  outerloop:
                  for(k=0;k<a0.size();k++){
                      for(l=0;l<a1.size();l++){
                          int secondline = Integer.parseInt(a1.get(l));
                //                                                System.out.println("second line is"+ secondline);
                          int firstline = Integer.parseInt(a0.get(k));
                //                                                System.out.println("first line is"+firstline);
                          int diff = secondline - firstline;
                //                                                System.out.println("DIFFERENCE IS "+diff);
                //                                                System.out.println("Special IS "+special);
                          if(diff == special+1){
                              insideLoopFlag = true;
                //                                                    System.out.println("K IS "+k);
                //                                                    System.out.println("IN BREAK ");
                              break outerloop;
                          }
                      }
                //                                            System.out.println("K IS "+k);
                  }
                //                                        System.out.println("OUT OF FOR LOOP");
                //                                        System.out.println("K IS "+k);
                  if(insideLoopFlag==true){
                  lineNumber = String.valueOf(a0.get(k));
                  }
                //                                        System.out.println("LINE NUMBER IS "+lineNumber);
                  }
                          
                          
                }
                */

                //                                }
                fragments[j] = fragments[j].replaceAll("\\n", " ");
                //                                System.out.println("\t\t" + fragments[j] + "...");
                fragments[j] = fragments[j] + "....";
                if (!(lineNumber.equals("null"))) {
                    //                                    System.out.println("in line number");
                    fragments[j] = fragments[j] + " at Line " + lineNumber;
                }

            }

            //Setting Results
            SearchResults sr = new SearchResults();
            sr.setFilename(d.get("filename"));
            sr.setScore(hits[i].score);
            sr.setFragments(fragments);
            sr.setPath(filePath);
            sr.setContentType(d.get("contentType"));
            //                    sr.setLineNumber(lineNumber);

            searchResulsAL.add(sr);

            //                    
        }
        //      writer.close();
        reader.close();

    } catch (Exception e) {
        System.out.println("Error searching in search index " + e + " : " + e.getMessage());
        //      break;
    }

    //    }

    return searchResulsAL;

}

From source file:invertedindex.SearchIndex.java

public ArrayList<SearchResults> multipleSearch(String keyword1, String keyword2, String radio)
        throws IOException {

    String indexLocation = this.getIndexLocation();

    try {/* www  .j ava2  s  .c  o m*/
        IndexReader reader = DirectoryReader.open(FSDirectory.open(new File(indexLocation)));
        IndexSearcher searcher = new IndexSearcher(reader);
        TopScoreDocCollector collector = TopScoreDocCollector.create(topDocs, true);

        String query1 = keyword1;
        String query2 = keyword2;
        query1 = "\"" + query1 + "\"";
        query2 = "\"" + query2 + "\"";

        Query q1 = new QueryParser(Version.LUCENE_47, "contents", analyzer).parse(query1);
        Query q2 = new QueryParser(Version.LUCENE_47, "contents", analyzer).parse(query2);

        BooleanQuery apiQuery = new BooleanQuery();
        if (radio.equalsIgnoreCase("and")) {
            apiQuery.add(q1, BooleanClause.Occur.MUST);
            apiQuery.add(q2, BooleanClause.Occur.MUST);
        } else if (radio.equalsIgnoreCase("or")) {
            apiQuery.add(q1, BooleanClause.Occur.SHOULD);
            apiQuery.add(q2, BooleanClause.Occur.SHOULD);
        } else if (radio.equalsIgnoreCase("not")) {
            apiQuery.add(q1, BooleanClause.Occur.MUST);
            apiQuery.add(q2, BooleanClause.Occur.MUST_NOT);
        }

        SimpleFragListBuilder fragListBuilder = new SimpleFragListBuilder();
        ScoreOrderFragmentsBuilder fragBuilder = new ScoreOrderFragmentsBuilder();
        FastVectorHighlighter fvh = new FastVectorHighlighter(FastVectorHighlighter.DEFAULT_PHRASE_HIGHLIGHT,
                FastVectorHighlighter.DEFAULT_FIELD_MATCH, fragListBuilder, fragBuilder);
        fvh = new FastVectorHighlighter(FastVectorHighlighter.DEFAULT_PHRASE_HIGHLIGHT,
                FastVectorHighlighter.DEFAULT_FIELD_MATCH, fragListBuilder, fragBuilder);

        searcher.search(apiQuery, collector);

        ScoreDoc[] hits = collector.topDocs().scoreDocs;

        System.out.println("Found " + hits.length + " hits.");
        totalHits = hits.length;
        searchResulsAL = new ArrayList<>();

        for (int i = 0; i < hits.length; ++i) {
            int docId = hits[i].doc;
            FieldQuery fq = fvh.getFieldQuery(apiQuery);
            //                    

            String[] fragments = fvh.getBestFragments(fq, searcher.getIndexReader(), docId, "contents", 50, 10);

            Document d = searcher.doc(docId);
            //                    
            String filePath = d.get("path");

            for (int j = 0; j < fragments.length; j++) {

                String temp = Jsoup.parse(fragments[j]).text();
                //                                 
                LineNumberSearcher lns = new LineNumberSearcher();

                //lineNumbersList = new ArrayList<>();
                lineNumber = "null";
                lineNumberArrayList = new ArrayList<>();
                boolean g = Pattern.compile("\\n").matcher(fragments[j]).find();
                if (!g) {
                    //                                        System.out.println("NO G g");
                    lineNumbersList = lns.search(temp, filePath);
                    //                                        for(String s : lineNumbersList){
                    //                                            System.out.println("s is "+s);
                    //                                        }
                    //                                      
                    if (!lineNumbersList.isEmpty()) {
                        //                                                System.out.println("in line number");
                        lineNumber = lineNumbersList.get(0);
                    }

                }

                fragments[j] = fragments[j].replaceAll("\\n", " ");
                //                                System.out.println("\t\t" + fragments[j] + "...");
                fragments[j] = fragments[j] + " ....";
                if (!(lineNumber.equals("null"))) {
                    //                                    System.out.println("in line number");
                    fragments[j] = fragments[j] + " at Line " + lineNumber;
                }

            }

            SearchResults sr = new SearchResults();
            sr.setFilename(d.get("filename"));
            sr.setScore(hits[i].score);
            sr.setFragments(fragments);
            sr.setPath(filePath);
            sr.setContentType(d.get("contentType"));

            searchResulsAL.add(sr);

        }

        reader.close();

    } catch (Exception e) {
        System.out.println("Error searching in search index " + e + " : " + e.getMessage());

    }

    return searchResulsAL;

}

From source file:org.apache.solr.highlight.DefaultSolrHighlighter.java

License:Apache License

@Override
public void init(PluginInfo info) {
    formatters.clear();/*from   www  .j  a va2  s .  co  m*/
    encoders.clear();
    fragmenters.clear();
    fragListBuilders.clear();
    fragmentsBuilders.clear();
    boundaryScanners.clear();

    // Load the fragmenters
    SolrFragmenter frag = solrCore.initPlugins(info.getChildren("fragmenter"), fragmenters,
            SolrFragmenter.class, null);
    if (frag == null)
        frag = new GapFragmenter();
    fragmenters.put("", frag);
    fragmenters.put(null, frag);

    // Load the formatters
    SolrFormatter fmt = solrCore.initPlugins(info.getChildren("formatter"), formatters, SolrFormatter.class,
            null);
    if (fmt == null)
        fmt = new HtmlFormatter();
    formatters.put("", fmt);
    formatters.put(null, fmt);

    // Load the encoders
    SolrEncoder enc = solrCore.initPlugins(info.getChildren("encoder"), encoders, SolrEncoder.class, null);
    if (enc == null)
        enc = new DefaultEncoder();
    encoders.put("", enc);
    encoders.put(null, enc);

    // Load the FragListBuilders
    SolrFragListBuilder fragListBuilder = solrCore.initPlugins(info.getChildren("fragListBuilder"),
            fragListBuilders, SolrFragListBuilder.class, null);
    if (fragListBuilder == null)
        fragListBuilder = new SimpleFragListBuilder();
    fragListBuilders.put("", fragListBuilder);
    fragListBuilders.put(null, fragListBuilder);

    // Load the FragmentsBuilders
    SolrFragmentsBuilder fragsBuilder = solrCore.initPlugins(info.getChildren("fragmentsBuilder"),
            fragmentsBuilders, SolrFragmentsBuilder.class, null);
    if (fragsBuilder == null)
        fragsBuilder = new ScoreOrderFragmentsBuilder();
    fragmentsBuilders.put("", fragsBuilder);
    fragmentsBuilders.put(null, fragsBuilder);

    // Load the BoundaryScanners
    SolrBoundaryScanner boundaryScanner = solrCore.initPlugins(info.getChildren("boundaryScanner"),
            boundaryScanners, SolrBoundaryScanner.class, null);
    if (boundaryScanner == null)
        boundaryScanner = new SimpleBoundaryScanner();
    boundaryScanners.put("", boundaryScanner);
    boundaryScanners.put(null, boundaryScanner);

    initialized = true;
}

From source file:org.apache.solr.highlight.DefaultSolrHighlighter.java

License:Apache License

@Override
@Deprecated/*www  .  j  a  v a  2 s  .  c  o m*/
public void initalize(SolrConfig config) {
    if (initialized)
        return;
    SolrFragmenter frag = new GapFragmenter();
    fragmenters.put("", frag);
    fragmenters.put(null, frag);

    SolrFormatter fmt = new HtmlFormatter();
    formatters.put("", fmt);
    formatters.put(null, fmt);

    SolrEncoder enc = new DefaultEncoder();
    encoders.put("", enc);
    encoders.put(null, enc);

    SolrFragListBuilder fragListBuilder = new SimpleFragListBuilder();
    fragListBuilders.put("", fragListBuilder);
    fragListBuilders.put(null, fragListBuilder);

    SolrFragmentsBuilder fragsBuilder = new ScoreOrderFragmentsBuilder();
    fragmentsBuilders.put("", fragsBuilder);
    fragmentsBuilders.put(null, fragsBuilder);

    SolrBoundaryScanner boundaryScanner = new SimpleBoundaryScanner();
    boundaryScanners.put("", boundaryScanner);
    boundaryScanners.put(null, boundaryScanner);
}

From source file:org.elasticsearch.search.fetch.subphase.highlight.FastVectorHighlighter.java

License:Apache License

@Override
public HighlightField highlight(HighlighterContext highlighterContext) {
    SearchContextHighlight.Field field = highlighterContext.field;
    SearchContext context = highlighterContext.context;
    FetchSubPhase.HitContext hitContext = highlighterContext.hitContext;
    FieldMapper mapper = highlighterContext.mapper;

    if (canHighlight(mapper) == false) {
        throw new IllegalArgumentException("the field [" + highlighterContext.fieldName
                + "] should be indexed with term vector with position offsets to be used with fast vector highlighter");
    }/*  ww w  .jav  a2  s .com*/

    Encoder encoder = field.fieldOptions().encoder().equals("html") ? HighlightUtils.Encoders.HTML
            : HighlightUtils.Encoders.DEFAULT;

    if (!hitContext.cache().containsKey(CACHE_KEY)) {
        hitContext.cache().put(CACHE_KEY, new HighlighterEntry());
    }
    HighlighterEntry cache = (HighlighterEntry) hitContext.cache().get(CACHE_KEY);

    try {
        FieldQuery fieldQuery;
        if (field.fieldOptions().requireFieldMatch()) {
            if (cache.fieldMatchFieldQuery == null) {
                /*
                 * we use top level reader to rewrite the query against all readers, with use caching it across hits (and across
                 * readers...)
                 */
                cache.fieldMatchFieldQuery = new CustomFieldQuery(highlighterContext.query,
                        hitContext.topLevelReader(), true, field.fieldOptions().requireFieldMatch());
            }
            fieldQuery = cache.fieldMatchFieldQuery;
        } else {
            if (cache.noFieldMatchFieldQuery == null) {
                /*
                 * we use top level reader to rewrite the query against all readers, with use caching it across hits (and across
                 * readers...)
                 */
                cache.noFieldMatchFieldQuery = new CustomFieldQuery(highlighterContext.query,
                        hitContext.topLevelReader(), true, field.fieldOptions().requireFieldMatch());
            }
            fieldQuery = cache.noFieldMatchFieldQuery;
        }

        MapperHighlightEntry entry = cache.mappers.get(mapper);
        if (entry == null) {
            FragListBuilder fragListBuilder;
            BaseFragmentsBuilder fragmentsBuilder;

            BoundaryScanner boundaryScanner = DEFAULT_BOUNDARY_SCANNER;
            if (field.fieldOptions().boundaryMaxScan() != SimpleBoundaryScanner.DEFAULT_MAX_SCAN
                    || field.fieldOptions().boundaryChars() != SimpleBoundaryScanner.DEFAULT_BOUNDARY_CHARS) {
                boundaryScanner = new SimpleBoundaryScanner(field.fieldOptions().boundaryMaxScan(),
                        field.fieldOptions().boundaryChars());
            }
            boolean forceSource = context.highlight().forceSource(field);
            if (field.fieldOptions().numberOfFragments() == 0) {
                fragListBuilder = new SingleFragListBuilder();

                if (!forceSource && mapper.fieldType().stored()) {
                    fragmentsBuilder = new SimpleFragmentsBuilder(mapper, field.fieldOptions().preTags(),
                            field.fieldOptions().postTags(), boundaryScanner);
                } else {
                    fragmentsBuilder = new SourceSimpleFragmentsBuilder(mapper, context,
                            field.fieldOptions().preTags(), field.fieldOptions().postTags(), boundaryScanner);
                }
            } else {
                fragListBuilder = field.fieldOptions().fragmentOffset() == -1 ? new SimpleFragListBuilder()
                        : new SimpleFragListBuilder(field.fieldOptions().fragmentOffset());
                if (field.fieldOptions().scoreOrdered()) {
                    if (!forceSource && mapper.fieldType().stored()) {
                        fragmentsBuilder = new ScoreOrderFragmentsBuilder(field.fieldOptions().preTags(),
                                field.fieldOptions().postTags(), boundaryScanner);
                    } else {
                        fragmentsBuilder = new SourceScoreOrderFragmentsBuilder(mapper, context,
                                field.fieldOptions().preTags(), field.fieldOptions().postTags(),
                                boundaryScanner);
                    }
                } else {
                    if (!forceSource && mapper.fieldType().stored()) {
                        fragmentsBuilder = new SimpleFragmentsBuilder(mapper, field.fieldOptions().preTags(),
                                field.fieldOptions().postTags(), boundaryScanner);
                    } else {
                        fragmentsBuilder = new SourceSimpleFragmentsBuilder(mapper, context,
                                field.fieldOptions().preTags(), field.fieldOptions().postTags(),
                                boundaryScanner);
                    }
                }
            }
            fragmentsBuilder.setDiscreteMultiValueHighlighting(termVectorMultiValue);
            entry = new MapperHighlightEntry();
            entry.fragListBuilder = fragListBuilder;
            entry.fragmentsBuilder = fragmentsBuilder;
            if (cache.fvh == null) {
                // parameters to FVH are not requires since:
                // first two booleans are not relevant since they are set on the CustomFieldQuery (phrase and fieldMatch)
                // fragment builders are used explicitly
                cache.fvh = new org.apache.lucene.search.vectorhighlight.FastVectorHighlighter();
            }
            CustomFieldQuery.highlightFilters.set(field.fieldOptions().highlightFilter());
            cache.mappers.put(mapper, entry);
        }
        cache.fvh.setPhraseLimit(field.fieldOptions().phraseLimit());

        String[] fragments;

        // a HACK to make highlighter do highlighting, even though its using the single frag list builder
        int numberOfFragments = field.fieldOptions().numberOfFragments() == 0 ? Integer.MAX_VALUE
                : field.fieldOptions().numberOfFragments();
        int fragmentCharSize = field.fieldOptions().numberOfFragments() == 0 ? Integer.MAX_VALUE
                : field.fieldOptions().fragmentCharSize();
        // we highlight against the low level reader and docId, because if we load source, we want to reuse it if possible
        // Only send matched fields if they were requested to save time.
        if (field.fieldOptions().matchedFields() != null && !field.fieldOptions().matchedFields().isEmpty()) {
            fragments = cache.fvh.getBestFragments(fieldQuery, hitContext.reader(), hitContext.docId(),
                    mapper.fieldType().name(), field.fieldOptions().matchedFields(), fragmentCharSize,
                    numberOfFragments, entry.fragListBuilder, entry.fragmentsBuilder,
                    field.fieldOptions().preTags(), field.fieldOptions().postTags(), encoder);
        } else {
            fragments = cache.fvh.getBestFragments(fieldQuery, hitContext.reader(), hitContext.docId(),
                    mapper.fieldType().name(), fragmentCharSize, numberOfFragments, entry.fragListBuilder,
                    entry.fragmentsBuilder, field.fieldOptions().preTags(), field.fieldOptions().postTags(),
                    encoder);
        }

        if (fragments != null && fragments.length > 0) {
            return new HighlightField(highlighterContext.fieldName, Text.convertFromStringArray(fragments));
        }

        int noMatchSize = highlighterContext.field.fieldOptions().noMatchSize();
        if (noMatchSize > 0) {
            // Essentially we just request that a fragment is built from 0 to noMatchSize using the normal fragmentsBuilder
            FieldFragList fieldFragList = new SimpleFieldFragList(-1 /*ignored*/);
            fieldFragList.add(0, noMatchSize, Collections.<WeightedPhraseInfo>emptyList());
            fragments = entry.fragmentsBuilder.createFragments(hitContext.reader(), hitContext.docId(),
                    mapper.fieldType().name(), fieldFragList, 1, field.fieldOptions().preTags(),
                    field.fieldOptions().postTags(), encoder);
            if (fragments != null && fragments.length > 0) {
                return new HighlightField(highlighterContext.fieldName, Text.convertFromStringArray(fragments));
            }
        }

        return null;

    } catch (Exception e) {
        throw new FetchPhaseExecutionException(context,
                "Failed to highlight field [" + highlighterContext.fieldName + "]", e);
    }
}

From source file:org.elasticsearch.search.highlight.FastVectorHighlighter.java

License:Apache License

@Override
public HighlightField highlight(HighlighterContext highlighterContext) {
    SearchContextHighlight.Field field = highlighterContext.field;
    SearchContext context = highlighterContext.context;
    FetchSubPhase.HitContext hitContext = highlighterContext.hitContext;
    FieldMapper<?> mapper = highlighterContext.mapper;

    if (!(mapper.fieldType().storeTermVectors() && mapper.fieldType().storeTermVectorOffsets()
            && mapper.fieldType().storeTermVectorPositions())) {
        throw new ElasticsearchIllegalArgumentException("the field [" + highlighterContext.fieldName
                + "] should be indexed with term vector with position offsets to be used with fast vector highlighter");
    }/*from w ww  .  j av a 2  s  .co  m*/

    Encoder encoder = field.fieldOptions().encoder().equals("html") ? HighlightUtils.Encoders.HTML
            : HighlightUtils.Encoders.DEFAULT;

    if (!hitContext.cache().containsKey(CACHE_KEY)) {
        hitContext.cache().put(CACHE_KEY, new HighlighterEntry());
    }
    HighlighterEntry cache = (HighlighterEntry) hitContext.cache().get(CACHE_KEY);

    try {
        FieldQuery fieldQuery;
        if (field.fieldOptions().requireFieldMatch()) {
            if (cache.fieldMatchFieldQuery == null) {
                // we use top level reader to rewrite the query against all readers, with use caching it across hits (and across readers...)
                cache.fieldMatchFieldQuery = new CustomFieldQuery(highlighterContext.query.originalQuery(),
                        hitContext.topLevelReader(), true, field.fieldOptions().requireFieldMatch());
            }
            fieldQuery = cache.fieldMatchFieldQuery;
        } else {
            if (cache.noFieldMatchFieldQuery == null) {
                // we use top level reader to rewrite the query against all readers, with use caching it across hits (and across readers...)
                cache.noFieldMatchFieldQuery = new CustomFieldQuery(highlighterContext.query.originalQuery(),
                        hitContext.topLevelReader(), true, field.fieldOptions().requireFieldMatch());
            }
            fieldQuery = cache.noFieldMatchFieldQuery;
        }

        MapperHighlightEntry entry = cache.mappers.get(mapper);
        if (entry == null) {
            FragListBuilder fragListBuilder;
            BaseFragmentsBuilder fragmentsBuilder;

            BoundaryScanner boundaryScanner = DEFAULT_BOUNDARY_SCANNER;
            if (field.fieldOptions().boundaryMaxScan() != SimpleBoundaryScanner.DEFAULT_MAX_SCAN
                    || field.fieldOptions().boundaryChars() != SimpleBoundaryScanner.DEFAULT_BOUNDARY_CHARS) {
                boundaryScanner = new SimpleBoundaryScanner(field.fieldOptions().boundaryMaxScan(),
                        field.fieldOptions().boundaryChars());
            }
            boolean forceSource = context.highlight().forceSource(field);
            if (field.fieldOptions().numberOfFragments() == 0) {
                fragListBuilder = new SingleFragListBuilder();

                if (!forceSource && mapper.fieldType().stored()) {
                    fragmentsBuilder = new SimpleFragmentsBuilder(mapper, field.fieldOptions().preTags(),
                            field.fieldOptions().postTags(), boundaryScanner);
                } else {
                    fragmentsBuilder = new SourceSimpleFragmentsBuilder(mapper, context,
                            field.fieldOptions().preTags(), field.fieldOptions().postTags(), boundaryScanner);
                }
            } else {
                fragListBuilder = field.fieldOptions().fragmentOffset() == -1 ? new SimpleFragListBuilder()
                        : new SimpleFragListBuilder(field.fieldOptions().fragmentOffset());
                if (field.fieldOptions().scoreOrdered()) {
                    if (!forceSource && mapper.fieldType().stored()) {
                        fragmentsBuilder = new ScoreOrderFragmentsBuilder(field.fieldOptions().preTags(),
                                field.fieldOptions().postTags(), boundaryScanner);
                    } else {
                        fragmentsBuilder = new SourceScoreOrderFragmentsBuilder(mapper, context,
                                field.fieldOptions().preTags(), field.fieldOptions().postTags(),
                                boundaryScanner);
                    }
                } else {
                    if (!forceSource && mapper.fieldType().stored()) {
                        fragmentsBuilder = new SimpleFragmentsBuilder(mapper, field.fieldOptions().preTags(),
                                field.fieldOptions().postTags(), boundaryScanner);
                    } else {
                        fragmentsBuilder = new SourceSimpleFragmentsBuilder(mapper, context,
                                field.fieldOptions().preTags(), field.fieldOptions().postTags(),
                                boundaryScanner);
                    }
                }
            }
            fragmentsBuilder.setDiscreteMultiValueHighlighting(termVectorMultiValue);
            entry = new MapperHighlightEntry();
            entry.fragListBuilder = fragListBuilder;
            entry.fragmentsBuilder = fragmentsBuilder;
            if (cache.fvh == null) {
                // parameters to FVH are not requires since:
                // first two booleans are not relevant since they are set on the CustomFieldQuery (phrase and fieldMatch)
                // fragment builders are used explicitly
                cache.fvh = new org.apache.lucene.search.vectorhighlight.FastVectorHighlighter();
            }
            CustomFieldQuery.highlightFilters.set(field.fieldOptions().highlightFilter());
            cache.mappers.put(mapper, entry);
        }
        cache.fvh.setPhraseLimit(field.fieldOptions().phraseLimit());

        String[] fragments;

        // a HACK to make highlighter do highlighting, even though its using the single frag list builder
        int numberOfFragments = field.fieldOptions().numberOfFragments() == 0 ? Integer.MAX_VALUE
                : field.fieldOptions().numberOfFragments();
        int fragmentCharSize = field.fieldOptions().numberOfFragments() == 0 ? Integer.MAX_VALUE
                : field.fieldOptions().fragmentCharSize();
        // we highlight against the low level reader and docId, because if we load source, we want to reuse it if possible
        // Only send matched fields if they were requested to save time.
        if (field.fieldOptions().matchedFields() != null && !field.fieldOptions().matchedFields().isEmpty()) {
            fragments = cache.fvh.getBestFragments(fieldQuery, hitContext.reader(), hitContext.docId(),
                    mapper.names().indexName(), field.fieldOptions().matchedFields(), fragmentCharSize,
                    numberOfFragments, entry.fragListBuilder, entry.fragmentsBuilder,
                    field.fieldOptions().preTags(), field.fieldOptions().postTags(), encoder);
        } else {
            fragments = cache.fvh.getBestFragments(fieldQuery, hitContext.reader(), hitContext.docId(),
                    mapper.names().indexName(), fragmentCharSize, numberOfFragments, entry.fragListBuilder,
                    entry.fragmentsBuilder, field.fieldOptions().preTags(), field.fieldOptions().postTags(),
                    encoder);
        }

        if (fragments != null && fragments.length > 0) {
            return new HighlightField(highlighterContext.fieldName,
                    StringText.convertFromStringArray(fragments));
        }

        int noMatchSize = highlighterContext.field.fieldOptions().noMatchSize();
        if (noMatchSize > 0) {
            // Essentially we just request that a fragment is built from 0 to noMatchSize using the normal fragmentsBuilder
            FieldFragList fieldFragList = new SimpleFieldFragList(-1 /*ignored*/);
            fieldFragList.add(0, noMatchSize, Collections.<WeightedPhraseInfo>emptyList());
            fragments = entry.fragmentsBuilder.createFragments(hitContext.reader(), hitContext.docId(),
                    mapper.names().indexName(), fieldFragList, 1, field.fieldOptions().preTags(),
                    field.fieldOptions().postTags(), encoder);
            if (fragments != null && fragments.length > 0) {
                return new HighlightField(highlighterContext.fieldName,
                        StringText.convertFromStringArray(fragments));
            }
        }

        return null;

    } catch (Exception e) {
        throw new FetchPhaseExecutionException(context,
                "Failed to highlight field [" + highlighterContext.fieldName + "]", e);
    }
}