Clover coverage report - QedeqKernelSe Coverage Report
Coverage timestamp: So Mrz 11 2007 07:05:19 CET
file stats: LOC: 1.068   Methods: 37
NCLOC: 826   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
Qedeq2Latex.java 65% 81,6% 100% 77,6%
coverage coverage
 1    /* $Id: Qedeq2Latex.java,v 1.44 2007/03/11 01:19:34 m31 Exp $
 2    *
 3    * This file is part of the project "Hilbert II" - http://www.qedeq.org
 4    *
 5    * Copyright 2000-2007, Michael Meyling <mime@qedeq.org>.
 6    *
 7    * "Hilbert II" is free software; you can redistribute
 8    * it and/or modify it under the terms of the GNU General Public
 9    * License as published by the Free Software Foundation; either
 10    * version 2 of the License, or (at your option) any later version.
 11    *
 12    * This program is distributed in the hope that it will be useful,
 13    * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15    * GNU General Public License for more details.
 16    */
 17   
 18    package org.qedeq.kernel.latex;
 19   
 20    import java.io.IOException;
 21    import java.text.SimpleDateFormat;
 22    import java.util.Date;
 23    import java.util.HashMap;
 24    import java.util.Map;
 25   
 26    import org.qedeq.kernel.base.list.Element;
 27    import org.qedeq.kernel.base.list.ElementList;
 28    import org.qedeq.kernel.base.module.Author;
 29    import org.qedeq.kernel.base.module.AuthorList;
 30    import org.qedeq.kernel.base.module.Axiom;
 31    import org.qedeq.kernel.base.module.Chapter;
 32    import org.qedeq.kernel.base.module.FunctionDefinition;
 33    import org.qedeq.kernel.base.module.Header;
 34    import org.qedeq.kernel.base.module.Import;
 35    import org.qedeq.kernel.base.module.ImportList;
 36    import org.qedeq.kernel.base.module.Latex;
 37    import org.qedeq.kernel.base.module.LatexList;
 38    import org.qedeq.kernel.base.module.LinkList;
 39    import org.qedeq.kernel.base.module.LiteratureItem;
 40    import org.qedeq.kernel.base.module.LiteratureItemList;
 41    import org.qedeq.kernel.base.module.LocationList;
 42    import org.qedeq.kernel.base.module.Node;
 43    import org.qedeq.kernel.base.module.PredicateDefinition;
 44    import org.qedeq.kernel.base.module.Proof;
 45    import org.qedeq.kernel.base.module.Proposition;
 46    import org.qedeq.kernel.base.module.Qedeq;
 47    import org.qedeq.kernel.base.module.Rule;
 48    import org.qedeq.kernel.base.module.Section;
 49    import org.qedeq.kernel.base.module.SectionList;
 50    import org.qedeq.kernel.base.module.Specification;
 51    import org.qedeq.kernel.base.module.Subsection;
 52    import org.qedeq.kernel.base.module.UsedByList;
 53    import org.qedeq.kernel.base.module.VariableList;
 54    import org.qedeq.kernel.bo.module.ModuleDataException;
 55    import org.qedeq.kernel.bo.module.QedeqBo;
 56    import org.qedeq.kernel.bo.visitor.AbstractModuleVisitor;
 57    import org.qedeq.kernel.bo.visitor.QedeqNotNullTransverser;
 58    import org.qedeq.kernel.dto.module.PredicateDefinitionVo;
 59    import org.qedeq.kernel.log.Trace;
 60    import org.qedeq.kernel.utility.IoUtility;
 61    import org.qedeq.kernel.utility.ReplaceUtility;
 62    import org.qedeq.kernel.utility.TextOutput;
 63   
 64   
 65    /**
 66    * Transfer a QEDEQ module into a LaTeX file.
 67    * <p>
 68    * <b>TODO mime 20070131: This is just a quick written generator. No parsing or validation
 69    * of inline LaTeX text is done. No references to other QEDEQ modules are resolved. This class just
 70    * generates some LaTeX output to be able to get a visual impression of a QEDEQ module.</b>
 71    * <p>
 72    * This generator operates operates against the interface declaration of a QEDEQ module.
 73    * A business object is not yet required.
 74    *
 75    *
 76    * @version $Revision: 1.44 $
 77    * @author Michael Meyling
 78    */
 79    public final class Qedeq2Latex extends AbstractModuleVisitor {
 80   
 81    /** Transverse QEDEQ module with this transverser. */
 82    private final QedeqNotNullTransverser transverser;
 83   
 84    /** Output goes here. */
 85    private final TextOutput printer;
 86   
 87    /** QEDEQ BO object to work on. */
 88    private final QedeqBo qedeq;
 89   
 90    /** Filter text to get and produce text in this language. */
 91    private final String language;
 92   
 93    /** Filter for this detail level. TODO mime 20050205: not used yet. */
 94    private final String level;
 95   
 96    /** Maps identifiers to {@link PredicateDefinition}s. */
 97    private final Map predicateDefinitions = new HashMap();
 98   
 99    /** Maps identifiers to {@link FunctionDefinition}s. */
 100    private final Map functionDefinitions = new HashMap();
 101   
 102    /** Current chapter number, starting with 0. */
 103    private int chapterNumber;
 104   
 105    /** Current section number, starting with 0. */
 106    private int sectionNumber;
 107   
 108    /** Current node id. */
 109    private String id;
 110   
 111    /** Current node title. */
 112    private String title;
 113   
 114    /** Alphabet for tagging. */
 115    private static final String ALPHABET = "abcdefghijklmnopqrstuvwxyz";
 116   
 117    /**
 118    * Constructor.
 119    *
 120    * @param qedeq QEDEQ BO object.
 121    * @param globalContext Module location information.
 122    * @param printer Print herein.
 123    * @param language Filter text to get and produce text in this language only.
 124    * @param level Filter for this detail level. TODO mime 20050205: not supported yet.
 125    */
 126  10 private Qedeq2Latex(final QedeqBo qedeq, final String globalContext,
 127    final TextOutput printer, final String language, final String level) {
 128  10 this.qedeq = qedeq;
 129  10 this.transverser = new QedeqNotNullTransverser(globalContext, this);
 130  10 this.printer = printer;
 131  10 if (language == null) {
 132  0 this.language = "en";
 133    } else {
 134  10 this.language = language;
 135    }
 136  10 if (level == null) {
 137  0 this.level = "1";
 138    } else {
 139  10 this.level = level;
 140    }
 141  10 final PredicateDefinitionVo equal = new PredicateDefinitionVo();
 142    // LATER mime 20050224: quick hack to have the logical identity operator
 143  10 equal.setArgumentNumber("2");
 144  10 equal.setName("equal");
 145  10 equal.setLatexPattern("#1 \\ = \\ #2");
 146  10 predicateDefinitions.put("equal_2", equal);
 147    // TODO mime 20060822: quick hack to get the negation of the logical identity operator
 148  10 final PredicateDefinitionVo notEqual = new PredicateDefinitionVo();
 149  10 notEqual.setArgumentNumber("2");
 150  10 notEqual.setName("notEqual");
 151  10 notEqual.setLatexPattern("#1 \\ \\neq \\ #2");
 152  10 predicateDefinitions.put("notEqual_2", notEqual);
 153    }
 154   
 155    /**
 156    * Prints a XML representation of given QEDEQ module into a given output stream.
 157    *
 158    * @param globalContext Module location information.
 159    * @param qedeq Basic qedeq module object.
 160    * @param printer Print herein.
 161    * @param language Filter text to get and produce text in this language only.
 162    * @param level Filter for this detail level. TODO mime 20050205: not supported yet.
 163    * @throws ModuleDataException Major problem occurred.
 164    * @throws IOException
 165    */
 166  10 public static void print(final String globalContext, final QedeqBo qedeq,
 167    final TextOutput printer, final String language, final String level)
 168    throws ModuleDataException, IOException {
 169  10 final Qedeq2Latex converter = new Qedeq2Latex(qedeq, globalContext, printer,
 170    language, level);
 171  10 converter.printLatex();
 172    }
 173   
 174    /**
 175    * Prints a XML file into a given output stream.
 176    * Constructs a {@link org.qedeq.kernel.bo.module.QedeqBo} first.
 177    *
 178    * @throws IOException Writing failed.
 179    * @throws ModuleDataException Exception during transversion.
 180    */
 181  10 private final void printLatex() throws IOException, ModuleDataException {
 182  10 transverser.accept(qedeq);
 183  10 printer.flush();
 184  10 if (printer.checkError()) {
 185  0 throw printer.getError();
 186    }
 187    }
 188   
 189  10 public final void visitEnter(final Qedeq qedeq) {
 190  10 printer.println("% -*- TeX:" + language.toUpperCase() + " -*-");
 191  10 printer.println("%%% ====================================================================");
 192  10 printer.println("%%% @LaTeX-file " + printer.getName());
 193  10 printer.println("%%% Generated at " + getTimestamp());
 194  10 printer.println("%%% ====================================================================");
 195  10 printer.println();
 196  10 printer.println(
 197    "%%% Permission is granted to copy, distribute and/or modify this document");
 198  10 printer.println("%%% under the terms of the GNU Free Documentation License, Version 1.2");
 199  10 printer.println("%%% or any later version published by the Free Software Foundation;");
 200  10 printer.println(
 201    "%%% with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.");
 202  10 printer.println();
 203  10 printer.println("\\documentclass[a4paper,german,10pt,twoside]{book}");
 204  10 if ("de".equals(language)) {
 205  5 printer.println("\\usepackage[german]{babel}");
 206    } else {
 207  5 if (!"en".equals(language)) {
 208  0 printer.println("%%% TODO unknown language: " + language);
 209    }
 210  5 printer.println("\\usepackage[english]{babel}");
 211    }
 212  10 printer.println("\\usepackage{makeidx}");
 213  10 printer.println("\\usepackage{amsmath,amsthm,amssymb}");
 214  10 printer.println("\\usepackage{color}");
 215  10 printer.println("\\usepackage[bookmarks,bookmarksnumbered,bookmarksopen,");
 216  10 printer.println(" colorlinks,linkcolor=webgreen,pagebackref]{hyperref}");
 217  10 printer.println("\\definecolor{webgreen}{rgb}{0,.5,0}");
 218  10 printer.println("\\usepackage{graphicx}");
 219  10 printer.println("\\usepackage{xr}");
 220  10 printer.println("\\usepackage{epsfig,longtable}");
 221  10 printer.println("\\usepackage{tabularx}");
 222  10 printer.println();
 223  10 if ("de".equals(language)) {
 224  5 printer.println("\\newtheorem{thm}{Theorem}[chapter]");
 225  5 printer.println("\\newtheorem{cor}[thm]{Korollar}");
 226  5 printer.println("\\newtheorem{lem}[thm]{Lemma}");
 227  5 printer.println("\\newtheorem{prop}[thm]{Proposition}");
 228  5 printer.println("\\newtheorem{ax}{Axiom}");
 229  5 printer.println("\\newtheorem{rul}{Regel}");
 230  5 printer.println();
 231  5 printer.println("\\theoremstyle{definition}");
 232  5 printer.println("\\newtheorem{defn}[thm]{Definition}");
 233  5 printer.println("\\newtheorem{idefn}[thm]{Initiale Definition}");
 234  5 printer.println();
 235  5 printer.println("\\theoremstyle{remark}");
 236  5 printer.println("\\newtheorem{rem}[thm]{Bemerkung}");
 237  5 printer.println("\\newtheorem*{notation}{Notation}");
 238    } else {
 239  5 if (!"en".equals(language)) {
 240  0 printer.println("%%% TODO unknown language: " + language);
 241    }
 242  5 printer.println("\\newtheorem{thm}{Theorem}[chapter]");
 243  5 printer.println("\\newtheorem{cor}[thm]{Corollary}");
 244  5 printer.println("\\newtheorem{lem}[thm]{Lemma}");
 245  5 printer.println("\\newtheorem{prop}[thm]{Proposition}");
 246  5 printer.println("\\newtheorem{ax}{Axiom}");
 247  5 printer.println("\\newtheorem{rul}{Rule}");
 248  5 printer.println();
 249  5 printer.println("\\theoremstyle{definition}");
 250  5 printer.println("\\newtheorem{defn}[thm]{Definition}");
 251  5 printer.println("\\newtheorem{idefn}[thm]{Initial Definition}");
 252  5 printer.println();
 253  5 printer.println("\\theoremstyle{remark}");
 254  5 printer.println("\\newtheorem{rem}[thm]{Remark}");
 255  5 printer.println("\\newtheorem*{notation}{Notation}");
 256    }
 257  10 printer.println();
 258  10 printer.println("\\addtolength{\\textheight}{7\\baselineskip}");
 259  10 printer.println("\\addtolength{\\topmargin}{-5\\baselineskip}");
 260  10 printer.println();
 261  10 printer.println("\\setlength{\\parindent}{0pt}");
 262  10 printer.println();
 263  10 printer.println("\\frenchspacing \\sloppy");
 264  10 printer.println();
 265  10 printer.println("\\makeindex");
 266  10 printer.println();
 267  10 printer.println();
 268    }
 269   
 270  10 public final void visitLeave(final Qedeq qedeq) {
 271  10 printer.println("\\backmatter");
 272  10 printer.println();
 273  10 printer.println("\\addcontentsline{toc}{chapter}{\\indexname} \\printindex");
 274  10 printer.println();
 275  10 printer.println("\\end{document}");
 276  10 printer.println();
 277    }
 278   
 279  10 public void visitEnter(final Header header) {
 280  10 final LatexList title = header.getTitle();
 281  10 printer.print("\\title{");
 282  10 printer.print(getLatexListEntry(title));
 283  10 printer.println("}");
 284  10 printer.println("\\author{");
 285  10 final AuthorList authors = qedeq.getHeader().getAuthorList();
 286  10 for (int i = 0; i < authors.size(); i++) {
 287  10 if (i > 0) {
 288  0 printer.println(", ");
 289    }
 290  10 final Author author = authors.get(i);
 291  10 printer.print(author.getName().getLatex());
 292    // TODO mime 20070206 if (author.getEmail() != null)
 293    }
 294  10 printer.println();
 295  10 printer.println("}");
 296  10 printer.println();
 297  10 printer.println("\\begin{document}");
 298  10 printer.println();
 299  10 printer.println("\\maketitle");
 300  10 printer.println();
 301  10 printer.println("\\setlength{\\parskip}{5pt plus 2pt minus 1pt}");
 302  10 printer.println("\\mbox{}");
 303  10 printer.println("\\vfill");
 304  10 printer.println();
 305  10 final String url = getUrl(header.getSpecification());
 306  10 if (url != null && url.length() > 0) {
 307  10 printer.println("\\par");
 308  10 if ("de".equals(language)) {
 309  5 printer.println("Die Quelle f{\"ur} dieses Dokument ist hier zu finden:");
 310    } else {
 311  5 if (!"en".equals(language)) {
 312  0 printer.println("%%% TODO unknown language: " + language);
 313    }
 314  5 printer.println("The source for this document can be found here:");
 315    }
 316  10 printer.println("\\par");
 317  10 printer.println("\\url{" + getUrl(header.getSpecification()) + "}");
 318  10 printer.println();
 319    }
 320    {
 321  10 printer.println("\\par");
 322  10 if ("de".equals(language)) {
 323  5 printer.println("Die vorliegende Publikation ist urheberrechtlich gesch{\"u}tzt.");
 324    } else {
 325  5 if (!"en".equals(language)) {
 326  0 printer.println("%%% TODO unknown language: " + language);
 327    }
 328  5 printer.println("Copyright by the authors. All rights reserved.");
 329    }
 330    }
 331  10 final String email = header.getEmail();
 332  10 if (email != null && email.length() > 0) {
 333  10 final String emailUrl = "\\url{mailto:" + email + "}";
 334  10 printer.println("\\par");
 335  10 if ("de".equals(language)) {
 336  5 printer.println("Bei Fragen, Anregungen oder Bitte um Aufnahme in die Liste der"
 337    + " abh{\"a}ngigen Module schicken Sie bitte eine EMail an die Addresse "
 338    + emailUrl);
 339    } else {
 340  5 if (!"en".equals(language)) {
 341  0 printer.println("%%% TODO unknown language: " + language);
 342    }
 343  5 printer.println("If you have any questions, suggestions or want to add something"
 344    + " to the list of modules that use this one, please send an email to the"
 345    + " address " + emailUrl);
 346    }
 347  10 printer.println();
 348    }
 349  10 printer.println("\\setlength{\\parskip}{0pt}");
 350  10 printer.println("\\tableofcontents");
 351  10 printer.println();
 352  10 printer.println("\\setlength{\\parskip}{5pt plus 2pt minus 1pt}");
 353  10 printer.println();
 354    }
 355   
 356    /**
 357    * Get URL for QEDEQ XML module.
 358    *
 359    * @param specification Find URL for this location list.
 360    * @return URL or <code>null</code> if none (valid?) was found.
 361    */
 362  22 private String getUrl(final Specification specification) {
 363  22 final LocationList list = specification.getLocationList();
 364  22 if (list == null || list.size() <= 0
 365    || list.get(0).getLocation().length() <= "http://a.b".length()) {
 366  2 return "";
 367    }
 368  20 String location = list.get(0).getLocation();
 369  20 if (!location.endsWith("/")) {
 370  20 location += "/";
 371    }
 372  20 location += specification.getName();
 373  20 location += ".xml";
 374  20 return location;
 375    }
 376   
 377  54 public void visitEnter(final Chapter chapter) {
 378  54 printer.print("\\chapter");
 379  54 if (chapter.getNoNumber() != null && chapter.getNoNumber().booleanValue()) {
 380  16 printer.print("*");
 381    }
 382  54 printer.print("{");
 383  54 printer.print(getLatexListEntry(chapter.getTitle()));
 384  54 final String label = "chapter" + chapterNumber;
 385  54 printer.println("} \\label{" + label + "} \\hypertarget{" + label + "}{}");
 386  54 if (chapter.getNoNumber() != null && chapter.getNoNumber().booleanValue()) {
 387  16 printer.println("\\addcontentsline{toc}{chapter}{"
 388    + getLatexListEntry(chapter.getTitle()) + "}");
 389    }
 390  54 printer.println();
 391  54 if (chapter.getIntroduction() != null) {
 392  54 printer.println(getLatexListEntry(chapter.getIntroduction()));
 393  54 printer.println();
 394    }
 395    }
 396   
 397  54 public void visitLeave(final Chapter chapter) {
 398  54 printer.println("%% end of chapter " + getLatexListEntry(chapter.getTitle()));
 399  54 printer.println();
 400  54 chapterNumber++; // increase global chapter number
 401  54 sectionNumber = 0; // reset section number
 402    }
 403   
 404  32 public void visitLeave(final SectionList list) {
 405  32 printer.println();
 406    }
 407   
 408  94 public void visitEnter(final Section section) {
 409    /* TODO mime 20070131: use this information?
 410    if (section.getNoNumber() != null) {
 411    printer.print(" noNumber=\"" + section.getNoNumber().booleanValue() + "\"");
 412    }
 413    */
 414  94 printer.print("\\section{");
 415  94 printer.print(getLatexListEntry(section.getTitle()));
 416  94 final String label = "chapter" + chapterNumber + "_section" + sectionNumber;
 417  94 printer.println("} \\label{" + label + "} \\hypertarget{" + label + "}{}");
 418  94 printer.println(getLatexListEntry(section.getIntroduction()));
 419  94 printer.println();
 420    }
 421   
 422  94 public void visitLeave(final Section section) {
 423  94 sectionNumber++; // increase global section number
 424    }
 425   
 426  46 public void visitEnter(final Subsection subsection) {
 427    /* TODO mime 20070131: use this information?
 428    if (subsection.getId() != null) {
 429    printer.print(" id=\"" + subsection.getId() + "\"");
 430    }
 431    if (subsection.getLevel() != null) {
 432    printer.print(" level=\"" + subsection.getLevel() + "\"");
 433    }
 434    */
 435  46 if (subsection.getTitle() != null) {
 436  40 printer.print("\\subsection{");
 437  40 printer.println(getLatexListEntry(subsection.getTitle()));
 438  40 printer.println("}");
 439    }
 440  46 if (subsection.getId() != null) {
 441  0 printer.println("\\label{" + subsection.getId() + "} \\hypertarget{"
 442    + subsection.getId() + "}{}");
 443    }
 444  46 printer.println(getLatexListEntry(subsection.getLatex()));
 445    }
 446   
 447  46 public void visitLeave(final Subsection subsection) {
 448  46 printer.println();
 449  46 printer.println();
 450    }
 451   
 452  216 public void visitEnter(final Node node) {
 453    /** TODO mime 20070131: level filter
 454    if (node.getLevel() != null) {
 455    printer.print(" level=\"" + node.getLevel() + "\"");
 456    }
 457    */
 458  216 printer.println("\\par");
 459  216 printer.println(getLatexListEntry(node.getPrecedingText()));
 460  216 printer.println();
 461  216 id = node.getId();
 462  216 title = null;
 463  216 if (node.getTitle() != null) {
 464  108 title = getLatexListEntry(node.getTitle());
 465    }
 466    }
 467   
 468  216 public void visitLeave(final Node node) {
 469  216 printer.println();
 470  216 printer.println(getLatexListEntry(node.getSucceedingText()));
 471  216 printer.println();
 472  216 printer.println();
 473    }
 474   
 475  36 public void visitEnter(final Axiom axiom) {
 476  36 printer.println("\\begin{ax}" + (title != null ? "[" + title + "]" : ""));
 477  36 printer.println("\\label{" + id + "} \\hypertarget{" + id + "}{}");
 478  36 printFormula(axiom.getFormula().getElement());
 479  36 printer.println(getLatexListEntry(axiom.getDescription()));
 480  36 printer.println("\\end{ax}");
 481    }
 482   
 483  108 public void visitEnter(final Proposition proposition) {
 484  108 printer.println("\\begin{prop}" + (title != null ? "[" + title + "]" : ""));
 485  108 printer.println("\\label{" + id + "} \\hypertarget{" + id + "}{}");
 486  108 printTopFormula(proposition.getFormula().getElement(), id);
 487  108 printer.println(getLatexListEntry(proposition.getDescription()));
 488  108 printer.println("\\end{prop}");
 489    }
 490   
 491  10 public void visitEnter(final Proof proof) {
 492    /* TODO mime 20070131: filter level and kind
 493    if (proof.getKind() != null) {
 494    printer.print(" kind=\"" + proof.getKind() + "\"");
 495    }
 496    if (proof.getLevel() != null) {
 497    printer.print(" level=\"" + proof.getLevel() + "\"");
 498    }
 499    */
 500  10 printer.println("\\begin{proof}");
 501  10 printer.println(getLatexListEntry(proof.getNonFormalProof()));
 502  10 printer.println("\\end{proof}");
 503    }
 504   
 505  24 public void visitEnter(final PredicateDefinition definition) {
 506  24 final StringBuffer define = new StringBuffer("$$" + definition.getLatexPattern());
 507  24 final VariableList list = definition.getVariableList();
 508  24 if (list != null) {
 509  24 for (int i = list.size() - 1; i >= 0; i--) {
 510  38 Trace.trace(this, "printPredicateDefinition", "replacing!");
 511  38 ReplaceUtility.replace(define, "#" + (i + 1), getLatex(list.get(i)));
 512    }
 513    }
 514  24 if (definition.getFormula() != null) {
 515  20 printer.println("\\begin{defn}" + (title != null ? "[" + title + "]" : ""));
 516  20 printer.println("\\label{" + id + "} \\hypertarget{" + id + "}{}");
 517  20 define.append("\\ :\\leftrightarrow \\ ");
 518  20 define.append(getLatex(definition.getFormula().getElement()));
 519    } else {
 520  4 printer.println("\\begin{idefn}" + (title != null ? "[" + title + "]" : ""));
 521  4 printer.println("\\label{" + id + "} \\hypertarget{" + id + "}{}");
 522    }
 523  24 define.append("$$");
 524  24 predicateDefinitions.put(definition.getName() + "_" + definition.getArgumentNumber(),
 525    definition);
 526  24 Trace.param(this, "printPredicateDefinition", "define", define);
 527  24 printer.println(define);
 528  24 printer.println(getLatexListEntry(definition.getDescription()));
 529  24 if (definition.getFormula() != null) {
 530  20 printer.println("\\end{defn}");
 531    } else {
 532  4 printer.println("\\end{idefn}");
 533    }
 534    }
 535   
 536  32 public void visitEnter(final FunctionDefinition definition) {
 537  32 final StringBuffer define = new StringBuffer("$$" + definition.getLatexPattern());
 538  32 final VariableList list = definition.getVariableList();
 539  32 if (list != null) {
 540  26 for (int i = list.size() - 1; i >= 0; i--) {
 541  36 Trace.trace(this, "printFunctionDefinition", "replacing!");
 542  36 ReplaceUtility.replace(define, "#" + (i + 1), getLatex(list.get(i)));
 543    }
 544    }
 545  32 if (definition.getTerm() != null) {
 546  32 printer.println("\\begin{defn}" + (title != null ? "[" + title + "]" : ""));
 547  32 printer.println("\\label{" + id + "} \\hypertarget{" + id + "}{}");
 548  32 define.append("\\ := \\ ");
 549  32 define.append(getLatex(definition.getTerm().getElement()));
 550    } else {
 551  0 printer.println("\\begin{idefn}" + (title != null ? "[" + title + "]" : ""));
 552  0 printer.println("\\label{" + id + "} \\hypertarget{" + id + "}{}");
 553    }
 554  32 define.append("$$");
 555  32 functionDefinitions.put(definition.getName() + "_" + definition.getArgumentNumber(),
 556    definition);
 557  32 Trace.param(this, "printFunctionDefinition", "define", define);
 558  32 printer.println(define);
 559  32 printer.println(getLatexListEntry(definition.getDescription()));
 560  32 if (definition.getTerm() != null) {
 561  32 printer.println("\\end{defn}");
 562    } else {
 563  0 printer.println("\\end{idefn}");
 564    }
 565    }
 566   
 567  32 public void visitLeave(final FunctionDefinition definition) {
 568    }
 569   
 570  16 public void visitEnter(final Rule rule) {
 571  16 printer.println("\\begin{rul}" + (title != null ? "[" + title + "]" : ""));
 572  16 printer.println("\\label{" + id + "} \\hypertarget{" + id + "}{}");
 573  16 printer.println(getLatexListEntry(rule.getDescription()));
 574  16 printer.println("\\end{rul}");
 575   
 576    // TODO mime 20051210: are these informations equivalent to a formal proof?
 577    /*
 578    if (null != rule.getLinkList()) {
 579    printer.println("\\begin{proof}");
 580    printer.println("Rule name: " + rule.getName());
 581    printer.println();
 582    printer.println();
 583    for (int i = 0; i < rule.getLinkList().size(); i++) {
 584    printer.println(rule.getLinkList().get(i));
 585    }
 586    printer.println("\\end{proof}");
 587    }
 588    */
 589  16 if (rule.getProofList() != null) {
 590  0 for (int i = 0; i < rule.getProofList().size(); i++) {
 591  0 printer.println("\\begin{proof}");
 592  0 printer.println(getLatexListEntry(rule.getProofList().get(i)
 593    .getNonFormalProof()));
 594  0 printer.println("\\end{proof}");
 595    }
 596    }
 597    }
 598   
 599  16 public void visitLeave(final Rule rule) {
 600    }
 601   
 602  2 public void visitEnter(final LinkList linkList) {
 603  2 if (linkList.size() <= 0) {
 604  0 return;
 605    }
 606  2 if ("de".equals(language)) {
 607  1 printer.println("Basierend auf: ");
 608    } else {
 609  1 if (!"en".equals(language)) {
 610  0 printer.println("%%% TODO unknown language: " + language);
 611    }
 612  1 printer.println("Based on: ");
 613    }
 614  2 for (int i = 0; i < linkList.size(); i++) {
 615  2 if (linkList.get(i) != null) {
 616  2 printer.print(" \\ref{" + linkList.get(i) + "}");
 617    }
 618    };
 619  2 printer.println();
 620    }
 621   
 622  4 public void visitEnter(final LiteratureItemList list) {
 623  4 printer.println("\\begin{thebibliography}{99}");
 624    // TODO mime 20060926: remove language dependency
 625  4 if ("de".equals(language)) {
 626  2 printer.println("\\addcontentsline{toc}{chapter}{Literaturverzeichnis}");
 627    } else {
 628  2 if (!"en".equals(language)) {
 629  0 printer.println("%%% TODO unknown language: " + language);
 630    }
 631  2 printer.println("\\addcontentsline{toc}{chapter}{Bibliography}");
 632    }
 633  4 final ImportList imports = qedeq.getHeader().getImportList();
 634  4 if (imports != null && imports.size() > 0) {
 635  2 printer.println();
 636  2 printer.println();
 637  2 printer.println("%% Used other QEDEQ modules:");
 638  2 for (int i = 0; i < imports.size(); i++) {
 639  2 final Import imp = imports.get(i);
 640  2 printer.print("\\bibitem{" + imp.getLabel() + "} ");
 641  2 final Specification spec = imp.getSpecification();
 642  2 printer.print(getLatex(spec.getName()));
 643  2 if (spec.getLocationList() != null && spec.getLocationList().size() > 0
 644    && spec.getLocationList().get(0).getLocation().length() > 0) {
 645  2 printer.print(" ");
 646    // TODO mime 20070205: later on here must stand the location that was used
 647    // to verify the document contents
 648    // TODO mime 20070205: convert relative address into absolute
 649  2 printer.print("\\url{" + spec.getLocationList().get(0).getLocation() + "}");
 650    }
 651  2 printer.println();
 652    }
 653  2 printer.println();
 654  2 printer.println();
 655  2 printer.println("%% Other references:");
 656  2 printer.println();
 657    }
 658    }
 659   
 660  4 public void visitLeave(final LiteratureItemList list) {
 661  4 final UsedByList usedby = qedeq.getHeader().getUsedByList();
 662  4 if (usedby != null && usedby.size() > 0) {
 663  2 printer.println();
 664  2 printer.println();
 665  2 printer.println("%% QEDEQ modules that use this one:");
 666  2 for (int i = 0; i < usedby.size(); i++) {
 667  2 final Specification spec = usedby.get(i);
 668  2 printer.print("\\bibitem{" + spec.getName() + "} ");
 669  2 printer.print(getLatex(spec.getName()));
 670  2 final String url = getUrl(spec);
 671  2 if (url != null && url.length() > 0) {
 672  0 printer.print(" ");
 673  0 printer.print("\\url{" + url + "}");
 674    }
 675  2 printer.println();
 676    }
 677  2 printer.println();
 678  2 printer.println();
 679    }
 680  4 printer.println("\\end{thebibliography}");
 681    }
 682   
 683  20 public void visitEnter(final LiteratureItem item) {
 684  20 printer.print("\\bibitem{" + item.getLabel() + "} ");
 685  20 printer.println(getLatexListEntry(item.getItem()));
 686  20 printer.println();
 687    }
 688   
 689    /**
 690    * Print top level formula. If the formula has the form <code>AND(.., .., ..)</code> the
 691    * formula is broken down in several labeled lines.
 692    *
 693    * @param element Formula to print.
 694    * @param mainLabel Main formula label.
 695    */
 696  108 private void printTopFormula(final Element element, final String mainLabel) {
 697  108 if (!element.isList() || !element.getList().getOperator().equals("AND")) {
 698  76 printFormula(element);
 699  76 return;
 700    }
 701  32 final ElementList list = element.getList();
 702  32 printer.println("\\mbox{}");
 703  32 printer.println("\\begin{longtable}{{@{\\extracolsep{\\fill}}p{0.9\\linewidth}l}}");
 704  32 for (int i = 0; i < list.size(); i++) {
 705  158 final String label = (i < ALPHABET.length() ? "" + ALPHABET .charAt(i) : "" + i);
 706  158 printer.println("\\centering $" + getLatex(list.getElement(i)) + "$"
 707    + " & \\label{" + mainLabel + ":" + label + "} \\hypertarget{" + mainLabel + ":"
 708    + label + "}{} \\mbox{\\emph{(" + label + ")}} "
 709  158 + (i + 1 < list.size() ? "\\\\" : ""));
 710    }
 711  32 printer.println("\\end{longtable}");
 712    }
 713   
 714    /**
 715    * Print formula.
 716    *
 717    * @param element Formula to print.
 718    */
 719  112 private void printFormula(final Element element) {
 720  112 printer.println("\\mbox{}");
 721  112 printer.println("\\begin{longtable}{{@{\\extracolsep{\\fill}}p{\\linewidth}}}");
 722  112 printer.println("\\centering $" + getLatex(element) + "$");
 723  112 printer.println("\\end{longtable}");
 724    }
 725   
 726    /**
 727    * Get LaTeX element presentation.
 728    *
 729    * @param element Print this element.
 730    * @return LaTeX form of element.
 731    */
 732  396 private String getLatex(final Element element) {
 733  396 return getLatex(element, true);
 734    }
 735   
 736    /**
 737    * Get LaTeX element presentation.
 738    *
 739    * @param element Print this element.
 740    * @param first First level?
 741    * @return LaTeX form of element.
 742    */
 743  3064 private String getLatex(final Element element, final boolean first) {
 744  3064 final StringBuffer buffer = new StringBuffer();
 745  3064 if (element.isAtom()) {
 746  0 return element.getAtom().getString();
 747    }
 748  3064 final ElementList list = element.getList();
 749  3064 if (list.getOperator().equals("PREDCON")) {
 750  606 final String identifier = list.getElement(0).getAtom().getString() + "_"
 751    + (list.size() - 1);
 752    // TODO mime 20060922: is only working for definition name + argument number
 753    // if argument length is dynamic this dosen't work
 754  606 if (predicateDefinitions.containsKey(identifier)) {
 755  606 final PredicateDefinition definition = (PredicateDefinition)
 756    predicateDefinitions.get(identifier);
 757  606 final StringBuffer define = new StringBuffer(definition.getLatexPattern());
 758  606 for (int i = list.size() - 1; i >= 1; i--) {
 759  1038 ReplaceUtility.replace(define, "#" + i, getLatex(list.getElement(i), false));
 760    }
 761  606 buffer.append(define);
 762    } else {
 763  0 buffer.append(identifier);
 764  0 buffer.append("(");
 765  0 for (int i = 1; i < list.size(); i++) {
 766  0 buffer.append(getLatex(list.getElement(i), false));
 767  0 if (i + 1 < list.size()) {
 768  0 buffer.append(", ");
 769    }
 770    }
 771  0 buffer.append(")");
 772    }
 773  2458 } else if (list.getOperator().equals("PREDVAR")) {
 774  98 final String identifier = list.getElement(0).getAtom().getString();
 775  98 buffer.append(identifier);
 776  98 if (list.size() > 1) {
 777  50 buffer.append("(");
 778  50 for (int i = 1; i < list.size(); i++) {
 779  50 buffer.append(getLatex(list.getElement(i), false));
 780  50 if (i + 1 < list.size()) {
 781  0 buffer.append(", ");
 782    }
 783    }
 784  50 buffer.append(")");
 785    }
 786  2360 } else if (list.getOperator().equals("FUNCON")) {
 787  480 final String identifier = list.getElement(0).getAtom().getString() + "_"
 788    + (list.size() - 1);
 789    // TODO mime 20060922: is only working for definition name + argument number
 790    // if argument length is dynamic this dosen't work
 791  480 if (functionDefinitions.containsKey(identifier)) {
 792  480 final FunctionDefinition definition = (FunctionDefinition)
 793    functionDefinitions.get(identifier);
 794  480 final StringBuffer define = new StringBuffer(definition.getLatexPattern());
 795  480 for (int i = list.size() - 1; i >= 1; i--) {
 796  566 ReplaceUtility.replace(define, "#" + i, getLatex(list.getElement(i), false));
 797    }
 798  480 buffer.append(define);
 799    } else {
 800  0 buffer.append(identifier);
 801  0 buffer.append("(");
 802  0 for (int i = 1; i < list.size(); i++) {
 803  0 buffer.append(getLatex(list.getElement(i), false));
 804  0 if (i + 1 < list.size()) {
 805  0 buffer.append(", ");
 806    }
 807    }
 808  0 buffer.append(")");
 809    }
 810  1880 } else if (list.getOperator().equals("FUNVAR")) {
 811  0 final String identifier = list.getElement(0).getAtom().getString();
 812  0 buffer.append(identifier);
 813  0 if (list.size() > 1) {
 814  0 buffer.append("(");
 815  0 for (int i = 1; i < list.size(); i++) {
 816  0 buffer.append(getLatex(list.getElement(i), false));
 817  0 if (i + 1 < list.size()) {
 818  0 buffer.append(", ");
 819    }
 820    }
 821  0 buffer.append(")");
 822    }
 823  1880 } else if (list.getOperator().equals("VAR")) {
 824  1364 final String text = list.getElement(0).getAtom().getString();
 825    // interpret variable identifier as number
 826  1364 try {
 827  1364 final int index = Integer.parseInt(text);
 828  0 final String newText = "" + index;
 829  0 if (!text.equals(newText) || newText.startsWith("-")) {
 830  0 throw new NumberFormatException("This is no allowed number: " + text);
 831    }
 832  0 switch (index) {
 833  0 case 1:
 834  0 return "x";
 835  0 case 2:
 836  0 return "y";
 837  0 case 3:
 838  0 return "z";
 839  0 case 4:
 840  0 return "u";
 841  0 case 5:
 842  0 return "v";
 843  0 case 6:
 844  0 return "w";
 845  0 default:
 846  0 return "x_" + (index - 6);
 847    }
 848    } catch (NumberFormatException e) {
 849    // variable identifier is no number, just take it as it is
 850  1364 return text;
 851    }
 852  516 } else if (list.getOperator().equals("AND") || list.getOperator().equals("OR")
 853    || list.getOperator().equals("EQUI") || list.getOperator().equals("IMPL")) {
 854  334 final String infix;
 855  334 if (list.getOperator().equals("AND")) {
 856  80 infix = "\\ \\land \\ ";
 857  254 } else if (list.getOperator().equals("OR")) {
 858  30 infix = "\\ \\lor \\ ";
 859  224 } else if (list.getOperator().equals("EQUI")) {
 860  84 infix = "\\ \\leftrightarrow \\ ";
 861    } else {
 862  140 infix = "\\ \\rightarrow \\ ";
 863    }
 864  334 if (!first) {
 865  170 buffer.append("(");
 866    }
 867  334 for (int i = 0; i < list.size(); i++) {
 868  680 buffer.append(getLatex(list.getElement(i), false));
 869  680 if (i + 1 < list.size()) {
 870  346 buffer.append(infix);
 871    }
 872    }
 873  334 if (!first) {
 874  170 buffer.append(")");
 875    }
 876  182 } else if (list.getOperator().equals("FORALL") || list.getOperator().equals("EXISTS")
 877    || list.getOperator().equals("EXISTSU")) {
 878  88 final String prefix;
 879  88 if (list.getOperator().equals("FORALL")) {
 880  52 prefix = "\\forall ";
 881  36 } else if (list.getOperator().equals("EXISTS")) {
 882  30 prefix = "\\exists ";
 883    } else {
 884  6 prefix = "\\exists! ";
 885    }
 886  88 buffer.append(prefix);
 887  88 for (int i = 0; i < list.size(); i++) {
 888  180 if (i != 0 || (i == 0 && list.size() <= 2)) {
 889  176 buffer.append(getLatex(list.getElement(i), false));
 890    }
 891  180 if (i + 1 < list.size()) {
 892  92 buffer.append("\\ ");
 893    }
 894  180 if (list.size() > 2 && i == 1) {
 895  4 buffer.append("\\ ");
 896    }
 897    }
 898  94 } else if (list.getOperator().equals("NOT")) {
 899  30 final String prefix = "\\neg ";
 900  30 buffer.append(prefix);
 901  30 for (int i = 0; i < list.size(); i++) {
 902  30 buffer.append(getLatex(list.getElement(i), false));
 903    }
 904  64 } else if (list.getOperator().equals("CLASS")) {
 905  64 final String prefix = "\\{ ";
 906  64 buffer.append(prefix);
 907  64 for (int i = 0; i < list.size(); i++) {
 908  128 buffer.append(getLatex(list.getElement(i), false));
 909  128 if (i + 1 < list.size()) {
 910  64 buffer.append(" \\ | \\ ");
 911    }
 912    }
 913  64 buffer.append(" \\} ");
 914  0 } else if (list.getOperator().equals("CLASSLIST")) {
 915  0 final String prefix = "\\{ ";
 916  0 buffer.append(prefix);
 917  0 for (int i = 0; i < list.size(); i++) {
 918  0 buffer.append(getLatex(list.getElement(i), false));
 919  0 if (i + 1 < list.size()) {
 920  0 buffer.append(", \\ ");
 921    }
 922    }
 923  0 buffer.append(" \\} ");
 924  0 } else if (list.getOperator().equals("QUANTOR_INTERSECTION")) {
 925  0 final String prefix = "\\bigcap";
 926  0 buffer.append(prefix);
 927  0 if (0 < list.size()) {
 928  0 buffer.append("{").append(getLatex(list.getElement(0), false)).append("}");
 929    }
 930  0 for (int i = 1; i < list.size(); i++) {
 931  0 buffer.append(getLatex(list.getElement(i), false));
 932  0 if (i + 1 < list.size()) {
 933  0 buffer.append(" \\ \\ ");
 934    }
 935    }
 936  0 buffer.append(" \\} ");
 937  0 } else if (list.getOperator().equals("QUANTOR_UNION")) {
 938  0 final String prefix = "\\bigcup";
 939  0 buffer.append(prefix);
 940  0 if (0 < list.size()) {
 941  0 buffer.append("{").append(getLatex(list.getElement(0), false)).append("}");
 942    }
 943  0 for (int i = 1; i < list.size(); i++) {
 944  0 buffer.append(getLatex(list.getElement(i), false));
 945  0 if (i + 1 < list.size()) {
 946  0 buffer.append(" \\ \\ ");
 947    }
 948    }
 949  0 buffer.append(" \\} ");
 950    } else {
 951  0 buffer.append(list.getOperator());
 952  0 buffer.append("(");
 953  0 for (int i = 0; i < list.size(); i++) {
 954  0 buffer.append(getLatex(list.getElement(i), false));
 955  0 if (i + 1 < list.size()) {
 956  0 buffer.append(", ");
 957    }
 958    }
 959  0 buffer.append(")");
 960    }
 961  1700 return buffer.toString();
 962    }
 963   
 964    /**
 965    * Get timestamp.
 966    *
 967    * @return Current timestamp.
 968    */
 969  10 private String getTimestamp() {
 970  10 final SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd' 'HH:mm:ss,SSS");
 971  10 return formatter.format(new Date());
 972    }
 973   
 974    /**
 975    * Filters correct entry out of LaTeX list. Filter criterion is for example the correct
 976    * language.
 977    * TODO mime 20050205: filter level too?
 978    *
 979    * @param list List of LaTeX texts.
 980    * @return Filtered text.
 981    */
 982  1248 private String getLatexListEntry(final LatexList list) {
 983  1248 if (list == null) {
 984  384 return "";
 985    }
 986  864 for (int i = 0; i < list.size(); i++) {
 987  1168 if (language.equals(list.get(i).getLanguage())) {
 988  626 return getLatex(list.get(i));
 989    }
 990    }
 991    // assume entry with missing language as default
 992  238 for (int i = 0; i < list.size(); i++) {
 993  238 if (list.get(i).getLanguage() == null) {
 994  220 return getLatex(list.get(i));
 995    }
 996    }
 997  18 for (int i = 0; i < list.size(); i++) { // LATER mime 20050222: evaluate default?
 998  18 return "MISSING! OTHER: " + getLatex(list.get(i));
 999    }
 1000  0 return "MISSING!";
 1001    }
 1002   
 1003    /**
 1004    * Get really LaTeX. Does some simple character replacements for umlauts.
 1005    * TODO mime 20050205: filter more than German umlauts
 1006    *
 1007    * @param latex Unescaped text.
 1008    * @return Really LaTeX.
 1009    */
 1010  864 private String getLatex(final Latex latex) {
 1011  864 return escapeUmlauts(latex.getLatex());
 1012    }
 1013   
 1014    /**
 1015    * Get LaTeX from string. Escapes common characters.
 1016    *
 1017    * @param text Unescaped text.
 1018    * @return LaTeX.
 1019    */
 1020  4 private String getLatex(final String text) {
 1021  4 final StringBuffer buffer = new StringBuffer(text);
 1022  4 IoUtility.deleteLineLeadingWhitespace(buffer);
 1023  4 ReplaceUtility.replace(buffer, "\\", "\\textbackslash");
 1024  4 ReplaceUtility.replace(buffer, "$", "\\$");
 1025  4 ReplaceUtility.replace(buffer, "&", "\\&");
 1026  4 ReplaceUtility.replace(buffer, "%", "\\%");
 1027  4 ReplaceUtility.replace(buffer, "#", "\\#");
 1028  4 ReplaceUtility.replace(buffer, "_", "\\_");
 1029  4 ReplaceUtility.replace(buffer, "{", "\\{");
 1030  4 ReplaceUtility.replace(buffer, "}", "\\}");
 1031  4 ReplaceUtility.replace(buffer, "~", "\\textasciitilde");
 1032  4 ReplaceUtility.replace(buffer, "^", "\\textasciicircum");
 1033  4 ReplaceUtility.replace(buffer, "<", "\\textless");
 1034  4 ReplaceUtility.replace(buffer, ">", "\\textgreater");
 1035  4 ReplaceUtility.replace(buffer, "\u00fc", "{\\\"u}");
 1036  4 ReplaceUtility.replace(buffer, "\u00f6", "{\\\"o}");
 1037  4 ReplaceUtility.replace(buffer, "\u00e4", "{\\\"a}");
 1038  4 ReplaceUtility.replace(buffer, "\u00dc", "{\\\"U}");
 1039  4 ReplaceUtility.replace(buffer, "\u00d6", "{\\\"O}");
 1040  4 ReplaceUtility.replace(buffer, "\u00c4", "{\\\"A}");
 1041  4 ReplaceUtility.replace(buffer, "\u00df", "{\\ss}");
 1042  4 return buffer.toString();
 1043    }
 1044   
 1045    /**
 1046    * Get really LaTeX. Does some simple character replacements for umlauts.
 1047    * TODO mime 20050205: filter more than German umlauts
 1048    *
 1049    * @param nearlyLatex Unescaped text.
 1050    * @return Really LaTeX.
 1051    */
 1052  864 private String escapeUmlauts(final String nearlyLatex) {
 1053  864 if (nearlyLatex == null) {
 1054  4 return "";
 1055    }
 1056  860 final StringBuffer buffer = new StringBuffer(nearlyLatex);
 1057  860 IoUtility.deleteLineLeadingWhitespace(buffer);
 1058  860 ReplaceUtility.replace(buffer, "\u00fc", "{\\\"u}");
 1059  860 ReplaceUtility.replace(buffer, "\u00f6", "{\\\"o}");
 1060  860 ReplaceUtility.replace(buffer, "\u00e4", "{\\\"a}");
 1061  860 ReplaceUtility.replace(buffer, "\u00dc", "{\\\"U}");
 1062  860 ReplaceUtility.replace(buffer, "\u00d6", "{\\\"O}");
 1063  860 ReplaceUtility.replace(buffer, "\u00c4", "{\\\"A}");
 1064  860 ReplaceUtility.replace(buffer, "\u00df", "{\\ss}");
 1065  860 return buffer.toString();
 1066    }
 1067   
 1068    }