/**
   * Retourne la liste des champs "snippet".
   *
   * @param node
   * @param source
   * @param target
   * @throws IllegalAccessException
   * @throws InstantiationException
   */
  public static void copySnippetFields(Node node, SchemaFieldList source, SnippetFieldList target)
      throws InstantiationException, IllegalAccessException {
    String fieldName = XPathParser.getAttributeString(node, "name");
    String tag = XPathParser.getAttributeString(node, "tag");
    if (tag == null) tag = "em";
    int maxSnippetNumber = XPathParser.getAttributeValue(node, "maxSnippetNumber");
    if (maxSnippetNumber == 0) maxSnippetNumber = 1;
    int maxSnippetSize = XPathParser.getAttributeValue(node, "maxSnippetSize");
    if (maxSnippetSize == 0) maxSnippetSize = 200;
    int timeLimit = DomUtils.getAttributeInteger(node, "timeLimit", 0);

    FragmenterAbstract fragmenter =
        FragmenterAbstract.newInstance(XPathParser.getAttributeString(node, "fragmenterClass"));
    fragmenter.setAttributes(node.getAttributes());
    String separator = XPathParser.getAttributeString(node, "separator");
    if (separator == null) separator = "...";
    SchemaField schemaField = source.get(fieldName);
    if (schemaField == null) return;
    SnippetField field =
        new SnippetField(
            schemaField.getName(),
            tag,
            separator,
            maxSnippetSize,
            maxSnippetNumber,
            fragmenter,
            timeLimit);
    target.put(field);
  }
 public void setFragmenter(String fragmenterName) throws SearchLibException {
   try {
     fragmenterTemplate = FragmenterAbstract.newInstance(fragmenterName);
   } catch (InstantiationException e) {
     throw new SearchLibException(e);
   } catch (IllegalAccessException e) {
     throw new SearchLibException(e);
   }
 }
 @Override
 public int compareTo(SnippetField f) {
   int c = super.compareTo(f);
   if (c != 0) return c;
   if ((c =
           fragmenterTemplate
               .getClass()
               .getName()
               .compareTo(f.fragmenterTemplate.getClass().getName()))
       != 0) return c;
   if ((c = tag.compareTo(f.tag)) != 0) return c;
   if ((c = separator.compareTo(f.separator)) != 0) return c;
   if ((c = maxSnippetSize - f.maxSnippetSize) != 0) return c;
   if ((c = maxSnippetNumber - f.maxSnippetNumber) != 0) return c;
   return 0;
 }
 @Override
 public void writeXmlConfig(XmlWriter xmlWriter) throws SAXException {
   xmlWriter.startElement(
       "field",
       "name",
       name,
       "tag",
       tag,
       "separator",
       separator,
       "maxSnippetSize",
       Integer.toString(maxSnippetSize),
       "maxSnippetNumber",
       Integer.toString(maxSnippetNumber),
       "fragmenterClass",
       fragmenterTemplate != null ? fragmenterTemplate.getClass().getSimpleName() : null,
       "timeLimit",
       Long.toString(timeLimit));
   xmlWriter.endElement();
 }
 public String getFragmenter() {
   return fragmenterTemplate.getClass().getSimpleName();
 }
  public boolean getSnippets(
      final int docId,
      final ReaderInterface reader,
      final List<FieldValueItem> values,
      final List<FieldValueItem> snippets,
      final Timer parentTimer)
      throws IOException, ParseException, SyntaxError, SearchLibException {

    if (values == null) return false;

    final Timer timer = new Timer(parentTimer, "SnippetField " + this.name);
    final long halfTimeExpiration =
        this.timeLimit == 0 ? 0 : timer.getStartOffset(this.timeLimit / 2);
    final long expiration = this.timeLimit == 0 ? 0 : timer.getStartOffset(this.timeLimit);

    FragmenterAbstract fragmenter = fragmenterTemplate.newInstance();
    SnippetVector currentVector = null;

    Timer t = new Timer(timer, "extractTermVectorIterator");

    Iterator<SnippetVector> vectorIterator =
        SnippetVectors.extractTermVectorIterator(
            docId, reader, snippetQueries, name, values, indexAnalyzer, t, halfTimeExpiration);
    if (vectorIterator != null)
      currentVector = vectorIterator.hasNext() ? vectorIterator.next() : null;

    t.end(null);

    t = new Timer(timer, "getFraments");

    int startOffset = 0;
    FragmentList fragments = new FragmentList();
    int vectorOffset = 0;
    for (FieldValueItem valueItem : values) {
      String value = valueItem.getValue();
      if (value != null) {
        // VectorOffset++ depends of EndOffset bug #patch Lucene 579 and
        // 1458
        fragmenter.getFragments(value, fragments, vectorOffset++);
      }
    }

    t.end(null);

    if (fragments.size() == 0) {
      timer.end(null);
      return false;
    }

    t = new Timer(timer, "checkValue");

    Fragment fragment = fragments.first();
    while (fragment != null) {
      currentVector = checkValue(currentVector, vectorIterator, startOffset, fragment);
      startOffset += fragment.getOriginalText().length();
      fragment = fragment.next();
    }

    t.end(null);

    Timer sbTimer = new Timer(timer, "snippetBuilder");

    boolean result = false;
    int snippetCounter = maxSnippetNumber;
    int scoredFragment = 0;
    while (snippetCounter-- != 0) {
      Fragment bestScoreFragment = null;
      fragment = Fragment.findNextHighlightedFragment(fragments.first());
      List<Fragment> scoreFragments = new ArrayList<Fragment>(0);
      double maxSearchScore = 0;

      t = new Timer(sbTimer, "fragmentScore");
      boolean expired = false;

      while (fragment != null) {
        double sc = fragment.searchScore(name, queryAnalyzer, query);
        if (sc > maxSearchScore) maxSearchScore = sc;
        scoreFragments.add(fragment);
        fragment = Fragment.findNextHighlightedFragment(fragment.next());
        scoredFragment++;
        if (expiration != 0) {
          if (System.currentTimeMillis() > expiration) {
            expired = true;
            break;
          }
        }
      }

      t.end("fragmentScore " + scoredFragment + " " + expired);

      for (Fragment frag : scoreFragments)
        bestScoreFragment =
            Fragment.bestScore(bestScoreFragment, frag, maxSearchScore, maxSnippetSize);

      if (bestScoreFragment != null) {
        SnippetBuilder snippetBuilder =
            new SnippetBuilder(maxSnippetSize, unescapedSeparator, tags, bestScoreFragment);
        if (snippetBuilder.length() > 0)
          snippets.add(new FieldValueItem(FieldValueOriginEnum.SNIPPET, snippetBuilder.toString()));
        fragments.remove(snippetBuilder.getFragments());
        result = true;
        continue;
      }

      if (fragments.first() == null) break;
      SnippetBuilder snippetBuilder =
          new SnippetBuilder(maxSnippetSize, unescapedSeparator, tags, fragments.first());
      if (snippetBuilder.length() > 0) {
        snippets.add(new FieldValueItem(FieldValueOriginEnum.SNIPPET, snippetBuilder.toString()));
        fragments.remove(snippetBuilder.getFragments());
      }
    }

    sbTimer.end(null);

    timer.end(null);

    return result;
  }