Clover coverage report - QedeqKernelSe Coverage Report
Coverage timestamp: Do Mai 10 2007 03:16:40 CEST
file stats: LOC: 1.080   Methods: 37
NCLOC: 838   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
Qedeq2Latex.java 66% 81,5% 100% 77,8%
coverage coverage
 1    /* $Id: Qedeq2Latex.java,v 1.47 2007/05/10 00:37:53 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.trace.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.47 $
 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  11 private Qedeq2Latex(final QedeqBo qedeq, final String globalContext,
 127    final TextOutput printer, final String language, final String level) {
 128  11 this.qedeq = qedeq;
 129  11 this.transverser = new QedeqNotNullTransverser(globalContext, this);
 130  11 this.printer = printer;
 131  11 if (language == null) {
 132  0 this.language = "en";
 133    } else {
 134  11 this.language = language;
 135    }
 136  11 if (level == null) {
 137  0 this.level = "1";
 138    } else {
 139  11 this.level = level;
 140    }
 141  11 final PredicateDefinitionVo equal = new PredicateDefinitionVo();
 142    // LATER mime 20050224: quick hack to have the logical identity operator
 143  11 equal.setArgumentNumber("2");
 144  11 equal.setName("equal");
 145  11 equal.setLatexPattern("#1 \\ = \\ #2");
 146  11 predicateDefinitions.put("equal_2", equal);
 147    // TODO mime 20060822: quick hack to get the negation of the logical identity operator
 148  11 final PredicateDefinitionVo notEqual = new PredicateDefinitionVo();
 149  11 notEqual.setArgumentNumber("2");
 150  11 notEqual.setName("notEqual");
 151  11 notEqual.setLatexPattern("#1 \\ \\neq \\ #2");
 152  11 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  11 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  11 final Qedeq2Latex converter = new Qedeq2Latex(qedeq, globalContext, printer,
 170    language, level);
 171  11 converter.printLatex();
 172    }
 173   
 174    /**
 175    * Prints a XML file into a given output stream.
 176    * Constructs a {@link QedeqBo} first.
 177    *
 178    * @throws IOException Writing failed.
 179    * @throws ModuleDataException Exception during transversion.
 180    */
 181  11 private final void printLatex() throws IOException, ModuleDataException {
 182  11 transverser.accept(qedeq);
 183  11 printer.flush();
 184  11 if (printer.checkError()) {
 185  0 throw printer.getError();
 186    }
 187    }
 188   
 189  11 public final void visitEnter(final Qedeq qedeq) {
 190  11 printer.println("% -*- TeX:" + language.toUpperCase() + " -*-");
 191  11 printer.println("%%% ====================================================================");
 192  11 printer.println("%%% @LaTeX-file " + printer.getName());
 193  11 printer.println("%%% Generated at " + getTimestamp());
 194  11 printer.println("%%% ====================================================================");
 195  11 printer.println();
 196  11 printer.println(
 197    "%%% Permission is granted to copy, distribute and/or modify this document");
 198  11 printer.println("%%% under the terms of the GNU Free Documentation License, Version 1.2");
 199  11 printer.println("%%% or any later version published by the Free Software Foundation;");
 200  11 printer.println(
 201    "%%% with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.");
 202  11 printer.println();
 203  11 printer.println("\\documentclass[a4paper,german,10pt,twoside]{book}");
 204  11 if ("de".equals(language)) {
 205  5 printer.println("\\usepackage[german]{babel}");
 206    } else {
 207  6 if (!"en".equals(language)) {
 208  0 printer.println("%%% TODO unknown language: " + language);
 209    }
 210  6 printer.println("\\usepackage[english]{babel}");
 211    }
 212  11 printer.println("\\usepackage{makeidx}");
 213  11 printer.println("\\usepackage{amsmath,amsthm,amssymb}");
 214  11 printer.println("\\usepackage{color}");
 215  11 printer.println("\\usepackage[bookmarks,bookmarksnumbered,bookmarksopen,");
 216  11 printer.println(" colorlinks,linkcolor=webgreen,pagebackref]{hyperref}");
 217  11 printer.println("\\definecolor{webgreen}{rgb}{0,.5,0}");
 218  11 printer.println("\\usepackage{graphicx}");
 219  11 printer.println("\\usepackage{xr}");
 220  11 printer.println("\\usepackage{epsfig,longtable}");
 221  11 printer.println("\\usepackage{tabularx}");
 222  11 printer.println();
 223  11 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  6 if (!"en".equals(language)) {
 240  0 printer.println("%%% TODO unknown language: " + language);
 241    }
 242  6 printer.println("\\newtheorem{thm}{Theorem}[chapter]");
 243  6 printer.println("\\newtheorem{cor}[thm]{Corollary}");
 244  6 printer.println("\\newtheorem{lem}[thm]{Lemma}");
 245  6 printer.println("\\newtheorem{prop}[thm]{Proposition}");
 246  6 printer.println("\\newtheorem{ax}{Axiom}");
 247  6 printer.println("\\newtheorem{rul}{Rule}");
 248  6 printer.println();
 249  6 printer.println("\\theoremstyle{definition}");
 250  6 printer.println("\\newtheorem{defn}[thm]{Definition}");
 251  6 printer.println("\\newtheorem{idefn}[thm]{Initial Definition}");
 252  6 printer.println();
 253  6 printer.println("\\theoremstyle{remark}");
 254  6 printer.println("\\newtheorem{rem}[thm]{Remark}");
 255  6 printer.println("\\newtheorem*{notation}{Notation}");
 256    }
 257  11 printer.println();
 258  11 printer.println("\\addtolength{\\textheight}{7\\baselineskip}");
 259  11 printer.println("\\addtolength{\\topmargin}{-5\\baselineskip}");
 260  11 printer.println();
 261  11 printer.println("\\setlength{\\parindent}{0pt}");
 262  11 printer.println();
 263  11 printer.println("\\frenchspacing \\sloppy");
 264  11 printer.println();
 265  11 printer.println("\\makeindex");
 266  11 printer.println();
 267  11 printer.println();
 268    }
 269   
 270  11 public final void visitLeave(final Qedeq qedeq) {
 271  11 printer.println("\\backmatter");
 272  11 printer.println();
 273  11 printer.println("\\addcontentsline{toc}{chapter}{\\indexname} \\printindex");
 274  11 printer.println();
 275  11 printer.println("\\end{document}");
 276  11 printer.println();
 277    }
 278   
 279  11 public void visitEnter(final Header header) {
 280  11 final LatexList title = header.getTitle();
 281  11 printer.print("\\title{");
 282  11 printer.print(getLatexListEntry(title));
 283  11 printer.println("}");
 284  11 printer.println("\\author{");
 285  11 final AuthorList authors = qedeq.getHeader().getAuthorList();
 286  11 for (int i = 0; i < authors.size(); i++) {
 287  11 if (i > 0) {
 288  0 printer.println(", ");
 289    }
 290  11 final Author author = authors.get(i);
 291  11 printer.print(author.getName().getLatex());
 292    // TODO mime 20070206 if (author.getEmail() != null)
 293    }
 294  11 printer.println();
 295  11 printer.println("}");
 296  11 printer.println();
 297  11 printer.println("\\begin{document}");
 298  11 printer.println();
 299  11 printer.println("\\maketitle");
 300  11 printer.println();
 301  11 printer.println("\\setlength{\\parskip}{5pt plus 2pt minus 1pt}");
 302  11 printer.println("\\mbox{}");
 303  11 printer.println("\\vfill");
 304  11 printer.println();
 305  11 final String url = getUrl(header.getSpecification());
 306  11 if (url != null && url.length() > 0) {
 307  11 printer.println("\\par");
 308  11 if ("de".equals(language)) {
 309  5 printer.println("Die Quelle f{\"ur} dieses Dokument ist hier zu finden:");
 310    } else {
 311  6 if (!"en".equals(language)) {
 312  0 printer.println("%%% TODO unknown language: " + language);
 313    }
 314  6 printer.println("The source for this document can be found here:");
 315    }
 316  11 printer.println("\\par");
 317  11 printer.println("\\url{" + getUrl(header.getSpecification()) + "}");
 318  11 printer.println();
 319    }
 320    {
 321  11 printer.println("\\par");
 322  11 if ("de".equals(language)) {
 323  5 printer.println("Die vorliegende Publikation ist urheberrechtlich gesch{\"u}tzt.");
 324    } else {
 325  6 if (!"en".equals(language)) {
 326  0 printer.println("%%% TODO unknown language: " + language);
 327    }
 328  6 printer.println("Copyright by the authors. All rights reserved.");
 329    }
 330    }
 331  11 final String email = header.getEmail();
 332  11 if (email != null && email.length() > 0) {
 333  11 final String emailUrl = "\\url{mailto:" + email + "}";
 334  11 printer.println("\\par");
 335  11 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  6 if (!"en".equals(language)) {
 341  0 printer.println("%%% TODO unknown language: " + language);
 342    }
 343  6 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  11 printer.println();
 348    }
 349  11 printer.println("\\setlength{\\parskip}{0pt}");
 350  11 printer.println("\\tableofcontents");
 351  11 printer.println();
 352  11 printer.println("\\setlength{\\parskip}{5pt plus 2pt minus 1pt}");
 353  11 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  24 private String getUrl(final Specification specification) {
 363  24 final LocationList list = specification.getLocationList();
 364  24 if (list == null || list.size() <= 0
 365    || list.get(0).getLocation().length() <= "http://a.b".length()) {
 366  2 return "";
 367    }
 368  22 String location = list.get(0).getLocation();
 369  22 if (!location.endsWith("/")) {
 370  22 location += "/";
 371    }
 372  22 location += specification.getName();
 373  22 location += ".xml";
 374  22 return location;
 375    }
 376   
 377  62 public void visitEnter(final Chapter chapter) {
 378  62 printer.print("\\chapter");
 379  62 if (chapter.getNoNumber() != null && chapter.getNoNumber().booleanValue()) {
 380  18 printer.print("*");
 381    }
 382  62 printer.print("{");
 383  62 printer.print(getLatexListEntry(chapter.getTitle()));
 384  62 final String label = "chapter" + chapterNumber;
 385  62 printer.println("} \\label{" + label + "} \\hypertarget{" + label + "}{}");
 386  62 if (chapter.getNoNumber() != null && chapter.getNoNumber().booleanValue()) {
 387  18 printer.println("\\addcontentsline{toc}{chapter}{"
 388    + getLatexListEntry(chapter.getTitle()) + "}");
 389    }
 390  62 printer.println();
 391  62 if (chapter.getIntroduction() != null) {
 392  62 printer.println(getLatexListEntry(chapter.getIntroduction()));
 393  62 printer.println();
 394    }
 395    }
 396   
 397  62 public void visitLeave(final Chapter chapter) {
 398  62 printer.println("%% end of chapter " + getLatexListEntry(chapter.getTitle()));
 399  62 printer.println();
 400  62 chapterNumber++; // increase global chapter number
 401  62 sectionNumber = 0; // reset section number
 402    }
 403   
 404  37 public void visitLeave(final SectionList list) {
 405  37 printer.println();
 406    }
 407   
 408  116 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  116 printer.print("\\section{");
 415  116 printer.print(getLatexListEntry(section.getTitle()));
 416  116 final String label = "chapter" + chapterNumber + "_section" + sectionNumber;
 417  116 printer.println("} \\label{" + label + "} \\hypertarget{" + label + "}{}");
 418  116 printer.println(getLatexListEntry(section.getIntroduction()));
 419  116 printer.println();
 420    }
 421   
 422  116 public void visitLeave(final Section section) {
 423  116 sectionNumber++; // increase global section number
 424    }
 425   
 426  47 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  47 if (subsection.getTitle() != null) {
 436  40 printer.print("\\subsection{");
 437  40 printer.println(getLatexListEntry(subsection.getTitle()));
 438  40 printer.println("}");
 439    }
 440  47 if (subsection.getId() != null) {
 441  0 printer.println("\\label{" + subsection.getId() + "} \\hypertarget{"
 442    + subsection.getId() + "}{}");
 443    }
 444  47 printer.println(getLatexListEntry(subsection.getLatex()));
 445    }
 446   
 447  47 public void visitLeave(final Subsection subsection) {
 448  47 printer.println();
 449  47 printer.println();
 450    }
 451   
 452  310 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  310 printer.println("\\par");
 459  310 printer.println(getLatexListEntry(node.getPrecedingText()));
 460  310 printer.println();
 461  310 id = node.getId();
 462  310 title = null;
 463  310 if (node.getTitle() != null) {
 464  149 title = getLatexListEntry(node.getTitle());
 465    }
 466    }
 467   
 468  310 public void visitLeave(final Node node) {
 469  310 printer.println();
 470  310 printer.println(getLatexListEntry(node.getSucceedingText()));
 471  310 printer.println();
 472  310 printer.println();
 473    }
 474   
 475  47 public void visitEnter(final Axiom axiom) {
 476  47 printer.println("\\begin{ax}" + (title != null ? "[" + title + "]" : ""));
 477  47 printer.println("\\label{" + id + "} \\hypertarget{" + id + "}{}");
 478  47 printFormula(axiom.getFormula().getElement());
 479  47 printer.println(getLatexListEntry(axiom.getDescription()));
 480  47 printer.println("\\end{ax}");
 481    }
 482   
 483  163 public void visitEnter(final Proposition proposition) {
 484  163 printer.println("\\begin{prop}" + (title != null ? "[" + title + "]" : ""));
 485  163 printer.println("\\label{" + id + "} \\hypertarget{" + id + "}{}");
 486  163 printTopFormula(proposition.getFormula().getElement(), id);
 487  163 printer.println(getLatexListEntry(proposition.getDescription()));
 488  163 printer.println("\\end{prop}");
 489    }
 490   
 491  14 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  14 printer.println("\\begin{proof}");
 501  14 printer.println(getLatexListEntry(proof.getNonFormalProof()));
 502  14 printer.println("\\end{proof}");
 503    }
 504   
 505  35 public void visitEnter(final PredicateDefinition definition) {
 506  35 final StringBuffer define = new StringBuffer("$$" + definition.getLatexPattern());
 507  35 final VariableList list = definition.getVariableList();
 508  35 if (list != null) {
 509  31 for (int i = list.size() - 1; i >= 0; i--) {
 510  48 Trace.trace(this, "printPredicateDefinition", "replacing!");
 511  48 ReplaceUtility.replace(define, "#" + (i + 1), getLatex(list.get(i)));
 512    }
 513    }
 514  35 if (definition.getFormula() != null) {
 515  30 printer.println("\\begin{defn}" + (title != null ? "[" + title + "]" : ""));
 516  30 printer.println("\\label{" + id + "} \\hypertarget{" + id + "}{}");
 517  30 define.append("\\ :\\leftrightarrow \\ ");
 518  30 define.append(getLatex(definition.getFormula().getElement()));
 519    } else {
 520  5 printer.println("\\begin{idefn}" + (title != null ? "[" + title + "]" : ""));
 521  5 printer.println("\\label{" + id + "} \\hypertarget{" + id + "}{}");
 522    }
 523  35 define.append("$$");
 524  35 predicateDefinitions.put(definition.getName() + "_" + definition.getArgumentNumber(),
 525    definition);
 526  35 Trace.param(this, "printPredicateDefinition", "define", define);
 527  35 printer.println(define);
 528  35 printer.println(getLatexListEntry(definition.getDescription()));
 529  35 if (definition.getFormula() != null) {
 530  30 printer.println("\\end{defn}");
 531    } else {
 532  5 printer.println("\\end{idefn}");
 533    }
 534    }
 535   
 536  48 public void visitEnter(final FunctionDefinition definition) {
 537  48 final StringBuffer define = new StringBuffer("$$" + definition.getLatexPattern());
 538  48 final VariableList list = definition.getVariableList();
 539  48 if (list != null) {
 540  39 for (int i = list.size() - 1; i >= 0; i--) {
 541  54 Trace.trace(this, "printFunctionDefinition", "replacing!");
 542  54 ReplaceUtility.replace(define, "#" + (i + 1), getLatex(list.get(i)));
 543    }
 544    }
 545  48 if (definition.getTerm() != null) {
 546  48 printer.println("\\begin{defn}" + (title != null ? "[" + title + "]" : ""));
 547  48 printer.println("\\label{" + id + "} \\hypertarget{" + id + "}{}");
 548  48 define.append("\\ := \\ ");
 549  48 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  48 define.append("$$");
 555  48 functionDefinitions.put(definition.getName() + "_" + definition.getArgumentNumber(),
 556    definition);
 557  48 Trace.param(this, "printFunctionDefinition", "define", define);
 558  48 printer.println(define);
 559  48 printer.println(getLatexListEntry(definition.getDescription()));
 560  48 if (definition.getTerm() != null) {
 561  48 printer.println("\\end{defn}");
 562    } else {
 563  0 printer.println("\\end{idefn}");
 564    }
 565    }
 566   
 567  48 public void visitLeave(final FunctionDefinition definition) {
 568    }
 569   
 570  17 public void visitEnter(final Rule rule) {
 571  17 printer.println("\\begin{rul}" + (title != null ? "[" + title + "]" : ""));
 572  17 printer.println("\\label{" + id + "} \\hypertarget{" + id + "}{}");
 573  17 printer.println(getLatexListEntry(rule.getDescription()));
 574  17 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  17 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  17 public void visitLeave(final Rule rule) {
 600    }
 601   
 602  3 public void visitEnter(final LinkList linkList) {
 603  3 if (linkList.size() <= 0) {
 604  0 return;
 605    }
 606  3 if ("de".equals(language)) {
 607  1 printer.println("Basierend auf: ");
 608    } else {
 609  2 if (!"en".equals(language)) {
 610  0 printer.println("%%% TODO unknown language: " + language);
 611    }
 612  2 printer.println("Based on: ");
 613    }
 614  3 for (int i = 0; i < linkList.size(); i++) {
 615  3 if (linkList.get(i) != null) {
 616  3 printer.print(" \\ref{" + linkList.get(i) + "}");
 617    }
 618    };
 619  3 printer.println();
 620    }
 621   
 622  5 public void visitEnter(final LiteratureItemList list) {
 623  5 printer.println("\\begin{thebibliography}{99}");
 624    // TODO mime 20060926: remove language dependency
 625  5 if ("de".equals(language)) {
 626  2 printer.println("\\addcontentsline{toc}{chapter}{Literaturverzeichnis}");
 627    } else {
 628  3 if (!"en".equals(language)) {
 629  0 printer.println("%%% TODO unknown language: " + language);
 630    }
 631  3 printer.println("\\addcontentsline{toc}{chapter}{Bibliography}");
 632    }
 633  5 final ImportList imports = qedeq.getHeader().getImportList();
 634  5 if (imports != null && imports.size() > 0) {
 635  3 printer.println();
 636  3 printer.println();
 637  3 printer.println("%% Used other QEDEQ modules:");
 638  3 for (int i = 0; i < imports.size(); i++) {
 639  3 final Import imp = imports.get(i);
 640  3 printer.print("\\bibitem{" + imp.getLabel() + "} ");
 641  3 final Specification spec = imp.getSpecification();
 642  3 printer.print(getLatex(spec.getName()));
 643  3 if (spec.getLocationList() != null && spec.getLocationList().size() > 0
 644    && spec.getLocationList().get(0).getLocation().length() > 0) {
 645  3 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  3 printer.print("\\url{" + spec.getLocationList().get(0).getLocation() + "}");
 650    }
 651  3 printer.println();
 652    }
 653  3 printer.println();
 654  3 printer.println();
 655  3 printer.println("%% Other references:");
 656  3 printer.println();
 657    }
 658    }
 659   
 660  5 public void visitLeave(final LiteratureItemList list) {
 661  5 final UsedByList usedby = qedeq.getHeader().getUsedByList();
 662  5 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  5 printer.println("\\end{thebibliography}");
 681    }
 682   
 683  23 public void visitEnter(final LiteratureItem item) {
 684  23 printer.print("\\bibitem{" + item.getLabel() + "} ");
 685  23 printer.println(getLatexListEntry(item.getItem()));
 686  23 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  163 private void printTopFormula(final Element element, final String mainLabel) {
 697  163 if (!element.isList() || !element.getList().getOperator().equals("AND")) {
 698  113 printFormula(element);
 699  113 return;
 700    }
 701  50 final ElementList list = element.getList();
 702  50 printer.println("\\mbox{}");
 703  50 printer.println("\\begin{longtable}{{@{\\extracolsep{\\fill}}p{0.9\\linewidth}l}}");
 704  50 for (int i = 0; i < list.size(); i++) {
 705  309 String label = "";
 706  309 if (list.size() >= ALPHABET.length() * ALPHABET.length()) {
 707  0 label = "" + (i + 1);
 708    } else {
 709  309 if (list.size() > ALPHABET.length()) {
 710  72 final int div = (i / ALPHABET.length());
 711  72 label = "" + ALPHABET.charAt(div);
 712    }
 713  309 label += ALPHABET.charAt(i % ALPHABET.length());
 714    }
 715    // final String label = (i < ALPHABET.length() ? "" + ALPHABET .charAt(i) : "" + i);
 716  309 printer.println("\\centering $" + getLatex(list.getElement(i)) + "$"
 717    + " & \\label{" + mainLabel + ":" + label + "} \\hypertarget{" + mainLabel + ":"
 718    + label + "}{} \\mbox{\\emph{(" + label + ")}} "
 719  309 + (i + 1 < list.size() ? "\\\\" : ""));
 720    }
 721  50 printer.println("\\end{longtable}");
 722    }
 723   
 724    /**
 725    * Print formula.
 726    *
 727    * @param element Formula to print.
 728    */
 729  160 private void printFormula(final Element element) {
 730  160 printer.println("\\mbox{}");
 731  160 printer.println("\\begin{longtable}{{@{\\extracolsep{\\fill}}p{\\linewidth}}}");
 732  160 printer.println("\\centering $" + getLatex(element) + "$");
 733  160 printer.println("\\end{longtable}");
 734    }
 735   
 736    /**
 737    * Get LaTeX element presentation.
 738    *
 739    * @param element Print this element.
 740    * @return LaTeX form of element.
 741    */
 742  649 private String getLatex(final Element element) {
 743  649 return getLatex(element, true);
 744    }
 745   
 746    /**
 747    * Get LaTeX element presentation.
 748    *
 749    * @param element Print this element.
 750    * @param first First level?
 751    * @return LaTeX form of element.
 752    */
 753  5028 private String getLatex(final Element element, final boolean first) {
 754  5028 final StringBuffer buffer = new StringBuffer();
 755  5028 if (element.isAtom()) {
 756  0 return element.getAtom().getString();
 757    }
 758  5028 final ElementList list = element.getList();
 759  5028 if (list.getOperator().equals("PREDCON")) {
 760  937 final String identifier = list.getElement(0).getAtom().getString() + "_"
 761    + (list.size() - 1);
 762    // TODO mime 20060922: is only working for definition name + argument number
 763    // if argument length is dynamic this dosen't work
 764  937 if (predicateDefinitions.containsKey(identifier)) {
 765  937 final PredicateDefinition definition = (PredicateDefinition)
 766    predicateDefinitions.get(identifier);
 767  937 final StringBuffer define = new StringBuffer(definition.getLatexPattern());
 768  937 for (int i = list.size() - 1; i >= 1; i--) {
 769  1542 ReplaceUtility.replace(define, "#" + i, getLatex(list.getElement(i), false));
 770    }
 771  937 buffer.append(define);
 772    } else {
 773  0 buffer.append(identifier);
 774  0 buffer.append("(");
 775  0 for (int i = 1; i < list.size(); i++) {
 776  0 buffer.append(getLatex(list.getElement(i), false));
 777  0 if (i + 1 < list.size()) {
 778  0 buffer.append(", ");
 779    }
 780    }
 781  0 buffer.append(")");
 782    }
 783  4091 } else if (list.getOperator().equals("PREDVAR")) {
 784  367 final String identifier = list.getElement(0).getAtom().getString();
 785  367 buffer.append(identifier);
 786  367 if (list.size() > 1) {
 787  71 buffer.append("(");
 788  71 for (int i = 1; i < list.size(); i++) {
 789  71 buffer.append(getLatex(list.getElement(i), false));
 790  71 if (i + 1 < list.size()) {
 791  0 buffer.append(", ");
 792    }
 793    }
 794  71 buffer.append(")");
 795    }
 796  3724 } else if (list.getOperator().equals("FUNCON")) {
 797  720 final String identifier = list.getElement(0).getAtom().getString() + "_"
 798    + (list.size() - 1);
 799    // TODO mime 20060922: is only working for definition name + argument number
 800    // if argument length is dynamic this dosen't work
 801  720 if (functionDefinitions.containsKey(identifier)) {
 802  720 final FunctionDefinition definition = (FunctionDefinition)
 803    functionDefinitions.get(identifier);
 804  720 final StringBuffer define = new StringBuffer(definition.getLatexPattern());
 805  720 for (int i = list.size() - 1; i >= 1; i--) {
 806  849 ReplaceUtility.replace(define, "#" + i, getLatex(list.getElement(i), false));
 807    }
 808  720 buffer.append(define);
 809    } else {
 810  0 buffer.append(identifier);
 811  0 buffer.append("(");
 812  0 for (int i = 1; i < list.size(); i++) {
 813  0 buffer.append(getLatex(list.getElement(i), false));
 814  0 if (i + 1 < list.size()) {
 815  0 buffer.append(", ");
 816    }
 817    }
 818  0 buffer.append(")");
 819    }
 820  3004 } else if (list.getOperator().equals("FUNVAR")) {
 821  0 final String identifier = list.getElement(0).getAtom().getString();
 822  0 buffer.append(identifier);
 823  0 if (list.size() > 1) {
 824  0 buffer.append("(");
 825  0 for (int i = 1; i < list.size(); i++) {
 826  0 buffer.append(getLatex(list.getElement(i), false));
 827  0 if (i + 1 < list.size()) {
 828  0 buffer.append(", ");
 829    }
 830    }
 831  0 buffer.append(")");
 832    }
 833  3004 } else if (list.getOperator().equals("VAR")) {
 834  2014 final String text = list.getElement(0).getAtom().getString();
 835    // interpret variable identifier as number
 836  2014 try {
 837  2014 final int index = Integer.parseInt(text);
 838  0 final String newText = "" + index;
 839  0 if (!text.equals(newText) || newText.startsWith("-")) {
 840  0 throw new NumberFormatException("This is no allowed number: " + text);
 841    }
 842  0 switch (index) {
 843  0 case 1:
 844  0 return "x";
 845  0 case 2:
 846  0 return "y";
 847  0 case 3:
 848  0 return "z";
 849  0 case 4:
 850  0 return "u";
 851  0 case 5:
 852  0 return "v";
 853  0 case 6:
 854  0 return "w";
 855  0 default:
 856  0 return "x_" + (index - 6);
 857    }
 858    } catch (NumberFormatException e) {
 859    // variable identifier is no number, just take it as it is
 860  2014 return text;
 861    }
 862  990 } else if (list.getOperator().equals("AND") || list.getOperator().equals("OR")
 863    || list.getOperator().equals("EQUI") || list.getOperator().equals("IMPL")) {
 864  686 final String infix;
 865  686 if (list.getOperator().equals("AND")) {
 866  169 infix = "\\ \\land \\ ";
 867  517 } else if (list.getOperator().equals("OR")) {
 868  73 infix = "\\ \\lor \\ ";
 869  444 } else if (list.getOperator().equals("EQUI")) {
 870  208 infix = "\\ \\leftrightarrow \\ ";
 871    } else {
 872  236 infix = "\\ \\rightarrow \\ ";
 873    }
 874  686 if (!first) {
 875  380 buffer.append("(");
 876    }
 877  686 for (int i = 0; i < list.size(); i++) {
 878  1390 buffer.append(getLatex(list.getElement(i), false));
 879  1390 if (i + 1 < list.size()) {
 880  704 buffer.append(infix);
 881    }
 882    }
 883  686 if (!first) {
 884  380 buffer.append(")");
 885    }
 886  304 } else if (list.getOperator().equals("FORALL") || list.getOperator().equals("EXISTS")
 887    || list.getOperator().equals("EXISTSU")) {
 888  127 final String prefix;
 889  127 if (list.getOperator().equals("FORALL")) {
 890  75 prefix = "\\forall ";
 891  52 } else if (list.getOperator().equals("EXISTS")) {
 892  43 prefix = "\\exists ";
 893    } else {
 894  9 prefix = "\\exists! ";
 895    }
 896  127 buffer.append(prefix);
 897  127 for (int i = 0; i < list.size(); i++) {
 898  259 if (i != 0 || (i == 0 && list.size() <= 2)) {
 899  254 buffer.append(getLatex(list.getElement(i), false));
 900    }
 901  259 if (i + 1 < list.size()) {
 902  132 buffer.append("\\ ");
 903    }
 904  259 if (list.size() > 2 && i == 1) {
 905  5 buffer.append("\\ ");
 906    }
 907    }
 908  177 } else if (list.getOperator().equals("NOT")) {
 909  81 final String prefix = "\\neg ";
 910  81 buffer.append(prefix);
 911  81 for (int i = 0; i < list.size(); i++) {
 912  81 buffer.append(getLatex(list.getElement(i), false));
 913    }
 914  96 } else if (list.getOperator().equals("CLASS")) {
 915  96 final String prefix = "\\{ ";
 916  96 buffer.append(prefix);
 917  96 for (int i = 0; i < list.size(); i++) {
 918  192 buffer.append(getLatex(list.getElement(i), false));
 919  192 if (i + 1 < list.size()) {
 920  96 buffer.append(" \\ | \\ ");
 921    }
 922    }
 923  96 buffer.append(" \\} ");
 924  0 } else if (list.getOperator().equals("CLASSLIST")) {
 925  0 final String prefix = "\\{ ";
 926  0 buffer.append(prefix);
 927  0 for (int i = 0; i < list.size(); i++) {
 928  0 buffer.append(getLatex(list.getElement(i), false));
 929  0 if (i + 1 < list.size()) {
 930  0 buffer.append(", \\ ");
 931    }
 932    }
 933  0 buffer.append(" \\} ");
 934  0 } else if (list.getOperator().equals("QUANTOR_INTERSECTION")) {
 935  0 final String prefix = "\\bigcap";
 936  0 buffer.append(prefix);
 937  0 if (0 < list.size()) {
 938  0 buffer.append("{").append(getLatex(list.getElement(0), false)).append("}");
 939    }
 940  0 for (int i = 1; i < list.size(); i++) {
 941  0 buffer.append(getLatex(list.getElement(i), false));
 942  0 if (i + 1 < list.size()) {
 943  0 buffer.append(" \\ \\ ");
 944    }
 945    }
 946  0 buffer.append(" \\} ");
 947  0 } else if (list.getOperator().equals("QUANTOR_UNION")) {
 948  0 final String prefix = "\\bigcup";
 949  0 buffer.append(prefix);
 950  0 if (0 < list.size()) {
 951  0 buffer.append("{").append(getLatex(list.getElement(0), false)).append("}");
 952    }
 953  0 for (int i = 1; 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    } else {
 961  0 buffer.append(list.getOperator());
 962  0 buffer.append("(");
 963  0 for (int i = 0; i < list.size(); i++) {
 964  0 buffer.append(getLatex(list.getElement(i), false));
 965  0 if (i + 1 < list.size()) {
 966  0 buffer.append(", ");
 967    }
 968    }
 969  0 buffer.append(")");
 970    }
 971  3014 return buffer.toString();
 972    }
 973   
 974    /**
 975    * Get timestamp.
 976    *
 977    * @return Current timestamp.
 978    */
 979  11 private String getTimestamp() {
 980  11 final SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd' 'HH:mm:ss,SSS");
 981  11 return formatter.format(new Date());
 982    }
 983   
 984    /**
 985    * Filters correct entry out of LaTeX list. Filter criterion is for example the correct
 986    * language.
 987    * TODO mime 20050205: filter level too?
 988    *
 989    * @param list List of LaTeX texts.
 990    * @return Filtered text.
 991    */
 992  1650 private String getLatexListEntry(final LatexList list) {
 993  1650 if (list == null) {
 994  554 return "";
 995    }
 996  1096 for (int i = 0; i < list.size(); i++) {
 997  1407 if (language.equals(list.get(i).getLanguage())) {
 998  857 return getLatex(list.get(i));
 999    }
 1000    }
 1001    // assume entry with missing language as default
 1002  239 for (int i = 0; i < list.size(); i++) {
 1003  239 if (list.get(i).getLanguage() == null) {
 1004  220 return getLatex(list.get(i));
 1005    }
 1006    }
 1007  19 for (int i = 0; i < list.size(); i++) { // LATER mime 20050222: evaluate default?
 1008  19 return "MISSING! OTHER: " + getLatex(list.get(i));
 1009    }
 1010  0 return "MISSING!";
 1011    }
 1012   
 1013    /**
 1014    * Get really LaTeX. Does some simple character replacements for umlauts.
 1015    *
 1016    * @param latex Unescaped text.
 1017    * @return Really LaTeX.
 1018    */
 1019  1096 private String getLatex(final Latex latex) {
 1020  1096 if (latex == null || latex.getLatex() == null) {
 1021  6 return "";
 1022    }
 1023  1090 return escapeUmlauts(latex.getLatex());
 1024    }
 1025   
 1026    /**
 1027    * Get LaTeX from string. Escapes common characters.
 1028    *
 1029    * @param text Unescaped text.
 1030    * @return LaTeX.
 1031    */
 1032  5 private String getLatex(final String text) {
 1033  5 final StringBuffer buffer = new StringBuffer(text);
 1034  5 IoUtility.deleteLineLeadingWhitespace(buffer);
 1035  5 ReplaceUtility.replace(buffer, "\\", "\\textbackslash");
 1036  5 ReplaceUtility.replace(buffer, "$", "\\$");
 1037  5 ReplaceUtility.replace(buffer, "&", "\\&");
 1038  5 ReplaceUtility.replace(buffer, "%", "\\%");
 1039  5 ReplaceUtility.replace(buffer, "#", "\\#");
 1040  5 ReplaceUtility.replace(buffer, "_", "\\_");
 1041  5 ReplaceUtility.replace(buffer, "{", "\\{");
 1042  5 ReplaceUtility.replace(buffer, "}", "\\}");
 1043  5 ReplaceUtility.replace(buffer, "~", "\\textasciitilde");
 1044  5 ReplaceUtility.replace(buffer, "^", "\\textasciicircum");
 1045  5 ReplaceUtility.replace(buffer, "<", "\\textless");
 1046  5 ReplaceUtility.replace(buffer, ">", "\\textgreater");
 1047  5 ReplaceUtility.replace(buffer, "\u00fc", "{\\\"u}");
 1048  5 ReplaceUtility.replace(buffer, "\u00f6", "{\\\"o}");
 1049  5 ReplaceUtility.replace(buffer, "\u00e4", "{\\\"a}");
 1050  5 ReplaceUtility.replace(buffer, "\u00dc", "{\\\"U}");
 1051  5 ReplaceUtility.replace(buffer, "\u00d6", "{\\\"O}");
 1052  5 ReplaceUtility.replace(buffer, "\u00c4", "{\\\"A}");
 1053  5 ReplaceUtility.replace(buffer, "\u00df", "{\\ss}");
 1054  5 return buffer.toString();
 1055    }
 1056   
 1057    /**
 1058    * Get really LaTeX. Does some simple character replacements for umlauts.
 1059    * TODO mime 20050205: filter more than German umlauts
 1060    *
 1061    * @param nearlyLatex Unescaped text.
 1062    * @return Really LaTeX.
 1063    */
 1064  1090 private String escapeUmlauts(final String nearlyLatex) {
 1065  1090 if (nearlyLatex == null) {
 1066  0 return "";
 1067    }
 1068  1090 final StringBuffer buffer = new StringBuffer(nearlyLatex);
 1069  1090 IoUtility.deleteLineLeadingWhitespace(buffer);
 1070  1090 ReplaceUtility.replace(buffer, "\u00fc", "{\\\"u}");
 1071  1090 ReplaceUtility.replace(buffer, "\u00f6", "{\\\"o}");
 1072  1090 ReplaceUtility.replace(buffer, "\u00e4", "{\\\"a}");
 1073  1090 ReplaceUtility.replace(buffer, "\u00dc", "{\\\"U}");
 1074  1090 ReplaceUtility.replace(buffer, "\u00d6", "{\\\"O}");
 1075  1090 ReplaceUtility.replace(buffer, "\u00c4", "{\\\"A}");
 1076  1090 ReplaceUtility.replace(buffer, "\u00df", "{\\ss}");
 1077  1090 return buffer.toString();
 1078    }
 1079   
 1080    }