Qedeq2LatexExecutor.java
0001 /* This file is part of the project "Hilbert II" - http://www.qedeq.org
0002  *
0003  * Copyright 2000-2014,  Michael Meyling <mime@qedeq.org>.
0004  *
0005  * "Hilbert II" is free software; you can redistribute
0006  * it and/or modify it under the terms of the GNU General Public
0007  * License as published by the Free Software Foundation; either
0008  * version 2 of the License, or (at your option) any later version.
0009  *
0010  * This program is distributed in the hope that it will be useful,
0011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0013  * GNU General Public License for more details.
0014  */
0015 
0016 package org.qedeq.kernel.bo.service.latex;
0017 
0018 import java.io.File;
0019 import java.io.FileInputStream;
0020 import java.io.FileOutputStream;
0021 import java.io.IOException;
0022 import java.io.InputStream;
0023 import java.util.Locale;
0024 
0025 import org.qedeq.base.io.IoUtility;
0026 import org.qedeq.base.io.Parameters;
0027 import org.qedeq.base.io.SourcePosition;
0028 import org.qedeq.base.io.TextInput;
0029 import org.qedeq.base.io.TextOutput;
0030 import org.qedeq.base.trace.Trace;
0031 import org.qedeq.base.utility.DateUtility;
0032 import org.qedeq.base.utility.EqualsUtility;
0033 import org.qedeq.base.utility.StringUtility;
0034 import org.qedeq.kernel.bo.log.QedeqLog;
0035 import org.qedeq.kernel.bo.module.InternalModuleServiceCall;
0036 import org.qedeq.kernel.bo.module.KernelNodeBo;
0037 import org.qedeq.kernel.bo.module.KernelQedeqBo;
0038 import org.qedeq.kernel.bo.module.Reference;
0039 import org.qedeq.kernel.bo.service.basis.ControlVisitor;
0040 import org.qedeq.kernel.bo.service.basis.ModuleServicePluginExecutor;
0041 import org.qedeq.kernel.se.base.list.Element;
0042 import org.qedeq.kernel.se.base.list.ElementList;
0043 import org.qedeq.kernel.se.base.module.Add;
0044 import org.qedeq.kernel.se.base.module.Author;
0045 import org.qedeq.kernel.se.base.module.AuthorList;
0046 import org.qedeq.kernel.se.base.module.Axiom;
0047 import org.qedeq.kernel.se.base.module.ChangedRule;
0048 import org.qedeq.kernel.se.base.module.ChangedRuleList;
0049 import org.qedeq.kernel.se.base.module.Chapter;
0050 import org.qedeq.kernel.se.base.module.Conclusion;
0051 import org.qedeq.kernel.se.base.module.ConditionalProof;
0052 import org.qedeq.kernel.se.base.module.Existential;
0053 import org.qedeq.kernel.se.base.module.FormalProof;
0054 import org.qedeq.kernel.se.base.module.FormalProofLine;
0055 import org.qedeq.kernel.se.base.module.FormalProofLineList;
0056 import org.qedeq.kernel.se.base.module.FunctionDefinition;
0057 import org.qedeq.kernel.se.base.module.Header;
0058 import org.qedeq.kernel.se.base.module.Hypothesis;
0059 import org.qedeq.kernel.se.base.module.Import;
0060 import org.qedeq.kernel.se.base.module.ImportList;
0061 import org.qedeq.kernel.se.base.module.InitialFunctionDefinition;
0062 import org.qedeq.kernel.se.base.module.InitialPredicateDefinition;
0063 import org.qedeq.kernel.se.base.module.Latex;
0064 import org.qedeq.kernel.se.base.module.LatexList;
0065 import org.qedeq.kernel.se.base.module.LinkList;
0066 import org.qedeq.kernel.se.base.module.LiteratureItem;
0067 import org.qedeq.kernel.se.base.module.LiteratureItemList;
0068 import org.qedeq.kernel.se.base.module.LocationList;
0069 import org.qedeq.kernel.se.base.module.ModusPonens;
0070 import org.qedeq.kernel.se.base.module.Node;
0071 import org.qedeq.kernel.se.base.module.PredicateDefinition;
0072 import org.qedeq.kernel.se.base.module.Proof;
0073 import org.qedeq.kernel.se.base.module.Proposition;
0074 import org.qedeq.kernel.se.base.module.Qedeq;
0075 import org.qedeq.kernel.se.base.module.Rename;
0076 import org.qedeq.kernel.se.base.module.Rule;
0077 import org.qedeq.kernel.se.base.module.Section;
0078 import org.qedeq.kernel.se.base.module.SectionList;
0079 import org.qedeq.kernel.se.base.module.Specification;
0080 import org.qedeq.kernel.se.base.module.Subsection;
0081 import org.qedeq.kernel.se.base.module.SubsectionList;
0082 import org.qedeq.kernel.se.base.module.SubsectionType;
0083 import org.qedeq.kernel.se.base.module.SubstFree;
0084 import org.qedeq.kernel.se.base.module.SubstFunc;
0085 import org.qedeq.kernel.se.base.module.SubstPred;
0086 import org.qedeq.kernel.se.base.module.Universal;
0087 import org.qedeq.kernel.se.base.module.UsedByList;
0088 import org.qedeq.kernel.se.common.ModuleAddress;
0089 import org.qedeq.kernel.se.common.ModuleContext;
0090 import org.qedeq.kernel.se.common.ModuleDataException;
0091 import org.qedeq.kernel.se.common.ModuleService;
0092 import org.qedeq.kernel.se.common.RuleKey;
0093 import org.qedeq.kernel.se.common.SourceFileExceptionList;
0094 
0095 
0096 /**
0097  * Transfer a QEDEQ module into a LaTeX file.
0098  <p>
0099  <b>This is just a quick written generator. No parsing or validation
0100  * of inline LaTeX text is done. This class just generates some LaTeX output to be able to
0101  * get a visual impression of a QEDEQ module.</b>
0102  *
0103  @author  Michael Meyling
0104  */
0105 public final class Qedeq2LatexExecutor extends ControlVisitor implements ModuleServicePluginExecutor {
0106 
0107     /** This class. */
0108     private static final Class CLASS = Qedeq2LatexExecutor.class;
0109 
0110 // TODO m31 20100316: check number area for error codes
0111 // TODO m31 20100803: add JUnit tests for all error codes
0112 
0113     /** Output goes here. */
0114     private TextOutput printer;
0115 
0116     /** Filter text to get and produce text in this language. */
0117     private String language;
0118 
0119     /** Filter for this detail level. */
0120 //    private String level;
0121 
0122     /** Should additional information be put into LaTeX output? E.g. QEDEQ reference names. */
0123     private final boolean info;
0124 
0125     /** Should only names and formulas be be printed? */
0126     private final boolean brief;
0127 
0128     /** Current node id. */
0129     private String id;
0130 
0131     /** Current node title. */
0132     private String title;
0133 
0134     /** Sub context like "getIntroduction()". */
0135     private String subContext = "";
0136 
0137     /** Remembered proof line label. */
0138     private String label = "";
0139 
0140     /** Remembered proof line formula. */
0141     private String formula = "";
0142 
0143     /** Remembered proof line reason. */
0144     private String reason = "";
0145 
0146     /** Remembered proof line tabulator level. */
0147     private int tabLevel = 0;
0148 
0149     /** Alphabet for tagging. */
0150     private static final String ALPHABET = "abcdefghijklmnopqrstuvwxyz";
0151 
0152     /**
0153      * Constructor.
0154      *
0155      @param   plugin      This plugin we work for.
0156      @param   prop        QEDEQ BO object.
0157      @param   parameters  Parameters.
0158      */
0159     public Qedeq2LatexExecutor(final ModuleService plugin, final KernelQedeqBo prop, final Parameters parameters) {
0160         super(plugin, prop);
0161         info = parameters.getBoolean("info");
0162         brief = parameters.getBoolean("brief");
0163     }
0164 
0165     private ModuleService getPlugin() {
0166         return (ModuleServicegetService();
0167     }
0168 
0169     public Object executePlugin(final InternalModuleServiceCall call, final Object data) {
0170         final String method = "executePlugin(QedeqBo, Map)";
0171         try {
0172             QedeqLog.getInstance().logRequest("Generate LaTeX", getKernelQedeqBo().getUrl());
0173             final String[] languages = getKernelQedeqBo().getSupportedLanguages();
0174             for (int j = 0; j < languages.length; j++) {
0175                 language = languages[j];
0176 //                level = "1";
0177                 final String result = generateLatex(call, languages[j]"1").toString();
0178                 if (languages[j!= null) {
0179                     QedeqLog.getInstance().logSuccessfulReply(
0180                         "LaTeX for language \"" + languages[j]
0181                         "\" was generated from into \"" + result + "\"", getKernelQedeqBo().getUrl());
0182                 else {
0183                     QedeqLog.getInstance().logSuccessfulReply(
0184                         "LaTeX for default language "
0185                         "was generated into \"" + result + "\"", getKernelQedeqBo().getUrl());
0186                 }
0187             }
0188             if (languages.length == 0) {
0189                 QedeqLog.getInstance().logMessage("no supported language found, assuming 'en'");
0190                 final String result = generateLatex(call, "en""1").toString();
0191                 QedeqLog.getInstance().logSuccessfulReply(
0192                     "LaTeX for language \"en"
0193                     "\" was generated into \"" + result + "\"", getKernelQedeqBo().getUrl());
0194             }
0195         catch (final SourceFileExceptionList e) {
0196             final String msg = "Generation failed";
0197             Trace.fatal(CLASS, this, method, msg, e);
0198             QedeqLog.getInstance().logFailureReply(msg, getKernelQedeqBo().getUrl(), e.getMessage());
0199         catch (IOException e) {
0200             final String msg = "Generation failed";
0201             Trace.fatal(CLASS, this, method, msg, e);
0202             QedeqLog.getInstance().logFailureReply(msg, getKernelQedeqBo().getUrl(), e.getMessage());
0203         catch (final RuntimeException e) {
0204             Trace.fatal(CLASS, this, method, "unexpected problem", e);
0205             QedeqLog.getInstance().logFailureReply(
0206                 "Generation failed", getKernelQedeqBo().getUrl()"unexpected problem: "
0207                 (e.getMessage() != null ? e.getMessage() : e.toString()));
0208         }
0209         return null;
0210     }
0211 
0212     /**
0213      * Get an input stream for the LaTeX creation.
0214      *
0215      @param   call        This process executes us.
0216      @param   language    Filter text to get and produce text in this language only.
0217      @param   level       Filter for this detail level. LATER mime 20050205: not supported
0218      *                      yet.
0219      @return  Resulting LaTeX.
0220      @throws  SourceFileExceptionList Major problem occurred.
0221      @throws  IOException File IO failed.
0222      */
0223     public InputStream createLatex(final InternalModuleServiceCall call, final String language, final String level)
0224             throws SourceFileExceptionList, IOException {
0225         return new FileInputStream(generateLatex(call, language, level));
0226     }
0227 
0228     /**
0229      * Gives a LaTeX representation of given QEDEQ module as InputStream.
0230      *
0231      @param   call        This process executes us.
0232      @param   language    Filter text to get and produce text in this language only.
0233      *                      <code>null</code> is ok.
0234      @param   level       Filter for this detail level. LATER mime 20050205: not supported
0235      *                      yet.
0236      @return  Resulting LaTeX.
0237      @throws  SourceFileExceptionList Major problem occurred.
0238      @throws  IOException     File IO failed.
0239      */
0240     public File generateLatex(final InternalModuleServiceCall call, final String language, final String level)
0241             throws SourceFileExceptionList, IOException {
0242         final String method = "generateLatex(String, String)";
0243         this.language = language;
0244 //        this.level = level;
0245         // first we try to get more information about required modules and their predicates..
0246         try {
0247             getServices().loadRequiredModules(call.getInternalServiceProcess(), getKernelQedeqBo());
0248             getServices().checkWellFormedness(call.getInternalServiceProcess(), getKernelQedeqBo());
0249         catch (Exception e) {
0250             // we continue and ignore external predicates
0251             Trace.trace(CLASS, method, e);
0252         }
0253         String tex = getKernelQedeqBo().getModuleAddress().getFileName();
0254         if (tex.toLowerCase(Locale.US).endsWith(".xml")) {
0255             tex = tex.substring(0, tex.length() 4);
0256         }
0257         if (language != null && language.length() 0) {
0258             tex = tex + "_" + language;
0259         }
0260         // the destination is the configured destination directory plus the (relative)
0261         // localized file (or path) name
0262         File destination = new File(getServices().getConfig()
0263             .getGenerationDirectory(), tex + ".tex").getCanonicalFile();
0264 
0265         init();
0266 
0267         try {
0268             // TODO 20110204 m31: here we should choose the correct encoding; perhaps GUI configurable?
0269             if ("de".equals(language)) {
0270                 printer = new TextOutput(getKernelQedeqBo().getName()new FileOutputStream(destination),
0271                     "ISO-8859-1") {
0272                     public void append(final String txt) {
0273                         super.append(escapeUmlauts(txt));
0274                     }
0275                 };
0276             else {
0277                 printer = new TextOutput(getKernelQedeqBo().getName()new FileOutputStream(destination),
0278                     "UTF-8") {
0279                     public void append(final String txt) {
0280                         super.append(escapeUmlauts(txt));
0281                     }
0282                 };
0283             }
0284             traverse(call.getInternalServiceProcess());
0285         finally {
0286             getKernelQedeqBo().addPluginErrorsAndWarnings(getPlugin(), getErrorList(), getWarningList());
0287             if (printer != null) {
0288                 printer.flush();
0289                 printer.close();
0290             }
0291         }
0292         if (printer != null && printer.checkError()) {
0293             throw printer.getError();
0294         }
0295         try {
0296             QedeqBoDuplicateLanguageChecker.check(call);
0297         catch (SourceFileExceptionList warnings) {
0298             getKernelQedeqBo().addPluginErrorsAndWarnings(getPlugin(), null, warnings);
0299         }
0300         return destination.getCanonicalFile();
0301     }
0302 
0303     /**
0304      * Reset counters and other variables. Should be executed before {@link #traverse()}.
0305      */
0306     protected void init() {
0307         id = null;
0308         title = null;
0309         subContext = "";
0310     }
0311 
0312     public final void visitEnter(final Qedeq qedeq) {
0313         printer.println("% -*- TeX"
0314             (language != null ":" + language.toUpperCase(Locale.US""" -*-");
0315         printer.println("%%% ====================================================================");
0316         printer.println("%%% @LaTeX-file    " + printer.getName());
0317         printer.println("%%% Generated from " + getKernelQedeqBo().getModuleAddress());
0318         printer.println("%%% Generated at   " + DateUtility.getTimestamp());
0319         printer.println("%%% ====================================================================");
0320         printer.println();
0321         printer.println(
0322             "%%% Permission is granted to copy, distribute and/or modify this document");
0323         printer.println("%%% under the terms of the GNU Free Documentation License, Version 1.2");
0324         printer.println("%%% or any later version published by the Free Software Foundation;");
0325         printer.println(
0326             "%%% with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.");
0327         printer.println();
0328         printer.println("\\documentclass[a4paper,german,10pt,twoside]{book}");
0329         if ("de".equals(language)) {
0330             printer.println("\\usepackage[german]{babel}");
0331         else {
0332             if (!"en".equals(language)) {
0333                 printer.println("%%% TODO unknown language: " + language);
0334             }
0335             printer.println("\\usepackage[english]{babel}");
0336         }
0337         printer.println("\\usepackage{makeidx}");
0338         printer.println("\\usepackage{amsmath,amsthm,amssymb}");
0339         printer.println("\\usepackage{color}");
0340         printer.println("\\usepackage{xr}");
0341         printer.println("\\usepackage{tabularx}");
0342 //        printer.println("\\usepackage{epsfig,longtable}");
0343 //        printer.println("\\usepackage{ltabptch}");    // not installed on our server
0344         printer.println("\\usepackage[bookmarks=true,bookmarksnumbered,bookmarksopen,");
0345         printer.println("   unicode=true,colorlinks=true,linkcolor=webgreen,");
0346         printer.println("   pagebackref=true,pdfnewwindow=true,pdfstartview=FitH]{hyperref}");
0347         printer.println("\\definecolor{webgreen}{rgb}{0,.5,0}");
0348         printer.println("\\usepackage{epsfig,longtable}");
0349         printer.println("\\usepackage{graphicx}");
0350         printer.println("\\usepackage[all]{hypcap}");
0351         printer.println();
0352         if ("de".equals(language)) {
0353 // TODO m31 20100313: validate different counter types
0354 //            printer.println("\\newtheorem{thm}{Theorem}[chapter]");
0355             printer.println("\\newtheorem{thm}{Theorem}");
0356             printer.println("\\newtheorem{cor}[thm]{Korollar}");
0357             printer.println("\\newtheorem{lem}[thm]{Lemma}");
0358             printer.println("\\newtheorem{prop}[thm]{Proposition}");
0359             printer.println("\\newtheorem{ax}{Axiom}");
0360             printer.println("\\newtheorem{rul}{Regel}");
0361             printer.println();
0362             printer.println("\\theoremstyle{definition}");
0363             printer.println("\\newtheorem{defn}{Definition}");
0364             printer.println("\\newtheorem{idefn}[defn]{Initiale Definition}");
0365             printer.println();
0366             printer.println("\\theoremstyle{remark}");
0367             printer.println("\\newtheorem{rem}[thm]{Bemerkung}");
0368             printer.println("\\newtheorem*{notation}{Notation}");
0369         else {
0370             if (!"en".equals(language)) {
0371                 printer.println("%%% TODO unknown language: " + language);
0372             }
0373 // TODO m31 20100313: validate different counter types
0374 //            printer.println("\\newtheorem{thm}{Theorem}[chapter]");
0375             printer.println("\\newtheorem{thm}{Theorem}");
0376             printer.println("\\newtheorem{cor}[thm]{Corollary}");
0377             printer.println("\\newtheorem{lem}[thm]{Lemma}");
0378             printer.println("\\newtheorem{prop}[thm]{Proposition}");
0379             printer.println("\\newtheorem{ax}{Axiom}");
0380             printer.println("\\newtheorem{rul}{Rule}");
0381             printer.println();
0382             printer.println("\\theoremstyle{definition}");
0383             printer.println("\\newtheorem{defn}{Definition}");
0384             printer.println("\\newtheorem{idefn}[defn]{Initial Definition}");
0385             printer.println();
0386             printer.println("\\theoremstyle{remark}");
0387             printer.println("\\newtheorem{rem}[thm]{Remark}");
0388             printer.println("\\newtheorem*{notation}{Notation}");
0389         }
0390         printer.println();
0391         printer.println();
0392         printer.println("\\addtolength{\\textheight}{7\\baselineskip}");
0393         printer.println("\\addtolength{\\topmargin}{-5\\baselineskip}");
0394         printer.println();
0395         printer.println("\\setlength{\\parindent}{0pt}");
0396         printer.println();
0397         printer.println("\\frenchspacing \\sloppy");
0398         printer.println();
0399         printer.println("\\makeindex");
0400         printer.println();
0401         printer.println();
0402     }
0403 
0404     public final void visitLeave(final Qedeq qedeq) {
0405         printer.println("\\addcontentsline{toc}{chapter}{\\indexname} \\printindex");
0406         printer.println();
0407         printer.println("\\end{document}");
0408         printer.println();
0409     }
0410 
0411     public void visitEnter(final Header header) {
0412         final LatexList tit = header.getTitle();
0413         printer.print("\\title{");
0414         printer.print(getLatexListEntry("getTitle()", tit));
0415         printer.println("}");
0416         printer.println("\\author{");
0417         final AuthorList authors = getKernelQedeqBo().getQedeq().getHeader().getAuthorList();
0418         final StringBuffer authorList = new StringBuffer();
0419         for (int i = 0; i < authors.size(); i++) {
0420             if (i > 0) {
0421                 authorList.append(", ");
0422                 printer.println(", ");
0423             }
0424             final Author author = authors.get(i);
0425             final String name = author.getName().getLatex().trim();
0426             printer.print(name);
0427             authorList.append(name);
0428             String email = author.getEmail();
0429             if (email != null && email.trim().length() 0) {
0430                 authorList.append(" \\href{mailto:" + email + "}{" + email + "}");
0431             }
0432         }
0433         printer.println();
0434         printer.println("}");
0435         printer.println();
0436         printer.println("\\begin{document}");
0437         printer.println();
0438         printer.println("\\maketitle");
0439         printer.println();
0440         printer.println("\\setlength{\\parskip}{5pt plus 2pt minus 1pt}");
0441         printer.println("\\mbox{}");
0442         printer.println("\\vfill");
0443         printer.println();
0444         final String url = getKernelQedeqBo().getUrl();
0445         if (url != null && url.length() 0) {
0446             printer.println("\\par");
0447             if ("de".equals(language)) {
0448                 printer.println("Die Quelle f{\"ur} dieses Dokument ist hier zu finden:");
0449             else {
0450                 if (!"en".equals(language)) {
0451                     printer.println("%%% TODO unknown language: " + language);
0452                 }
0453                 printer.println("The source for this document can be found here:");
0454             }
0455             printer.println("\\par");
0456             printer.println("\\url{" + url + "}");
0457             printer.println();
0458         }
0459         {
0460             printer.println("\\par");
0461             if ("de".equals(language)) {
0462                 printer.println("Die vorliegende Publikation ist urheberrechtlich gesch{\"u}tzt.");
0463             else {
0464                 if (!"en".equals(language)) {
0465                     printer.println("%%% TODO unknown language: " + language);
0466                 }
0467                 printer.println("Copyright by the authors. All rights reserved.");
0468             }
0469         }
0470         final String email = header.getEmail();
0471         if (email != null && email.length() 0) {
0472             final String emailUrl = "\\href{mailto:" + email + "}{" + email + "}";
0473             printer.println("\\par");
0474             if ("de".equals(language)) {
0475                 printer.println("Bei Fragen, Anregungen oder Bitte um Aufnahme in die Liste der"
0476                     " abh\u00e4ngigen Module schicken Sie bitte eine EMail an die Adresse "
0477                     + emailUrl);
0478                 printer.println();
0479                 printer.println("\\par");
0480                 printer.println("Die Autoren dieses Dokuments sind:");
0481                 printer.println(authorList);
0482             else {
0483                 if (!"en".equals(language)) {
0484                     printer.println("%%% TODO unknown language: " + language);
0485                 }
0486                 printer.println("If you have any questions, suggestions or want to add something"
0487                     " to the list of modules that use this one, please send an email to the"
0488                     " address " + emailUrl);
0489                 printer.println();
0490                 printer.println("\\par");
0491                 printer.println("The authors of this document are:");
0492                 printer.println(authorList);
0493             }
0494             printer.println();
0495         }
0496     }
0497 
0498     public void visitLeave(final Header header) {
0499         printer.println();
0500         printer.println();
0501         printer.println("\\setlength{\\parskip}{0pt}");
0502         printer.println("\\tableofcontents");
0503         printer.println();
0504         printer.println("\\setlength{\\parskip}{5pt plus 2pt minus 1pt}");
0505         printer.println();
0506     }
0507 
0508     public void visitEnter(final ImportList importsthrows ModuleDataException {
0509         printer.println();
0510         printer.println();
0511         printer.println("\\par");
0512         if ("de".equals(language)) {
0513             printer.println("Benutzte QEDEQ module:");
0514         else {
0515             if (!"en".equals(language)) {
0516                 printer.println("%%% TODO unknown language: " + language);
0517             }
0518             printer.println("Used other QEDEQ modules:");
0519         }
0520         printer.println();
0521         printer.println("\\par");
0522         printer.println();
0523     }
0524 
0525     public void visitEnter(final Import impthrows ModuleDataException {
0526         printer.println();
0527         printer.println("\\par");
0528         printer.print("\\textbf{" + imp.getLabel() "} ");
0529         final Specification spec = imp.getSpecification();
0530         printer.print(getLatex(spec.getName()));
0531         if (spec.getLocationList() != null && spec.getLocationList().size() 0
0532                 && spec.getLocationList().get(0).getLocation().length() 0) {
0533             printer.print(" ");
0534             printer.print("\\url{" + getPdfLink((KernelQedeqBogetKernelQedeqBo()
0535                 .getLabels().getReferences().getQedeqBo(imp.getLabel())) "}");
0536         }
0537         printer.println();
0538     }
0539 
0540     /**
0541      * Get URL for QEDEQ XML module.
0542      *
0543      @param   address         Current module address.
0544      @param   specification   Find URL for this location list.
0545      @return  URL or <code>""</code> if none (valid?) was found.
0546      */
0547     private String getUrl(final ModuleAddress address, final Specification specification) {
0548         final LocationList list = specification.getLocationList();
0549         if (list == null || list.size() <= 0) {
0550             return "";
0551         }
0552         try {
0553             return address.getModulePaths(specification)[0].getUrl();
0554         catch (IOException e) {
0555             return "";
0556         }
0557     }
0558 
0559     public void visitEnter(final Chapter chapter) {
0560         // check if we print only brief and test for non text subnodes
0561         if (brief) {
0562             boolean hasFormalContent = false;
0563             do {
0564                 final SectionList sections = chapter.getSectionList();
0565                 if (sections == null) {
0566                     break;
0567                 }
0568                 for (int i = 0; i < sections.size() && !hasFormalContent; i++) {
0569                     final Section section = sections.get(i);
0570                     if (section == null) {
0571                         continue;
0572                     }
0573                     final SubsectionList subSections = section.getSubsectionList();
0574                     if (subSections == null) {
0575                         continue;
0576                     }
0577                     for (int j = 0; j < subSections.size(); j++) {
0578                         final SubsectionType subSection = subSections.get(j);
0579                         if (!(subSection instanceof Subsection)) {
0580                             hasFormalContent = true;
0581                             break;
0582                         }
0583                     }
0584                 }
0585             while (false);
0586             if (!hasFormalContent) {
0587                 setBlocked(true);
0588                 return;
0589             }
0590         }
0591         printer.print("\\chapter");
0592         if (chapter.getNoNumber() != null && chapter.getNoNumber().booleanValue()) {
0593             printer.print("*");
0594         }
0595         printer.print("{");
0596         printer.print(getLatexListEntry("getTitle()", chapter.getTitle()));
0597         final String chapterLabel = "chapter" + getCurrentNumbers().getAbsoluteChapterNumber();
0598         printer.println("} \\label{" + chapterLabel + "} \\hypertarget{" + chapterLabel + "}{}");
0599         if (chapter.getNoNumber() != null && chapter.getNoNumber().booleanValue()) {
0600             printer.println("\\addcontentsline{toc}{chapter}{"
0601                 + getLatexListEntry("getTitle()", chapter.getTitle()) "}");
0602         }
0603         printer.println();
0604         if (chapter.getIntroduction() != null && !brief) {
0605             printer.println(getLatexListEntry("getIntroduction()", chapter.getIntroduction()));
0606             printer.println();
0607         }
0608     }
0609 
0610     public void visitLeave(final Chapter chapter) {
0611         printer.println("%% end of chapter " + getLatexListEntry("getTitle()", chapter.getTitle()));
0612         printer.println();
0613         setBlocked(false);
0614     }
0615 
0616     public void visitLeave(final SectionList list) {
0617         printer.println();
0618     }
0619 
0620     public void visitEnter(final Section section) {
0621         // check if we print only brief and test for non text subnodes
0622         if (brief) {
0623             boolean hasFormalContent = false;
0624             do {
0625                 final SubsectionList subSections = section.getSubsectionList();
0626                 if (subSections == null) {
0627                     break;
0628                 }
0629                 for (int j = 0; j < subSections.size(); j++) {
0630                     final SubsectionType subSection = subSections.get(j);
0631                     if (!(subSection instanceof Subsection)) {
0632                         hasFormalContent = true;
0633                         break;
0634                     }
0635                 }
0636             while (false);
0637             if (!hasFormalContent) {
0638                 setBlocked(true);
0639                 return;
0640             }
0641         }
0642         printer.print("\\section");
0643         if (section.getNoNumber() != null && section.getNoNumber().booleanValue()) {
0644             printer.print("*");
0645         }
0646         printer.print("{");
0647         printer.print(getLatexListEntry("getTitle()", section.getTitle()));
0648         final String chapterLabel = "chapter" + getCurrentNumbers().getAbsoluteChapterNumber()
0649             "_section" + getCurrentNumbers().getAbsoluteSectionNumber();
0650         printer.println("} \\label{" + chapterLabel + "} \\hypertarget{" + chapterLabel + "}{}");
0651         if (section.getIntroduction() != null && !brief) {
0652             printer.println(getLatexListEntry("getIntroduction()", section.getIntroduction()));
0653             printer.println();
0654         }
0655     }
0656 
0657     public void visitLeave(final Section section) {
0658         setBlocked(false);
0659     }
0660 
0661     public void visitEnter(final Subsection subsection) {
0662 /* LATER mime 20070131: use this information?
0663         if (subsection.getId() != null) {
0664             printer.print(" id=\"" + subsection.getId() + "\"");
0665         }
0666         if (subsection.getLevel() != null) {
0667             printer.print(" level=\"" + subsection.getLevel() + "\"");
0668         }
0669 */
0670         if (brief) {
0671             return;
0672         }
0673         if (subsection.getTitle() != null) {
0674             printer.print("\\subsection{");
0675             printer.println(getLatexListEntry("getTitle()", subsection.getTitle()));
0676             printer.println("}");
0677         }
0678         if (subsection.getId() != null) {
0679             printer.println("\\label{" + subsection.getId() "} \\hypertarget{"
0680                 + subsection.getId() "}{}");
0681         }
0682         printer.println(getLatexListEntry("getLatex()", subsection.getLatex()));
0683     }
0684 
0685     public void visitLeave(final Subsection subsection) {
0686         if (brief) {
0687             return;
0688         }
0689         printer.println();
0690         printer.println();
0691     }
0692 
0693     public void visitEnter(final Node node) {
0694 /** TODO mime 20070131: level filter
0695         if (node.getLevel() != null) {
0696             printer.print(" level=\"" + node.getLevel() + "\"");
0697         }
0698 */
0699         if (node.getPrecedingText() != null && !brief) {
0700             printer.println("\\par");
0701             printer.println(getLatexListEntry("getPrecedingText()", node.getPrecedingText()));
0702             printer.println();
0703         }
0704         id = node.getId();
0705         title = null;
0706         if (node.getTitle() != null) {
0707             title = getLatexListEntry("getTitle()", node.getTitle());
0708         }
0709     }
0710 
0711     public void visitLeave(final Node node) {
0712         printer.println();
0713         if (node.getSucceedingText() != null && !brief) {
0714             printer.println(getLatexListEntry("getSucceedingText()", node.getSucceedingText()));
0715             printer.println();
0716         }
0717         printer.println();
0718     }
0719 
0720     public void visitEnter(final Axiom axiom) {
0721         printer.println("\\begin{ax}" (title != null "[" + title + "]" ""));
0722         printer.println("\\label{" + id + "} \\hypertarget{" + id + "}{}");
0723         if (info) {
0724             printer.println("{\\tt \\tiny [\\verb]" + id + "]]}");
0725         }
0726         printFormula(axiom.getFormula().getElement());
0727         printer.println(getLatexListEntry("getDescription()", axiom.getDescription()));
0728         printer.println("\\end{ax}");
0729     }
0730 
0731     public void visitEnter(final Proposition proposition) {
0732         printer.println("\\begin{prop}" (title != null "[" + title + "]" ""));
0733         printer.println("\\label{" + id + "} \\hypertarget{" + id + "}{}");
0734         if (info) {
0735             printer.println("{\\tt \\tiny [\\verb]" + id + "]]}");
0736         }
0737         printTopFormula(proposition.getFormula().getElement(), id);
0738         printer.println(getLatexListEntry("getDescription()", proposition.getDescription()));
0739         printer.println("\\end{prop}");
0740     }
0741 
0742     public void visitEnter(final Proof proof) {
0743 /* LATER mime 20070131: filter level and kind
0744         if (proof.getKind() != null) {
0745             printer.print(" kind=\"" + proof.getKind() + "\"");
0746         }
0747         if (proof.getLevel() != null) {
0748             printer.print(" level=\"" + proof.getLevel() + "\"");
0749         }
0750 */
0751         if (brief) {
0752             setBlocked(true);
0753             return;
0754         }
0755         printer.println("\\begin{proof}");
0756         printer.println(getLatexListEntry("getNonFormalProof()", proof.getNonFormalProof()));
0757         printer.println("\\end{proof}");
0758     }
0759 
0760     public void visitLeave(final Proof proof) {
0761         setBlocked(false);
0762     }
0763 
0764     public void visitEnter(final FormalProof proof) {
0765         if (brief) {
0766             setBlocked(true);
0767             return;
0768         }
0769         tabLevel = 0;
0770         printer.println("\\begin{proof}");
0771 //        if ("de".equals(language)) {
0772 //            printer.println("Beweis (formal):");
0773 //        } else {
0774 //            printer.println("Proof (formal):");
0775 //        }
0776     }
0777 
0778     public void visitEnter(final FormalProofLineList lines) {
0779         if (tabLevel == 0) {
0780             printer.println("\\mbox{}\\\\");
0781             printer.println("\\begin{longtable}[h!]{r@{\\extracolsep{\\fill}}p{9cm}@{\\extracolsep{\\fill}}p{4cm}}");
0782         }
0783     }
0784 
0785     public void visitLeave(final FormalProofLineList lines) {
0786         if (tabLevel == 0) {
0787             printer.println(" & & \\qedhere");
0788             printer.println("\\end{longtable}");
0789         }
0790     }
0791 
0792     public void visitEnter(final FormalProofLine line) {
0793         if (line.getLabel() != null) {
0794             label = line.getLabel();
0795         else {
0796             label = "";
0797         }
0798         if (line.getFormula() != null) {
0799             formula = "$" + getKernelQedeqBo().getElement2Latex().getLatex(line.getFormula().getElement()) "$";
0800         else {
0801             formula = "";
0802         }
0803         if (line.getReason() != null) {
0804             reason = line.getReason().toString();
0805         else {
0806             reason = "";
0807         }
0808     }
0809 
0810     public void visitLeave(final FormalProofLine line) {
0811         if (brief) {
0812             return;
0813         }
0814         linePrintln();
0815     }
0816 
0817     /**
0818      * Print proof line made out of label, formula and reason.
0819      */
0820     private void linePrintln() {
0821         if (formula.length() == && reason.length() == 0) {
0822             return;
0823         }
0824         if (label.length() 0) {
0825             String display = getNodeBo().getNodeVo().getId() "!" + label;
0826             printer.print("\\label{" + display + "} \\hypertarget{" + display
0827                 "}{\\mbox{(" + label + ")}} ");
0828         }
0829         printer.print(" \\ &  \\ ");
0830         for (int i = 0; i < tabLevel; i++) {
0831             printer.print("\\mbox{\\qquad}");
0832         }
0833         if (formula.length() 0) {
0834             printer.print(formula);
0835         }
0836         printer.print(" \\ &  \\ ");
0837         if (reason.length() 0) {
0838             printer.print("{\\tiny ");
0839             printer.print(reason);
0840             printer.print("}");
0841         }
0842         printer.println(" \\\\ ");
0843         reason = "";
0844         formula = "";
0845         label = "";
0846     }
0847 
0848     private String getReference(final String reference) {
0849         return getReference(reference, "getReference()");
0850     }
0851 
0852     private String getReference(final String reference, final String subContext) {
0853         final String context = getCurrentContext().getLocationWithinModule();
0854         try {
0855             getCurrentContext().setLocationWithinModule(context + "." + subContext);
0856             return (getReference(reference, null, null));
0857         finally {
0858             getCurrentContext().setLocationWithinModule(context);
0859         }
0860     }
0861 
0862     public void visitEnter(final ModusPonens rthrows ModuleDataException {
0863         if (brief) {
0864             return;
0865         }
0866         reason = getRuleReference(r.getName());
0867         boolean one = false;
0868         if (r.getReference1() != null) {
0869             reason += " " + getReference(r.getReference1()"getReference1()");
0870             one = true;
0871         }
0872         if (r.getReference1() != null) {
0873             if (one) {
0874                 reason += ",";
0875             }
0876             reason += " " + getReference(r.getReference2()"getReference2()");
0877         }
0878     }
0879 
0880     public void visitEnter(final Add rthrows ModuleDataException {
0881         if (brief) {
0882             return;
0883         }
0884         reason = getRuleReference(r.getName());
0885         if (r.getReference() != null) {
0886             reason += " " + getReference(r.getReference());
0887         }
0888     }
0889 
0890     public void visitEnter(final Rename rthrows ModuleDataException {
0891         if (brief) {
0892             return;
0893         }
0894         reason = getRuleReference(r.getName());
0895         if (r.getOriginalSubjectVariable() != null) {
0896             reason += " $" + getKernelQedeqBo().getElement2Latex().getLatex(
0897                 r.getOriginalSubjectVariable()) "$";
0898         }
0899         if (r.getReplacementSubjectVariable() != null) {
0900             reason += " by $" + getKernelQedeqBo().getElement2Latex().getLatex(
0901                 r.getReplacementSubjectVariable()) "$";
0902         }
0903         if (r.getReference() != null) {
0904             reason += " in " + getReference(r.getReference());
0905         }
0906     }
0907 
0908     public void visitEnter(final SubstFree rthrows ModuleDataException {
0909         if (brief) {
0910             return;
0911         }
0912         reason = getRuleReference(r.getName());
0913         if (r.getSubjectVariable() != null) {
0914             reason += " $" + getKernelQedeqBo().getElement2Latex().getLatex(
0915                 r.getSubjectVariable()) "$";
0916         }
0917         if (r.getSubstituteTerm() != null) {
0918             reason += " by $" + getKernelQedeqBo().getElement2Latex().getLatex(
0919                 r.getSubstituteTerm()) "$";
0920         }
0921         if (r.getReference() != null) {
0922             reason += " in " + getReference(r.getReference());
0923         }
0924     }
0925 
0926     public void visitEnter(final SubstFunc rthrows ModuleDataException {
0927         if (brief) {
0928             return;
0929         }
0930         reason = getRuleReference(r.getName());
0931         if (r.getFunctionVariable() != null) {
0932             reason += " $" + getKernelQedeqBo().getElement2Latex().getLatex(
0933                 r.getFunctionVariable()) "$";
0934         }
0935         if (r.getSubstituteTerm() != null) {
0936             reason += " by $" + getKernelQedeqBo().getElement2Latex().getLatex(
0937                 r.getSubstituteTerm()) "$";
0938         }
0939         if (r.getReference() != null) {
0940             reason += " in " + getReference(r.getReference());
0941         }
0942     }
0943 
0944     public void visitEnter(final SubstPred rthrows ModuleDataException {
0945         if (brief) {
0946             return;
0947         }
0948         reason = getRuleReference(r.getName());
0949         if (r.getPredicateVariable() != null) {
0950             reason += " $" + getKernelQedeqBo().getElement2Latex().getLatex(
0951                 r.getPredicateVariable()) "$";
0952         }
0953         if (r.getSubstituteFormula() != null) {
0954             reason += " by $" + getKernelQedeqBo().getElement2Latex().getLatex(
0955                 r.getSubstituteFormula()) "$";
0956         }
0957         if (r.getReference() != null) {
0958             reason += " in " + getReference(r.getReference());
0959         }
0960     }
0961 
0962     public void visitEnter(final Existential rthrows ModuleDataException {
0963         if (brief) {
0964             return;
0965         }
0966         reason = getRuleReference(r.getName());
0967         if (r.getSubjectVariable() != null) {
0968             reason += " with $" + getKernelQedeqBo().getElement2Latex().getLatex(
0969                 r.getSubjectVariable()) "$";
0970         }
0971         if (r.getReference() != null) {
0972             reason += " in " + getReference(r.getReference());
0973         }
0974     }
0975 
0976     public void visitEnter(final Universal rthrows ModuleDataException {
0977         if (brief) {
0978             return;
0979         }
0980         reason = getRuleReference(r.getName());
0981         if (r.getSubjectVariable() != null) {
0982             reason += " with $" + getKernelQedeqBo().getElement2Latex().getLatex(
0983                 r.getSubjectVariable()) "$";
0984         }
0985         if (r.getReference() != null) {
0986             reason += " in " + getReference(r.getReference());
0987         }
0988     }
0989 
0990     public void visitEnter(final ConditionalProof rthrows ModuleDataException {
0991         if (brief) {
0992             return;
0993         }
0994         reason = getRuleReference(r.getName());
0995         printer.print(" \\ &  \\ ");
0996         for (int i = 0; i < tabLevel; i++) {
0997             printer.print("\\mbox{\\qquad}");
0998         }
0999         printer.println("Conditional Proof");
1000         printer.print(" \\ &  \\ ");
1001         printer.println(" \\\\ ");
1002         tabLevel++;
1003     }
1004 
1005     public void visitLeave(final ConditionalProof proof) {
1006         if (brief) {
1007             return;
1008         }
1009         tabLevel--;
1010     }
1011 
1012     public void visitEnter(final Hypothesis hypothesis) {
1013         if (brief) {
1014             return;
1015         }
1016         reason = "Hypothesis";
1017         if (hypothesis.getLabel() != null) {
1018             label = hypothesis.getLabel();
1019         }
1020         if (hypothesis.getFormula() != null) {
1021             formula = "$" + getKernelQedeqBo().getElement2Latex().getLatex(
1022                 hypothesis.getFormula().getElement()) "$";
1023         }
1024     }
1025 
1026     public void visitLeave(final Hypothesis hypothesis) {
1027         if (brief) {
1028             return;
1029         }
1030         linePrintln();
1031     }
1032 
1033     public void visitEnter(final Conclusion conclusion) {
1034         if (brief) {
1035             return;
1036         }
1037         tabLevel--;
1038         reason = "Conclusion";
1039         if (conclusion.getLabel() != null) {
1040             label = conclusion.getLabel();
1041         }
1042         if (conclusion.getFormula() != null) {
1043             formula = "$" + getKernelQedeqBo().getElement2Latex().getLatex(
1044                     conclusion.getFormula().getElement()) "$";
1045         }
1046     }
1047 
1048     public void visitLeave(final Conclusion conclusion) {
1049         if (brief) {
1050             return;
1051         }
1052         linePrintln();
1053         tabLevel++;
1054     }
1055 
1056     public void visitLeave(final FormalProof proof) {
1057         if (!getBlocked()) {
1058             printer.println("\\end{proof}");
1059         }
1060         setBlocked(false);
1061     }
1062 
1063     public void visitEnter(final InitialPredicateDefinition definition) {
1064         printer.println("\\begin{idefn}" (title != null "[" + title + "]" ""));
1065         printer.println("\\label{" + id + "} \\hypertarget{" + id + "}{}");
1066         if (info) {
1067             printer.println("{\\tt \\tiny [\\verb]" + id + "]]}");
1068         }
1069         printer.print("$$");
1070         printer.println(getLatex(definition.getPredCon()));
1071         printer.println("$$");
1072         printer.println(getLatexListEntry("getDescription()", definition.getDescription()));
1073         printer.println("\\end{idefn}");
1074     }
1075 
1076     public void visitEnter(final PredicateDefinition definition) {
1077         printer.println("\\begin{defn}" (title != null "[" + title + "]" ""));
1078         printer.println("\\label{" + id + "} \\hypertarget{" + id + "}{}");
1079         if (info) {
1080             printer.println("{\\tt \\tiny [\\verb]" + id + "]]}");
1081         }
1082         printer.print("$$");
1083         printer.print(getLatex(definition.getFormula().getElement()));
1084         printer.println("$$");
1085         printer.println(getLatexListEntry("getDescription()", definition.getDescription()));
1086         printer.println("\\end{defn}");
1087     }
1088 
1089     public void visitEnter(final InitialFunctionDefinition definition) {
1090         printer.println("\\begin{idefn}" (title != null "[" + title + "]" ""));
1091         printer.println("\\label{" + id + "} \\hypertarget{" + id + "}{}");
1092         if (info) {
1093             printer.println("{\\tt \\tiny [\\verb]" + id + "]]}");
1094         }
1095         printer.print("$$");
1096         printer.print(getLatex(definition.getFunCon()));
1097         printer.println("$$");
1098         printer.println(getLatexListEntry("getDescription()", definition.getDescription()));
1099         printer.println("\\end{defn}");
1100     }
1101 
1102     public void visitEnter(final FunctionDefinition definition) {
1103         printer.println("\\begin{defn}" (title != null "[" + title + "]" ""));
1104         printer.println("\\label{" + id + "} \\hypertarget{" + id + "}{}");
1105         if (info) {
1106             printer.println("{\\tt \\tiny [\\verb]" + id + "]]}");
1107         }
1108         printer.print("$$");
1109         printer.print(getLatex(definition.getFormula().getElement()));
1110         printer.println("$$");
1111         printer.println("\\end{defn}");
1112     }
1113 
1114     public void visitLeave(final FunctionDefinition definition) {
1115         // nothing to do
1116     }
1117 
1118     public void visitEnter(final Rule rule) {
1119         printer.println("\\begin{rul}" (title != null "[" + title + "]" ""));
1120         printer.println("\\label{" + id + "} \\hypertarget{" + id + "}{}");
1121         if (info) {
1122             printer.println("{\\tt \\tiny [\\verb]" + id + "]]}");
1123         }
1124         printer.println();
1125         printer.println("\\par");
1126         printer.println("{\\em "
1127             (rule.getName() != null "  Name: \\verb]" + rule.getName() "]" "")
1128             (rule.getVersion() != null "  -  Version: \\verb]" + rule.getVersion() "]" "")
1129             "}");
1130         printer.println();
1131         printer.println();
1132         printer.println(getLatexListEntry("getDescription()", rule.getDescription()));
1133         printer.println("\\end{rul}");
1134     }
1135 
1136     public void visitLeave(final Rule rule) {
1137         // nothing to do
1138     }
1139 
1140     public void visitEnter(final LinkList linkList) {
1141         if (linkList.size() <= 0) {
1142             return;
1143         }
1144         if ("de".equals(language)) {
1145             printer.println("Basierend auf: ");
1146         else {
1147             if (!"en".equals(language)) {
1148                 printer.println("%%% TODO unknown language: " + language);
1149             }
1150             printer.println("Based on: ");
1151         }
1152         for (int i = 0; i < linkList.size(); i++) {
1153             if (linkList.get(i!= null) {
1154                 printer.print(" " + getReference(linkList.get(i)"get(" + i + ")"));
1155             }
1156         };
1157         printer.println();
1158     }
1159 
1160     public void visitEnter(final ChangedRuleList list) {
1161         if (list.size() <= 0) {
1162             return;
1163         }
1164         if ("de".equals(language)) {
1165             printer.println("Die folgenden Regeln m\u00fcssen erweitert werden.");
1166         else {
1167             if (!"en".equals(language)) {
1168                 printer.println("%%% TODO unknown language: " + language);
1169             }
1170             printer.println("The following rules have to be extended.");
1171         }
1172         printer.println();
1173     }
1174 
1175     public void visitEnter(final ChangedRule rule) {
1176         printer.println("\\par");
1177         printer.println("\\label{" + id + "!" + rule.getName() "} \\hypertarget{" + id + "!"
1178                 + rule.getName() "}{}");
1179         printer.print("{\\em "
1180             (rule.getName() != null "  Name: \\verb]" + rule.getName() "]" "")
1181             (rule.getVersion() != null "  -  Version: \\verb]" + rule.getVersion() "]" ""));
1182         RuleKey old = getLocalRuleKey(rule.getName());
1183         if (old == null && getKernelQedeqBo().getExistenceChecker() != null) {
1184             old = getKernelQedeqBo().getExistenceChecker().getParentRuleKey(rule.getName());
1185         }
1186         if (old != null) {
1187             printer.print("  -  Old Version: "
1188                 + getRuleReference(rule.getName(), old.getVersion()));
1189         }
1190         printer.println("}");
1191         rule.getName();
1192         printer.println();
1193         if (rule.getDescription() != null) {
1194             printer.println(getLatexListEntry("getDescription()", rule.getDescription()));
1195             printer.println();
1196             printer.println();
1197         }
1198     }
1199 
1200 
1201     public void visitEnter(final LiteratureItemList list) {
1202         printer.println("\\backmatter");
1203         printer.println();
1204         printer.println("\\begin{thebibliography}{99}");
1205         if ("de".equals(language)) {
1206             printer.println("\\addcontentsline{toc}{chapter}{Literaturverzeichnis}");
1207         else {
1208             if (!"en".equals(language)) {
1209                 printer.println("%%% TODO unknown language: " + language);
1210             }
1211             printer.println("\\addcontentsline{toc}{chapter}{Bibliography}");
1212         }
1213         final ImportList imports = getKernelQedeqBo().getQedeq().getHeader().getImportList();
1214         if (imports != null && imports.size() 0) {
1215             printer.println();
1216             printer.println();
1217             printer.println("%% Used other QEDEQ modules:");
1218             for (int i = 0; i < imports.size(); i++) {
1219                 final Import imp = imports.get(i);
1220                 printer.print("\\bibitem{" + imp.getLabel() "} ");
1221                 final Specification spec = imp.getSpecification();
1222                 printer.print(getLatex(spec.getName()));
1223                 if (spec.getLocationList() != null && spec.getLocationList().size() 0
1224                         && spec.getLocationList().get(0).getLocation().length() 0) {
1225                     printer.print(" ");
1226                     // TODO m31 20070205, 2010727: later on here must stand the location that was used
1227                     //   to verify the document contents.
1228                     //   Also get other informations like authors, title, etc.
1229                     //   It might also be better to link to URL?
1230 //                    printer.print("\\url{" + getUrl(getQedeqBo().getModuleAddress(), spec) + "}");
1231                     printer.print("\\url{" + getPdfLink((KernelQedeqBogetKernelQedeqBo()
1232                         .getLabels().getReferences().getQedeqBo(imp.getLabel())) "}");
1233                 }
1234                 printer.println();
1235             }
1236             printer.println();
1237             printer.println();
1238             printer.println("%% Other references:");
1239             printer.println();
1240         }
1241     }
1242 
1243     public void visitLeave(final LiteratureItemList list) {
1244         final UsedByList usedby = getKernelQedeqBo().getQedeq().getHeader().getUsedByList();
1245         if (usedby != null && usedby.size() 0) {
1246             printer.println();
1247             printer.println();
1248             printer.println("%% QEDEQ modules that use this one:");
1249             for (int i = 0; i < usedby.size(); i++) {
1250                 final Specification spec = usedby.get(i);
1251                 printer.print("\\bibitem{" + spec.getName() "} ");
1252                 printer.print(getLatex(spec.getName()));
1253                 final String url = getUrl(getKernelQedeqBo().getModuleAddress(), spec);
1254                 if (url != null && url.length() 0) {
1255                     printer.print(" ");
1256                     printer.print("\\url{" + url + "}");
1257                 }
1258                 printer.println();
1259             }
1260             printer.println();
1261             printer.println();
1262         }
1263         printer.println("\\end{thebibliography}");
1264     }
1265 
1266     public void visitEnter(final LiteratureItem item) {
1267         printer.print("\\bibitem{" + item.getLabel() "} ");
1268         printer.println(getLatexListEntry("getItem()", item.getItem()));
1269         printer.println();
1270     }
1271 
1272     /**
1273      * Print top level formula. If the formula has the form <code>AND(.., .., ..)</code> the
1274      * formula is broken down in several labeled lines.
1275      *
1276      @param   element     Formula to print.
1277      @param   mainLabel   Main formula label.
1278      */
1279     private void printTopFormula(final Element element, final String mainLabel) {
1280         if (!element.isList() || !element.getList().getOperator().equals("AND")) {
1281             printFormula(element);
1282             return;
1283         }
1284         final ElementList list = element.getList();
1285         printer.println("\\mbox{}");
1286         printer.println("\\begin{longtable}{{@{\\extracolsep{\\fill}}p{0.9\\linewidth}l}}");
1287         for (int i = 0; i < list.size(); i++)  {
1288             String newLabel = "";
1289             if (list.size() >= ALPHABET.length() * ALPHABET.length()) {
1290                 newLabel = "" (i + 1);
1291             else {
1292                 // TODO 20110303 m31: this dosn't work if we have more than 26 * 26 elements
1293                 if (list.size() > ALPHABET.length()) {
1294                     final int div = (i / ALPHABET.length());
1295                     newLabel = "" + ALPHABET.charAt(div);
1296                 }
1297                 newLabel += ALPHABET.charAt(i % ALPHABET.length());
1298             }
1299 //            final String label = (i < ALPHABET.length() ? "" + ALPHABET .charAt(i) : "" + i);
1300             printer.println("\\centering $" + getLatex(list.getElement(i)) "$"
1301                 " & \\label{" + mainLabel + "/" + newLabel + "} \\hypertarget{" + mainLabel + "/"
1302                 + newLabel + "}{} \\mbox{\\emph{(" + newLabel + ")}} "
1303                 (i + < list.size() "\\\\" ""));
1304         }
1305         printer.println("\\end{longtable}");
1306     }
1307 
1308     /**
1309      * Print formula.
1310      *
1311      @param   element Formula to print.
1312      */
1313     private void printFormula(final Element element) {
1314         printer.println("\\mbox{}");
1315         printer.println("\\begin{longtable}{{@{\\extracolsep{\\fill}}p{\\linewidth}}}");
1316         printer.println("\\centering $" + getLatex(element"$");
1317         printer.println("\\end{longtable}");
1318     }
1319 
1320     /**
1321      * Get LaTeX element presentation.
1322      *
1323      @param   element    Print this element.
1324      @return  LaTeX form of element.
1325      */
1326     private String getLatex(final Element element) {
1327         return getKernelQedeqBo().getElement2Latex().getLatex(element);
1328     }
1329 
1330     /**
1331      * Filters correct entry out of LaTeX list. Filter criterion is for example the correct
1332      * language.
1333      * TODO mime 20050205: filter level too?
1334      *
1335      @param   method  This method was called. Used to get the correct sub context.
1336      *                  Should not be null. If it is empty the <code>subContext</code>
1337      *                  is not changed.
1338      @param   list    List of LaTeX texts.
1339      @return  Filtered text.
1340      */
1341     private String getLatexListEntry(final String method, final LatexList list) {
1342         if (list == null) {
1343             return "";
1344         }
1345         if (method.length() 0) {
1346             subContext = method;
1347         }
1348         try {
1349             for (int i = 0; language != null && i < list.size(); i++) {
1350                 if (language.equals(list.get(i).getLanguage())) {
1351                     if (method.length() 0) {
1352                         subContext = method + ".get(" + i + ")";
1353                     }
1354                     return getLatex(list.get(i));
1355                 }
1356             }
1357             // OK, we didn't found the language, so we take the default language
1358             final String def = getKernelQedeqBo().getOriginalLanguage();
1359             for (int i = 0; i < list.size(); i++) {
1360                 if (EqualsUtility.equals(def, list.get(i).getLanguage())) {
1361                     if (method.length() 0) {
1362                         subContext = method + ".get(" + i + ")";
1363                     }
1364                     return "MISSING! OTHER: " + getLatex(list.get(i));
1365                 }
1366             }
1367             // OK, we didn't find wanted and default language, so we take the first non empty one
1368             for (int i = 0; i < list.size(); i++) {
1369                 if (method.length() 0) {
1370                     subContext = method + ".get(" + i + ")";
1371                 }
1372                 if (null != list.get(i&& null != list.get(i).getLatex()
1373                         && list.get(i).getLatex().trim().length() 0) {
1374                     return "MISSING! OTHER: " + getLatex(list.get(i));
1375                 }
1376             }
1377             return "MISSING!";
1378         finally {
1379             if (method.length() 0) {
1380                 subContext = "";
1381             }
1382         }
1383     }
1384 
1385     /**
1386      * Get really LaTeX. Does some simple character replacements for umlauts. Also transforms
1387      <code>\qref{key}</code> into LaTeX.
1388      *
1389      @param   latex   Unescaped text.
1390      @return  Really LaTeX.
1391      */
1392     private String getLatex(final Latex latex) {
1393         if (latex == null || latex.getLatex() == null) {
1394             return "";
1395         }
1396         StringBuffer result = new StringBuffer(latex.getLatex());
1397 
1398         // LATER mime 20080324: check if LaTeX is correct and no forbidden tags are used
1399 
1400         transformQref(result);
1401 
1402         return deleteLineLeadingWhitespace(result.toString());
1403     }
1404 
1405     /**
1406      * Transform <code>\qref{key}</code> entries into common LaTeX code.
1407      *
1408      * LATER mime 20080324: write JUnitTests to be sure that no runtime exceptions are thrown if
1409      * reference is at end of latex etc.
1410      *
1411      @param   result  Work on this buffer.
1412      */
1413     private void transformQref(final StringBuffer result) {
1414         final String method = "transformQref(StringBuffer)";
1415         final StringBuffer buffer = new StringBuffer(result.toString());
1416         final TextInput input = new TextInput(buffer);
1417         int last = 0;
1418         try {
1419             result.setLength(0);
1420             while (input.forward("\\qref{")) {
1421                 final SourcePosition startPosition = input.getSourcePosition();
1422                 final int start = input.getPosition();
1423                 if (!input.forward("}")) {
1424                     addWarning(LatexErrorCodes.QREF_END_NOT_FOUND_CODE,
1425                         LatexErrorCodes.QREF_END_NOT_FOUND_TEXT, startPosition,
1426                         input.getSourcePosition());
1427                     continue;
1428                 }
1429                 String ref = input.getSubstring(start + "\\qref{".length(), input.getPosition()).trim();
1430                 input.read();   // read }
1431                 Trace.param(CLASS, this, method, "1 ref", ref);
1432                 if (ref.length() == 0) {
1433                     addWarning(LatexErrorCodes.QREF_EMPTY_CODE, LatexErrorCodes.QREF_EMPTY_TEXT,
1434                         startPosition, input.getSourcePosition());
1435                     continue;
1436                 }
1437                 if (ref.length() 1024) {
1438                     addWarning(LatexErrorCodes.QREF_END_NOT_FOUND_CODE,
1439                         LatexErrorCodes.QREF_END_NOT_FOUND_TEXT, startPosition,
1440                         input.getSourcePosition());
1441                     continue;
1442                 }
1443                 if (ref.indexOf("{">= 0) {
1444                     addWarning(LatexErrorCodes.QREF_END_NOT_FOUND_CODE,
1445                         LatexErrorCodes.QREF_END_NOT_FOUND_TEXT, startPosition,
1446                         input.getSourcePosition());
1447                     continue;
1448                 }
1449                 final int end = input.getPosition();
1450                 final SourcePosition endPosition = input.getSourcePosition();
1451                 result.append(buffer.substring(last, start));
1452                 result.append(getReference(ref, startPosition, endPosition));
1453                 last = end;
1454             }
1455         finally // thanks to findbugs
1456             IoUtility.close(input);
1457             if (last < buffer.length()) {
1458                 result.append(buffer.substring(last));
1459             }
1460         }
1461     }
1462 
1463     private String getReference(final String reference, final SourcePosition start, final SourcePosition end) {
1464         final String method = "getReference(String, String)";
1465         Trace.param(CLASS, this, method, "2 reference", reference);     // qreference within module
1466 
1467         final Reference ref = getReference(reference, getCurrentContext(start, end), true, false);
1468         if (ref.isNodeLocalReference() && ref.isSubReference()) {
1469             return "\\hyperlink{" + ref.getNodeLabel() "/" + ref.getSubLabel() "}{" "("
1470                 + ref.getSubLabel() ")" "}";
1471         }
1472 
1473         if (ref.isNodeLocalReference() && ref.isProofLineReference()) {
1474             return "\\hyperlink{" + ref.getNodeLabel() "!" + ref.getProofLineLabel() "}{" "("
1475                 + ref.getProofLineLabel() ")" "}";
1476         }
1477 
1478         if (!ref.isExternal()) {
1479             return "\\hyperlink{" + ref.getNodeLabel()
1480                 (ref.isSubReference() "/" + ref.getSubLabel() "")
1481                 (ref.isProofLineReference() "!" + ref.getProofLineLabel() "")
1482                 "}{"
1483                 + getNodeDisplay(ref.getNodeLabel(), ref.getNode())
1484                 (ref.isSubReference() " (" + ref.getSubLabel() ")" "")
1485                 (ref.isProofLineReference() " (" + ref.getProofLineLabel() ")" "")
1486                 "}";
1487         }
1488 
1489         // do we have an external module reference without node?
1490         if (ref.isExternalModuleReference()) {
1491             return "\\url{" + getPdfLink(ref.getExternalQedeq()) "}~\\cite{"
1492                 + ref.getExternalQedeqLabel() "}";
1493             // if we want to show the text "description": \href{my_url}{description}
1494         }
1495 
1496         String external = getPdfLink(ref.getExternalQedeq());
1497         if (external.startsWith("file://")) {
1498             external = "file:" + external.substring("file://".length());
1499         }
1500         return "\\hyperref{" +  external + "}{}{"
1501             + ref.getNodeLabel()
1502             (ref.isSubReference() "/" + ref.getSubLabel() "")
1503             (ref.isProofLineReference() "!" + ref.getProofLineLabel() "")
1504             "}{" + getNodeDisplay(ref.getNodeLabel(), ref.getNode())
1505                 (ref.isSubReference() " (" + ref.getSubLabel() ")" "")
1506                 (ref.isProofLineReference() " (" + ref.getProofLineLabel() ")" "")
1507             "}~\\cite{" + ref.getExternalQedeqLabel() "}";
1508     }
1509 
1510     private String getNodeDisplay(final String label, final KernelNodeBo kNode) {
1511         return StringUtility.replace(getNodeDisplay(label, kNode, language)" ""~");
1512     }
1513 
1514     private String getRuleReference(final String ruleName) {
1515         return getRuleReference(ruleName, ruleName);
1516     }
1517 
1518     private String getRuleReference(final String ruleName, final String caption) {
1519         final String method = "getRuleReference(String, String)";
1520         Trace.param(CLASS, this, method, "ruleName", ruleName);
1521         RuleKey key = getLocalRuleKey(ruleName);
1522         if (key == null && getKernelQedeqBo().getExistenceChecker() != null) {
1523             key = getKernelQedeqBo().getExistenceChecker().getParentRuleKey(ruleName);
1524         }
1525         if (key == null) {
1526             key = getKernelQedeqBo().getLabels().getRuleKey(ruleName);
1527         }
1528         KernelQedeqBo qedeq = getKernelQedeqBo();
1529         if (getKernelQedeqBo().getExistenceChecker() != null) {
1530             qedeq = getKernelQedeqBo().getExistenceChecker().getQedeq(key);
1531         }
1532         String localRef = getKernelQedeqBo().getLabels().getRuleLabel(key);
1533         final String refRuleName = qedeq.getLabels().getRule(key).getName();
1534         if (!ruleName.equals(refRuleName)) {
1535             localRef += "!" + ruleName;
1536         }
1537         qedeq.getLabels().getRule(key).getName();
1538         boolean local = getKernelQedeqBo().equals(qedeq);
1539         if (local) {
1540             return "\\hyperlink{" + localRef + "}{" + caption + "}";
1541         }
1542         String external = getPdfLink(qedeq);
1543         if (external.startsWith("file://")) {
1544             external = "file:" + external.substring("file://".length());
1545         }
1546         return "\\hyperref{" + external + "}{}{" + caption + "}{"
1547             + localRef + "}";
1548     }
1549 
1550     /**
1551      * Get current module context. Uses sub context information.
1552      *
1553      @param   startDelta  Skip position (relative to location start). Could be
1554      *                      <code>null</code>.
1555      @param   endDelta    Mark until this column (relative to location start).
1556      *                      be <code>null</code>
1557      @return  Current module context.
1558      */
1559     public ModuleContext getCurrentContext(final SourcePosition startDelta,
1560             final SourcePosition endDelta) {
1561         if (subContext.length() == 0) {
1562             return super.getCurrentContext();
1563         }
1564         final ModuleContext c = new ModuleContext(super.getCurrentContext().getModuleLocation(),
1565             super.getCurrentContext().getLocationWithinModule() "." + subContext,
1566             startDelta, endDelta);
1567         return c;
1568     }
1569 
1570 // TODO 20110214 m31: decide about removal
1571 //    public ModuleContext getCurrentContext() {
1572 //        throw new IllegalStateException("programming error");
1573 //    }
1574 
1575 
1576     /**
1577      * Add warning.
1578      *
1579      @param   code        Warning code.
1580      @param   msg         Warning message.
1581      @param   startDelta  Skip position (relative to location start). Could be
1582      *                      <code>null</code>.
1583      @param   endDelta    Mark until this column (relative to location start).
1584      *                      be <code>null</code>
1585      */
1586     private void addWarning(final int code, final String msg, final SourcePosition startDelta,
1587             final SourcePosition endDelta) {
1588         Trace.param(CLASS, this, "addWarning""msg", msg);
1589         addWarning(new LatexContentException(code, msg, getCurrentContext(startDelta, endDelta)));
1590     }
1591 
1592     /**
1593      * Get URL to for PDF version of module. If the referenced module doesn't
1594      * support the current language we switch to the original language.
1595      *
1596      @param   prop    Get URL for this QEDEQ module.
1597      @return  URL to PDF.
1598      */
1599     private String getPdfLink(final KernelQedeqBo prop) {
1600         if (prop == null) {
1601             return "";
1602         }
1603         final String url = prop.getUrl();
1604         final int dot = url.lastIndexOf(".");
1605         if (prop.isSupportedLanguage(language)) {
1606             return url.substring(0, dot"_" + language + ".pdf";
1607         }
1608         final String a = prop.getOriginalLanguage();
1609         return url.substring(0, dot(a.length() "_" + a : """.pdf";
1610     }
1611 
1612     /**
1613      * Get LaTeX from string. Escapes common characters.
1614      * Also gets rid of leading spaces if they are equal among the lines.
1615      *
1616      @param   text   Unescaped text.
1617      @return  LaTeX.
1618      */
1619     private String getLatex(final String text) {
1620         final StringBuffer buffer = new StringBuffer(text);
1621         StringUtility.replace(buffer, "\\""\\textbackslash");
1622         StringUtility.replace(buffer, "$""\\$");
1623         StringUtility.replace(buffer, "&""\\&");
1624         StringUtility.replace(buffer, "%""\\%");
1625         StringUtility.replace(buffer, "#""\\#");
1626         StringUtility.replace(buffer, "_""\\_");
1627         StringUtility.replace(buffer, "{""\\{");
1628         StringUtility.replace(buffer, "}""\\}");
1629         StringUtility.replace(buffer, "~""\\textasciitilde");
1630         StringUtility.replace(buffer, "^""\\textasciicircum");
1631         StringUtility.replace(buffer, "<""\\textless");
1632         StringUtility.replace(buffer, ">""\\textgreater");
1633         StringUtility.deleteLineLeadingWhitespace(buffer);
1634         return buffer.toString().trim();
1635     }
1636 
1637     /**
1638      * Trims text.  Also gets rid of leading spaces if they are equal among the lines.
1639      *
1640      @param   text   Text.
1641      @return  Untrimed text.
1642      */
1643     private String deleteLineLeadingWhitespace(final String text) {
1644         final StringBuffer buffer = new StringBuffer(text);
1645         StringUtility.deleteLineLeadingWhitespace(buffer);
1646         return buffer.toString().trim();
1647     }
1648 
1649     /**
1650      * Get really LaTeX. Does some simple character replacements for umlauts.
1651      * LATER mime 20050205: filter more than German umlauts
1652      *
1653      @param   nearlyLatex   Unescaped text.
1654      @return  Really LaTeX.
1655      */
1656     private String escapeUmlauts(final String nearlyLatex) {
1657         if (nearlyLatex == null) {
1658             return "";
1659         }
1660         final StringBuffer buffer = new StringBuffer(nearlyLatex);
1661 //        System.out.println("before");
1662 //        System.out.println(buffer);
1663 //        System.out.println();
1664 //        System.out.println("after");
1665 //        System.out.println(buffer);
1666 //        System.out.println("*******************************************************************");
1667         StringUtility.replace(buffer, "\u00fc""{\\\"u}");
1668         StringUtility.replace(buffer, "\u00f6""{\\\"o}");
1669         StringUtility.replace(buffer, "\u00e4""{\\\"a}");
1670         StringUtility.replace(buffer, "\u00dc""{\\\"U}");
1671         StringUtility.replace(buffer, "\u00d6""{\\\"O}");
1672         StringUtility.replace(buffer, "\u00c4""{\\\"A}");
1673         StringUtility.replace(buffer, "\u00df""{\\ss}");
1674         return buffer.toString();
1675     }
1676 
1677 }