/** {@inheritDoc} */
  @Override
  protected final synchronized void onClose() {
    final ITextOutput out;
    final String s;
    final char[] summary;

    out = this.getTextOutput();

    LaTeXDriver._endLine(out);

    s = ((LaTeXDocument) (this.getDocument())).m_class.getMakeTitle();
    if ((s != null) && (!(s.isEmpty()))) {
      out.append(s);
      LaTeXDriver._endLine(out);
    }

    LaTeXDriver._endLine(out);
    summary = this.m_summary;
    this.m_summary = null;
    if ((summary != null) && (summary.length > 0)) {
      out.append(summary);
    }

    super.onClose();
  }
  /** {@inheritDoc} */
  @Override
  protected final void doDate(final BibDate date) {
    super.doDate(date);
    final LaTeXDocumentClass clazz;
    final ITextOutput out;
    String s;

    if (date == null) {
      return;
    }

    out = this.getTextOutput();
    LaTeXDriver._endLine(out);

    clazz = ((LaTeXDocument) (this.getDocument())).m_class;

    s = clazz.getDateBegin();
    if ((s != null) && (!(s.isEmpty()))) {
      out.append(s);
    }
    date.toText(out);
    s = clazz.getDateEnd();
    if ((s != null) && (!(s.isEmpty()))) {
      out.append(s);
    }
    LaTeXDriver._endLine(out);
  }
 /** {@inheritDoc} */
 @Override
 protected void yAxisRenderYAxisSourceAsParameter(final ITextOutput out) {
   super.yAxisRenderYAxisSourceAsParameter(out);
   out.append(EMathComparison.fromEComparison(this.m_criterion).getOperatorChar());
   if (this.isGoalValueLong() || (this.m_goalValueLong == this.m_goalValueDouble)) {
     out.append(this.m_goalValueLong);
   } else {
     out.append(this.m_goalValueDouble);
   }
 }
  /** {@inheritDoc} */
  @Override
  protected final synchronized void onOpen() {
    final ITextOutput out;

    super.onOpen();

    out = this.getTextOutput();
    LaTeXDriver._endLine(out);
    out.append(_LaTeXDocumentHeader.DOCUMENT_BEGIN);
    LaTeXDriver._endLine(out);
  }
  /** {@inheritDoc} */
  @SuppressWarnings("resource")
  @Override
  protected final synchronized void onClose() {
    final ITextOutput out;
    final boolean emulated;
    final _LaTeXSection owner;

    out = this.getTextOutput();
    LaTeXDriver._endCommandLine(out);

    owner = ((_LaTeXSection) (this.getOwner()));
    emulated = owner.m_emulated;
    LaTeXDriver._label(owner.getLabel(), out, emulated);
    if (emulated) {
      out.append('~');
    }

    super.onClose();
  }
 /** {@inheritDoc} */
 @Override
 public final void toText(final ITextOutput textOut) {
   if (this.m_refText != null) {
     textOut.append(this.m_type.getName());
     textOut.appendNonBreakingSpace();
     textOut.append(this.m_refText);
   } else {
     textOut.append("[forward"); // $NON-NLS-1$
     textOut.appendNonBreakingSpace();
     textOut.append(this.m_type.getName());
     if (this.m_mark != null) {
       textOut.append('#');
       textOut.append(this.m_mark);
     }
     textOut.append(']');
   }
 }
  /** {@inheritDoc} */
  @Override
  protected final void render(final ITextOutput out, final char[][] data, final int size) {
    int i;

    out.append(_XHTML10InlineMath.MO_TAB);
    out.append(_XHTML10InlineMath.MO_TR);

    for (i = 0; i < size; i++) {
      if (i > 0) {
        out.append(_XHTML10InlineMath.MO_TD);
        out.append('-');
        out.append(_XHTML10Table.TD_END);
      }
      out.append(_XHTML10InlineMath.MO_TD);
      out.append(data[i]);
      out.append(_XHTML10Table.TD_END);
    }

    out.append(_XHTML10Table.TR_END);
    out.append(_XHTML10Table.TABLE_END);
  }
  /**
   * Print the name and title of the Nelder-Mead algorithm
   *
   * @param textCase the text case
   * @param textOut the text output destination
   * @param useShortName use the short name?
   * @return the next case
   */
  protected static final ETextCase printNelderMead(
      final ETextCase textCase, final ITextOutput textOut, final boolean useShortName) {
    ETextCase next;

    textOut.append(OptimizationBasedFitter.NAME_NELDER_MEAD);
    if (!useShortName) {
      textOut.append(' ');
      next = textCase.nextCase().appendWord(OptimizationBasedFitter.NAME_ALGORITHM, textOut);
    } else {
      next = textCase.nextCase();
    }

    if (textOut instanceof IComplexText) {
      try (final BibliographyBuilder builder =
          ((IComplexText) textOut).cite(ECitationMode.ID, next, ESequenceMode.COMMA)) {
        builder.add(OptimizationBasedFitter.REFERENCE_NELDER_MEAD);
      }
    }

    return next.nextCase();
  }
  /**
   * Print the name and title of the Levenberg-Marcquardt algorithm
   *
   * @param textCase the text case
   * @param textOut the text output destination
   * @param useShortName use the short name?
   * @return the next case
   */
  protected static final ETextCase printLevenbergMarcquardt(
      final ETextCase textCase, final ITextOutput textOut, final boolean useShortName) {
    ETextCase next;

    textOut.append(OptimizationBasedFitter.NAME_LEVENBERG_MARCQUARDT);
    next = textCase.nextCase();
    if (!useShortName) {
      textOut.append(' ');
      next = next.appendWord(OptimizationBasedFitter.NAME_ALGORITHM, textOut);
    }

    if (textOut instanceof IComplexText) {
      try (final BibliographyBuilder builder =
          ((IComplexText) textOut).cite(ECitationMode.ID, next, ESequenceMode.COMMA)) {
        builder.add(OptimizationBasedFitter.REFERENCE_LEVENBERG_MARCQUARDT_1);
        builder.add(OptimizationBasedFitter.REFERENCE_LEVENBERG_MARCQUARDT_2);
      }
    }

    return next.nextCase();
  }
  /**
   * Print the name and title of the CMAES algorithm
   *
   * @param textCase the text case
   * @param textOut the text output destination
   * @param useShortName use the short name?
   * @return the next case
   */
  protected static final ETextCase printCMAES(
      final ETextCase textCase, final ITextOutput textOut, final boolean useShortName) {
    textOut.append(
        useShortName
            ? OptimizationBasedFitter.NAME_CMAES_SHORT
            : OptimizationBasedFitter.NAME_CMAES_LONG);

    if (textOut instanceof IComplexText) {
      try (final BibliographyBuilder builder =
          ((IComplexText) textOut).cite(ECitationMode.ID, textCase, ESequenceMode.COMMA)) {
        builder.add(OptimizationBasedFitter.REFERENCE_CMAES);
      }
    }

    return textCase.nextCase();
  }
  /** {@inheritDoc} */
  @Override
  public ETextCase printDescription(final ITextOutput textOut, final ETextCase textCase) {
    final DimensionTransformation xIn, yIn;
    final Transformation yOut;
    ETextCase use;

    use = super.printDescription(textOut, textCase).nextCase();

    yIn = this.getYAxisInputTransformation();
    xIn = this.getXAxisTransformation();
    yOut = this.getYAxisOutputTransformation();

    textOut.append(" The "); // $NON-NLS-1$
    if (textOut instanceof IComplexText) {
      try (final IMath math = ((IComplexText) textOut).inlineMath()) {
        this.yAxisMathRender(math, DefaultParameterRenderer.INSTANCE);
      }
    } else {
      this.yAxisMathRender(textOut, DefaultParameterRenderer.INSTANCE);
    }
    textOut.append( //
        " represents the fraction of runs which reach a value of "); //$NON-NLS-1$
    yIn.printShortName(textOut, use);
    textOut.append(' ');
    textOut.append(this.m_criterion.toString());
    textOut.append(' ');
    if (this.m_useLongGoal) {
      textOut.append(this.m_goalValueLong);
    } else {
      textOut.append(this.m_goalValueDouble);
    }
    textOut.append(" for a given ellapsed runtime measured in "); // $NON-NLS-1$
    xIn.getDimension().printShortName(textOut, use);

    if (yOut.isIdentityTransformation()) {
      textOut.append(". The "); // $NON-NLS-1$
      this.printShortName(textOut, use);
    } else {
      textOut.append( //
          ". We do not use these fractions directly, but instead compute "); //$NON-NLS-1$
      if (textOut instanceof IComplexText) {
        try (final IMath math = ((IComplexText) textOut).inlineMath()) {
          this.yAxisMathRender(math, DefaultParameterRenderer.INSTANCE);
        }
      } else {
        this.yAxisMathRender(textOut, DefaultParameterRenderer.INSTANCE);
      }
      textOut.append(". The result of this formula"); // $NON-NLS-1$
    }

    textOut.append( //
        " is always computed over the runs of an experiment for a given benchmark instance. If runs for multiple instances are available, we aggregate the results by computing their "); //$NON-NLS-1$
    this.m_aggregate.printLongName(textOut, use);
    textOut.append('.');

    if (!(xIn.isIdentityTransformation())) {
      textOut.append(" The x-axis does not represent the values of "); // $NON-NLS-1$
      xIn.getDimension().printShortName(textOut, use);
      textOut.append(" directly, but instead "); // $NON-NLS-1$
      if (textOut instanceof IComplexText) {
        try (final IMath math = ((IComplexText) textOut).inlineMath()) {
          xIn.mathRender(math, DefaultParameterRenderer.INSTANCE);
        }
      } else {
        xIn.mathRender(textOut, DefaultParameterRenderer.INSTANCE);
      }
      textOut.append('.');
    }

    if (yOut.isIdentityTransformation()) {
      textOut.append(" The "); // $NON-NLS-1$
      this.printShortName(textOut, use);
      textOut.append(" is always between "); // $NON-NLS-1$
      textOut.append(0);
      textOut.append(" and "); // $NON-NLS-1$
      textOut.append(1);
      textOut.append(" \u2012 and the higher it is, the better."); // $NON-NLS-1$
    }
    return use;
  }
  /** {@inheritDoc} */
  @Override
  protected final void doAuthors(final BibAuthors authors) {
    final ITextOutput out, encoded;
    final LaTeXDocumentClass clazz;
    final int size;
    BibAuthor author;
    int i;
    String s;
    boolean needsSpace;

    super.doAuthors(authors);

    if ((authors == null) || ((size = authors.size()) <= 0)) {
      return;
    }

    out = this.getTextOutput();
    LaTeXDriver._endLine(out);

    clazz = ((LaTeXDocument) (this.getDocument())).m_class;

    s = clazz.getAuthorsBegin();
    if ((s != null) && (!(s.isEmpty()))) {
      out.append(s);
    }

    encoded = ((LaTeXDriver) (this.getDriver())).encode(out);
    for (i = 0; i < size; i++) {
      if (i > 0) {
        s = clazz.getAuthorSeparator();
        if ((s != null) && (!(s.isEmpty()))) {
          out.append(s);
        }
      }

      s = clazz.getAuthorBegin();
      if ((s != null) && (!(s.isEmpty()))) {
        out.append(s);
      }

      author = authors.get(i);

      needsSpace = false;
      s = author.getPersonalName();
      if ((s != null) && (!(s.isEmpty()))) {
        encoded.append(s);
        needsSpace = true;
      }
      s = author.getFamilyName();
      if ((s != null) && (!(s.isEmpty()))) {
        if (needsSpace) {
          encoded.append(' ');
        }
        encoded.append(s);
      }
      s = clazz.getAuthorEnd();
      if ((s != null) && (!(s.isEmpty()))) {
        out.append(s);
      }
    }

    s = clazz.getAuthorsEnd();
    if ((s != null) && (!(s.isEmpty()))) {
      out.append(s);
    }

    LaTeXDriver._endLine(out);
  }
  /** {@inheritDoc} */
  @Override
  protected final synchronized void onOpen() {
    final ITextOutput out;
    StreamEncoding<?, ?> e;
    String s;

    super.onOpen();

    this.getFileCollector().addFile(this.getDocumentPath(), XHTML.XHTML_1_0);

    out = this.getTextOutput();
    out.append(_XHTML10Document.XML_HEADER_BEGIN);

    e = StreamEncoding.getStreamEncoding(out);
    if ((e == null) || (e == StreamEncoding.TEXT) || (e == StreamEncoding.BINARY)) {
      e = StreamEncoding.getDefaultTextEncoding();
    }
    s = e.name();
    out.append(s);
    out.append(_XHTML10Document.XML_HEADER_END);
    out.appendLineBreak();

    out.append(_XHTML10Document.DOC_TYPE);
    out.appendLineBreak();

    out.append(_XHTML10Document.HTML_BEGIN);
    out.append(_XHTML10Document.HEAD_BEGIN);
    out.append(_XHTML10Document.META_CHARSET_BEGIN);
    out.append(s);
    out.append(XHTML10Driver.EMPTY_ATTRIB_TAG_END);

    out.append(_XHTML10Document.META_STYLE_TYPE);

    out.append(_XHTML10Document.DEFAULT_CSS_LINK);
    out.append(_XHTML10Document.CSS_DEFAULT);
    out.append(XHTML10Driver.EMPTY_ATTRIB_TAG_END);

    out.append(_XHTML10Document.PRINT_CSS_LINK);
    out.append(_XHTML10Document.CSS_PRINT);
    out.append(XHTML10Driver.EMPTY_ATTRIB_TAG_END);
  }