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.unicode;
0017
0018 import java.io.IOException;
0019 import java.util.ArrayList;
0020 import java.util.List;
0021
0022 import org.apache.commons.lang.ArrayUtils;
0023 import org.qedeq.base.io.AbstractOutput;
0024 import org.qedeq.base.io.SourcePosition;
0025 import org.qedeq.base.io.TextOutput;
0026 import org.qedeq.base.trace.Trace;
0027 import org.qedeq.base.utility.DateUtility;
0028 import org.qedeq.base.utility.EqualsUtility;
0029 import org.qedeq.base.utility.StringUtility;
0030 import org.qedeq.kernel.bo.module.InternalServiceJob;
0031 import org.qedeq.kernel.bo.module.KernelNodeBo;
0032 import org.qedeq.kernel.bo.module.KernelQedeqBo;
0033 import org.qedeq.kernel.bo.module.Reference;
0034 import org.qedeq.kernel.bo.service.basis.ControlVisitor;
0035 import org.qedeq.kernel.se.base.list.Element;
0036 import org.qedeq.kernel.se.base.list.ElementList;
0037 import org.qedeq.kernel.se.base.module.Add;
0038 import org.qedeq.kernel.se.base.module.Author;
0039 import org.qedeq.kernel.se.base.module.AuthorList;
0040 import org.qedeq.kernel.se.base.module.Axiom;
0041 import org.qedeq.kernel.se.base.module.ChangedRule;
0042 import org.qedeq.kernel.se.base.module.ChangedRuleList;
0043 import org.qedeq.kernel.se.base.module.Chapter;
0044 import org.qedeq.kernel.se.base.module.Conclusion;
0045 import org.qedeq.kernel.se.base.module.ConditionalProof;
0046 import org.qedeq.kernel.se.base.module.Existential;
0047 import org.qedeq.kernel.se.base.module.FormalProof;
0048 import org.qedeq.kernel.se.base.module.FormalProofLine;
0049 import org.qedeq.kernel.se.base.module.Formula;
0050 import org.qedeq.kernel.se.base.module.FunctionDefinition;
0051 import org.qedeq.kernel.se.base.module.Header;
0052 import org.qedeq.kernel.se.base.module.Hypothesis;
0053 import org.qedeq.kernel.se.base.module.Import;
0054 import org.qedeq.kernel.se.base.module.ImportList;
0055 import org.qedeq.kernel.se.base.module.InitialFunctionDefinition;
0056 import org.qedeq.kernel.se.base.module.InitialPredicateDefinition;
0057 import org.qedeq.kernel.se.base.module.Latex;
0058 import org.qedeq.kernel.se.base.module.LatexList;
0059 import org.qedeq.kernel.se.base.module.LinkList;
0060 import org.qedeq.kernel.se.base.module.LiteratureItem;
0061 import org.qedeq.kernel.se.base.module.LiteratureItemList;
0062 import org.qedeq.kernel.se.base.module.LocationList;
0063 import org.qedeq.kernel.se.base.module.ModusPonens;
0064 import org.qedeq.kernel.se.base.module.Node;
0065 import org.qedeq.kernel.se.base.module.PredicateDefinition;
0066 import org.qedeq.kernel.se.base.module.Proof;
0067 import org.qedeq.kernel.se.base.module.Proposition;
0068 import org.qedeq.kernel.se.base.module.Qedeq;
0069 import org.qedeq.kernel.se.base.module.Rename;
0070 import org.qedeq.kernel.se.base.module.Rule;
0071 import org.qedeq.kernel.se.base.module.Section;
0072 import org.qedeq.kernel.se.base.module.SectionList;
0073 import org.qedeq.kernel.se.base.module.Specification;
0074 import org.qedeq.kernel.se.base.module.Subsection;
0075 import org.qedeq.kernel.se.base.module.SubsectionList;
0076 import org.qedeq.kernel.se.base.module.SubsectionType;
0077 import org.qedeq.kernel.se.base.module.SubstFree;
0078 import org.qedeq.kernel.se.base.module.SubstFunc;
0079 import org.qedeq.kernel.se.base.module.SubstPred;
0080 import org.qedeq.kernel.se.base.module.Universal;
0081 import org.qedeq.kernel.se.base.module.UsedByList;
0082 import org.qedeq.kernel.se.common.ModuleAddress;
0083 import org.qedeq.kernel.se.common.ModuleContext;
0084 import org.qedeq.kernel.se.common.ModuleDataException;
0085 import org.qedeq.kernel.se.common.ModuleService;
0086 import org.qedeq.kernel.se.common.SourceFileExceptionList;
0087 import org.qedeq.kernel.se.visitor.QedeqNumbers;
0088
0089
0090 /**
0091 * Transfer a QEDEQ module into unicode text.
0092 * <p>
0093 * <b>This is just a quick written generator. This class just generates some text output to be able
0094 * to get a visual impression of a QEDEQ module.</b>
0095 *
0096 * @author Michael Meyling
0097 */
0098 public class Qedeq2UnicodeVisitor extends ControlVisitor implements ReferenceFinder {
0099
0100 /** This class. */
0101 private static final Class CLASS = Qedeq2UnicodeVisitor.class;
0102
0103 /** Output goes here. */
0104 private AbstractOutput printer;
0105
0106 /** Filter text to get and produce text in this language. */
0107 private String language;
0108
0109 /** Filter for this detail level. */
0110 // private String level;
0111
0112 /** Should additional information be put into LaTeX output? E.g. QEDEQ reference names. */
0113 private final boolean info;
0114
0115 /** Current node id. */
0116 private String id;
0117
0118 /** Current node title. */
0119 private String title;
0120
0121 /** Sub context like "getIntroduction()". */
0122 private String subContext = "";
0123
0124 /** Maximum column number. If zero no line breaking is done automatically. */
0125 private int maxColumns;
0126
0127 /** Should warning messages be generated if LaTeX problems occur? */
0128 private boolean addWarnings;
0129
0130 /** Should only names and formulas be be printed? */
0131 private final boolean brief;
0132
0133 /** Alphabet for tagging. */
0134 private static final String ALPHABET = "abcdefghijklmnopqrstuvwxyz";
0135
0136 /** Printing data for a single formal proof line. */
0137 private ProofLineData lineData = new ProofLineData();
0138
0139 /** This is the maximal formula width. All proof line formulas that are bigger are wrapped. */
0140 private int formulaWidth = 60;
0141
0142 /** This is the maximal reason width. All proof line reasons that are bigger are wrapped. */
0143 private int reasonWidth = 35;
0144
0145 /** Tabulation string. */
0146 private String tab = "";
0147
0148 /**
0149 * Constructor.
0150 *
0151 * @param plugin This plugin we work for.
0152 * @param prop QEDEQ BO object.
0153 * @param info Write reference info?
0154 * @param maximumColumn Maximum column before automatic break.
0155 * 0 means no automatic break.
0156 * @param addWarnings Should warning messages be generated
0157 * if LaTeX problems occur?
0158 * @param brief Should only names and formulas be be printed?
0159 */
0160 public Qedeq2UnicodeVisitor(final ModuleService plugin, final KernelQedeqBo prop,
0161 final boolean info, final int maximumColumn, final boolean addWarnings,
0162 final boolean brief) {
0163 super(plugin, prop);
0164 this.info = info;
0165 this.maxColumns = maximumColumn;
0166 this.addWarnings = addWarnings;
0167 this.brief = brief;
0168 }
0169
0170 /**
0171 * Gives a UTF-8 representation of given QEDEQ module as InputStream.
0172 *
0173 * @param process We run in this process.
0174 * @param printer Print herein.
0175 * @param language Filter text to get and produce text in this language only.
0176 * @param level Filter for this detail level. LATER 20100205 m31: not yet supported
0177 * yet.
0178 * @throws SourceFileExceptionList Major problem occurred.
0179 * @throws IOException File IO failed.
0180 */
0181 public void generateUtf8(final InternalServiceJob process, final AbstractOutput printer,
0182 final String language, final String level) throws SourceFileExceptionList, IOException {
0183 setParameters(printer, language);
0184 try {
0185 traverse(process);
0186 } finally {
0187 getKernelQedeqBo().addPluginErrorsAndWarnings((ModuleService) getService(), getErrorList(),
0188 getWarningList());
0189 }
0190 }
0191
0192 /**
0193 * Set parameters.
0194 *
0195 * @param printer Print herein.
0196 * @param language Choose this language.
0197 */
0198 public void setParameters(final AbstractOutput printer,
0199 final String language) {
0200 this.printer = printer;
0201 this.printer.setColumns(maxColumns);
0202 // TODO 20110208 m31: perhaps we should have some config parameters for those percentage splittings
0203 if (maxColumns <= 0) {
0204 formulaWidth = 80;
0205 reasonWidth = 50;
0206 } else if (maxColumns <= 50) {
0207 this.printer.setColumns(50);
0208 formulaWidth = 21;
0209 reasonWidth = 21;
0210 } else if (maxColumns <= 100) {
0211 formulaWidth = (maxColumns - 8) * 50 / 100;
0212 reasonWidth = (maxColumns - 8) * 50 / 100;
0213 } else if (maxColumns <= 120) {
0214 reasonWidth = 46 + (maxColumns - 100) / 5;
0215 formulaWidth = maxColumns - 8 - reasonWidth;
0216 } else {
0217 reasonWidth = 50 + (maxColumns - 120) / 10;
0218 formulaWidth = maxColumns - 8 - reasonWidth;
0219 }
0220 // System.out.println("maxColums =" + this.printer.getColumns());
0221 // System.out.println("formulaWidth =" + this.formulaWidth);
0222 // System.out.println("reasonWidth =" + this.reasonWidth);
0223 if (language == null) {
0224 this.language = "en";
0225 } else {
0226 this.language = language;
0227 }
0228 // if (level == null) {
0229 // this.level = "1";
0230 // } else {
0231 // this.level = level;
0232 // }
0233
0234 init();
0235 }
0236
0237 /**
0238 * Reset counters and other variables. Should be executed before {@link #traverse()}.
0239 */
0240 protected void init() {
0241 id = null;
0242 title = null;
0243 subContext = "";
0244 }
0245
0246 public final void visitEnter(final Qedeq qedeq) {
0247 if (printer instanceof TextOutput) {
0248 printer.println("================================================================================");
0249 printer.println("UTF-8-file " + ((TextOutput) printer).getName());
0250 printer.println("Generated from " + getKernelQedeqBo().getModuleAddress());
0251 printer.println("Generated at " + DateUtility.getTimestamp());
0252 printer.println("================================================================================");
0253 printer.println();
0254 printer.println("If the characters of this document don't display correctly try opening this");
0255 printer.println("document within a webbrowser and if necessary change the encoding to");
0256 printer.println("Unicode (UTF-8)");
0257 printer.println();
0258 printer.println("Permission is granted to copy, distribute and/or modify this document");
0259 printer.println("under the terms of the GNU Free Documentation License, Version 1.2");
0260 printer.println("or any later version published by the Free Software Foundation;");
0261 printer.println("with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.");
0262 printer.println();
0263 printer.println();
0264 printer.println();
0265 }
0266 }
0267
0268 public final void visitLeave(final Qedeq qedeq) {
0269 printer.println();
0270 }
0271
0272 public void visitEnter(final Header header) {
0273 final LatexList tit = header.getTitle();
0274 underlineBig(getLatexListEntry("getTitle()", tit));
0275 printer.println();
0276 final AuthorList authors = getKernelQedeqBo().getQedeq().getHeader().getAuthorList();
0277 final StringBuffer authorList = new StringBuffer();
0278 for (int i = 0; i < authors.size(); i++) {
0279 if (i > 0) {
0280 authorList.append(" \n");
0281 printer.println(", ");
0282 }
0283 final Author author = authors.get(i);
0284 final String name = author.getName().getLatex().trim();
0285 printer.print(name);
0286 authorList.append(" " + name);
0287 String email = author.getEmail();
0288 if (email != null && email.trim().length() > 0) {
0289 authorList.append(" <" + email + ">");
0290 }
0291 }
0292 printer.println();
0293 printer.println();
0294 final String url = getKernelQedeqBo().getUrl();
0295 if (url != null && url.length() > 0) {
0296 printer.println();
0297 if ("de".equals(language)) {
0298 printer.println("Die Quelle f\u00FCr dieses Dokument ist hier zu finden:");
0299 } else {
0300 if (!"en".equals(language)) {
0301 printer.println("%%% TODO unknown language: " + language);
0302 }
0303 printer.println("The source for this document can be found here:");
0304 }
0305 printer.println();
0306 printer.println(url);
0307 printer.println();
0308 }
0309 {
0310 printer.println();
0311 if ("de".equals(language)) {
0312 printer.println("Die vorliegende Publikation ist urheberrechtlich gesch\u00FCtzt.");
0313 } else {
0314 if (!"en".equals(language)) {
0315 printer.println("%%% TODO unknown language: " + language);
0316 }
0317 printer.println("Copyright by the authors. All rights reserved.");
0318 }
0319 }
0320 final String email = header.getEmail();
0321 if (email != null && email.length() > 0) {
0322 printer.println();
0323 printer.println();
0324 if ("de".equals(language)) {
0325 printer.println("Bei Fragen, Anregungen oder Bitte um Aufnahme in die Liste der"
0326 + " abh\u00E4ngigen Module schicken Sie bitte eine EMail an die Adresse "
0327 + email);
0328 printer.println();
0329 printer.println();
0330 printer.println("Die Autoren dieses Dokuments sind:");
0331 printer.println();
0332 printer.println(authorList);
0333 } else {
0334 if (!"en".equals(language)) {
0335 printer.println("%%% TODO unknown language: " + language);
0336 }
0337 printer.println("If you have any questions, suggestions or want to add something"
0338 + " to the list of modules that use this one, please send an email to the"
0339 + " address " + email);
0340 printer.println();
0341 printer.println();
0342 printer.println("The authors of this document are:");
0343 printer.println(authorList);
0344 }
0345 printer.println();
0346 }
0347 printer.println();
0348 printer.println();
0349 }
0350
0351 public void visitEnter(final ImportList imports) throws ModuleDataException {
0352 // this method call is a little bit odd but we have to print the imports
0353 // also in the literature list and we don't want to have doubled code
0354 printImports();
0355 }
0356
0357 /**
0358 * Get URL for QEDEQ XML module.
0359 *
0360 * @param address Current module address.
0361 * @param specification Find URL for this location list.
0362 * @return URL or <code>""</code> if none (valid?) was found.
0363 */
0364 private String getUrl(final ModuleAddress address, final Specification specification) {
0365 final LocationList list = specification.getLocationList();
0366 if (list == null || list.size() <= 0) {
0367 return "";
0368 }
0369 try {
0370 return address.getModulePaths(specification)[0].getUrl();
0371 } catch (IOException e) {
0372 return "";
0373 }
0374 }
0375
0376 public void visitEnter(final Chapter chapter) {
0377 // check if we print only brief and test for non text subnodes
0378 if (brief) {
0379 boolean hasFormalContent = false;
0380 do {
0381 final SectionList sections = chapter.getSectionList();
0382 if (sections == null) {
0383 break;
0384 }
0385 for (int i = 0; i < sections.size() && !hasFormalContent; i++) {
0386 final Section section = sections.get(i);
0387 if (section == null) {
0388 continue;
0389 }
0390 final SubsectionList subSections = section.getSubsectionList();
0391 if (subSections == null) {
0392 continue;
0393 }
0394 for (int j = 0; j < subSections.size(); j++) {
0395 final SubsectionType subSection = subSections.get(j);
0396 if (!(subSection instanceof Subsection)) {
0397 hasFormalContent = true;
0398 break;
0399 }
0400 }
0401 }
0402 } while (false);
0403 if (!hasFormalContent) {
0404 setBlocked(true);
0405 return;
0406 }
0407 }
0408 final QedeqNumbers numbers = getCurrentNumbers();
0409 if (numbers.isChapterNumbering()) {
0410 if ("de".equals(language)) {
0411 printer.println("Kapitel " + numbers.getChapterNumber() + " ");
0412 } else {
0413 printer.println("Chapter " + numbers.getChapterNumber() + " ");
0414 }
0415 printer.println();
0416 printer.println();
0417 }
0418 underlineBig(getLatexListEntry("getTitle()", chapter.getTitle()));
0419 printer.println();
0420 if (chapter.getIntroduction() != null && !brief) {
0421 printer.append(getLatexListEntry("getIntroduction()", chapter.getIntroduction()));
0422 printer.println();
0423 printer.println();
0424 printer.println();
0425 }
0426 }
0427
0428 public void visitLeave(final Header header) {
0429 printer.println();
0430 printer.println("___________________________________________________");
0431 printer.println();
0432 printer.println();
0433 }
0434
0435 public void visitLeave(final Chapter chapter) {
0436 if (!getBlocked()) {
0437 printer.println();
0438 printer.println("___________________________________________________");
0439 printer.println();
0440 printer.println();
0441 }
0442 setBlocked(false);
0443 }
0444
0445 public void visitEnter(final Section section) {
0446 // check if we print only brief and test for non text subnodes
0447 if (brief) {
0448 boolean hasFormalContent = false;
0449 do {
0450 final SubsectionList subSections = section.getSubsectionList();
0451 if (subSections == null) {
0452 break;
0453 }
0454 for (int j = 0; j < subSections.size(); j++) {
0455 final SubsectionType subSection = subSections.get(j);
0456 if (!(subSection instanceof Subsection)) {
0457 hasFormalContent = true;
0458 break;
0459 }
0460 }
0461 } while (false);
0462 if (!hasFormalContent) {
0463 setBlocked(true);
0464 return;
0465 }
0466 }
0467 final QedeqNumbers numbers = getCurrentNumbers();
0468 final StringBuffer buffer = new StringBuffer();
0469 if (numbers.isChapterNumbering()) {
0470 buffer.append(numbers.getChapterNumber());
0471 }
0472 if (numbers.isSectionNumbering()) {
0473 if (buffer.length() > 0) {
0474 buffer.append(".");
0475 }
0476 buffer.append(numbers.getSectionNumber());
0477 }
0478 if (buffer.length() > 0 && section.getTitle() != null) {
0479 buffer.append(" ");
0480 }
0481 buffer.append(getLatexListEntry("getTitle()", section.getTitle()));
0482 underline(buffer.toString());
0483 printer.println();
0484 if (section.getIntroduction() != null && !brief) {
0485 printer.append(getLatexListEntry("getIntroduction()", section.getIntroduction()));
0486 printer.println();
0487 printer.println();
0488 printer.println();
0489 }
0490 }
0491
0492 public void visitLeave(final Section section) {
0493 if (!getBlocked()) {
0494 printer.println();
0495 }
0496 setBlocked(false);
0497 }
0498
0499 public void visitEnter(final Subsection subsection) {
0500 if (brief) {
0501 return;
0502 }
0503 final QedeqNumbers numbers = getCurrentNumbers();
0504 final StringBuffer buffer = new StringBuffer();
0505 if (numbers.isChapterNumbering()) {
0506 buffer.append(numbers.getChapterNumber());
0507 }
0508 if (numbers.isSectionNumbering()) {
0509 if (buffer.length() > 0) {
0510 buffer.append(".");
0511 }
0512 buffer.append(numbers.getSectionNumber());
0513 }
0514 if (buffer.length() > 0) {
0515 buffer.append(".");
0516 }
0517 buffer.append(numbers.getSubsectionNumber());
0518 if (buffer.length() > 0 && subsection.getTitle() != null) {
0519 buffer.append(" ");
0520 }
0521 if (subsection.getTitle() != null) {
0522 printer.print(buffer.toString());
0523 printer.print(getLatexListEntry("getTitle()", subsection.getTitle()));
0524 }
0525 if (subsection.getId() != null && info) {
0526 printer.print(" [" + subsection.getId() + "]");
0527 }
0528 if (subsection.getTitle() != null) {
0529 printer.println();
0530 printer.println();
0531 }
0532 printer.append(getLatexListEntry("getLatex()", subsection.getLatex()));
0533 printer.println();
0534 printer.println();
0535 }
0536
0537 public void visitEnter(final Node node) {
0538 if (node.getPrecedingText() != null && !brief) {
0539 printer.append(getLatexListEntry("getPrecedingText()", node.getPrecedingText()));
0540 printer.println();
0541 printer.println();
0542 }
0543 id = node.getId();
0544 title = null;
0545 if (node.getTitle() != null) {
0546 title = getLatexListEntry("getTitle()", node.getTitle());
0547 }
0548 }
0549
0550 public void visitLeave(final Node node) {
0551 if (node.getSucceedingText() != null && !brief) {
0552 printer.append(getLatexListEntry("getSucceedingText()", node.getSucceedingText()));
0553 printer.println();
0554 printer.println();
0555 }
0556 printer.println();
0557 }
0558
0559 public void visitEnter(final Axiom axiom) {
0560 final QedeqNumbers numbers = getCurrentNumbers();
0561 printer.print("\u2609 ");
0562 printer.print("Axiom " + numbers.getAxiomNumber());
0563 printer.print(" ");
0564 if (title != null && title.length() > 0) {
0565 printer.print(" (" + title + ")");
0566 }
0567 if (info) {
0568 printer.print(" [" + id + "]");
0569 }
0570 printer.println();
0571 printer.println();
0572 printer.print(" ");
0573 printFormula(axiom.getFormula().getElement());
0574 printer.println();
0575 if (axiom.getDescription() != null) {
0576 printer.append(getLatexListEntry("getDescription()", axiom.getDescription()));
0577 printer.println();
0578 printer.println();
0579 }
0580 }
0581
0582 public void visitEnter(final Proposition proposition) {
0583 final QedeqNumbers numbers = getCurrentNumbers();
0584 printer.print("\u2609 ");
0585 printer.print("Proposition " + numbers.getPropositionNumber());
0586 printer.print(" ");
0587 if (title != null && title.length() > 0) {
0588 printer.print(" (" + title + ")");
0589 }
0590 if (info) {
0591 printer.print(" [" + id + "]");
0592 }
0593 printer.println();
0594 printer.println();
0595 printTopFormula(proposition.getFormula().getElement(), id);
0596 printer.println();
0597 if (proposition.getDescription() != null) {
0598 printer.append(getLatexListEntry("getDescription()", proposition.getDescription()));
0599 printer.println();
0600 printer.println();
0601 }
0602 }
0603
0604 public void visitEnter(final Proof proof) {
0605 if (brief) {
0606 setBlocked(true);
0607 return;
0608 }
0609 if ("de".equals(language)) {
0610 printer.println("Beweis:");
0611 } else {
0612 printer.println("Proof:");
0613 }
0614 printer.append(getLatexListEntry("getNonFormalProof()", proof.getNonFormalProof()));
0615 }
0616
0617 public void visitLeave(final Proof proof) {
0618 printer.println();
0619 printer.println("q.e.d.");
0620 printer.println();
0621 setBlocked(false);
0622 }
0623
0624 public void visitEnter(final FormalProof proof) {
0625 if (brief) {
0626 setBlocked(true);
0627 return;
0628 }
0629 if ("de".equals(language)) {
0630 printer.println("Beweis (formal):");
0631 } else {
0632 printer.println("Proof (formal):");
0633 }
0634 }
0635
0636 public void visitLeave(final FormalProof proof) {
0637 if (!brief) {
0638 printer.println("q.e.d.");
0639 printer.println();
0640 }
0641 setBlocked(false);
0642 }
0643
0644
0645 public void visitEnter(final FormalProofLine line) {
0646 lineData.init();
0647 if (line.getLabel() != null) {
0648 lineData.setLineLabel(line.getLabel());
0649 }
0650 if (line.getReason() != null) {
0651 setReason(line.getReason().toString());
0652 }
0653 setFormula(line.getFormula());
0654 }
0655
0656 public void visitLeave(final FormalProofLine line) {
0657 linePrintln();
0658 }
0659
0660 /**
0661 * Print formula and reason.
0662 */
0663 private void linePrintln() {
0664 if (!lineData.containsData()) {
0665 return;
0666 }
0667 if (lineData.getLineLabel().length() > 0) {
0668 printer.print(StringUtility.alignRight("(" + lineData.getLineLabel() + ")", 5) + " ");
0669 }
0670 for (int i = 0; i < lineData.lines(); i++) {
0671 printer.skipToColumn(6);
0672 printer.print(tab);
0673 if (i < lineData.getFormula().length) {
0674 printer.print(lineData.getFormula()[i]);
0675 }
0676 if (i < lineData.getReason().length) {
0677 printer.skipToColumn(6 + 2 + formulaWidth);
0678 printer.print(lineData.getReason()[i]);
0679 }
0680 printer.println();
0681 }
0682 lineData.init();
0683 }
0684
0685 public void visitEnter(final ConditionalProof r) throws ModuleDataException {
0686 lineData.init();
0687 printer.skipToColumn(6);
0688 printer.print(tab);
0689 printer.println("Conditional Proof");
0690 tab = tab + " ";
0691 }
0692
0693 public void visitLeave(final ConditionalProof proof) {
0694 tab = StringUtility.substring(tab, 0, tab.length() - 2);
0695 }
0696
0697 public void visitEnter(final Hypothesis hypothesis) {
0698 lineData.init();
0699 if (hypothesis.getLabel() != null) {
0700 lineData.setLineLabel(hypothesis.getLabel());
0701 }
0702 setReason("Hypothesis");
0703 setFormula(hypothesis.getFormula());
0704 }
0705
0706 public void visitLeave(final Hypothesis hypothesis) {
0707 linePrintln();
0708 }
0709
0710 public void visitEnter(final Conclusion conclusion) {
0711 tab = StringUtility.substring(tab, 0, tab.length() - 2);
0712 lineData.init();
0713 if (conclusion.getLabel() != null) {
0714 lineData.setLineLabel(conclusion.getLabel());
0715 }
0716 setReason("Conclusion");
0717 setFormula(conclusion.getFormula());
0718 linePrintln();
0719 }
0720
0721 public void visitLeave(final Conclusion conclusion) {
0722 linePrintln();
0723 tab = tab + " ";
0724 }
0725
0726 private void setReason(final String reasonString) {
0727 final List list = new ArrayList();
0728 int index = 0;
0729 while (index < reasonString.length()) {
0730 list.add(StringUtility.substring(reasonString, index, reasonWidth));
0731 index += reasonWidth;
0732 }
0733 lineData.setReason((String[]) list.toArray(ArrayUtils.EMPTY_STRING_ARRAY));
0734 }
0735
0736 private void setFormula(final Formula f) {
0737 if (f != null && f.getElement() != null) {
0738 lineData.setFormula(getUtf8(f.getElement(),
0739 formulaWidth - tab.length()));
0740 }
0741 }
0742
0743 private String getReference(final String reference) {
0744 return getReference(reference, "getReference()");
0745 }
0746
0747 private String getReference(final String reference, final String subContext) {
0748 final String context = getCurrentContext().getLocationWithinModule();
0749 try {
0750 getCurrentContext().setLocationWithinModule(context + "." + subContext);
0751 return (getReferenceLink(reference, null, null));
0752 } finally {
0753 getCurrentContext().setLocationWithinModule(context);
0754 }
0755 }
0756
0757 public void visitEnter(final ModusPonens r) throws ModuleDataException {
0758 String buffer = r.getName();
0759 boolean one = false;
0760 if (r.getReference1() != null) {
0761 buffer += " " + getReference(r.getReference1(), "getReference1()");
0762 one = true;
0763 }
0764 if (r.getReference1() != null) {
0765 if (one) {
0766 buffer += ",";
0767 }
0768 buffer += " " + getReference(r.getReference2(), "getReference2()");
0769 }
0770 setReason(buffer);
0771 }
0772
0773 public void visitEnter(final Add r) throws ModuleDataException {
0774 String buffer = r.getName();
0775 if (r.getReference() != null) {
0776 buffer += " " + getReference(r.getReference());
0777 }
0778 setReason(buffer);
0779 }
0780
0781 public void visitEnter(final Rename r) throws ModuleDataException {
0782 String buffer = r.getName();
0783 if (r.getOriginalSubjectVariable() != null) {
0784 buffer += " " + getUtf8(r.getOriginalSubjectVariable());
0785 }
0786 if (r.getReplacementSubjectVariable() != null) {
0787 buffer += " by " + getUtf8(r.getReplacementSubjectVariable());
0788 }
0789 if (r.getReference() != null) {
0790 buffer += " in " + getReference(r.getReference());
0791 }
0792 setReason(buffer);
0793 }
0794
0795 public void visitEnter(final SubstFree r) throws ModuleDataException {
0796 String buffer = r.getName();
0797 if (r.getSubjectVariable() != null) {
0798 buffer += " " + getUtf8(r.getSubjectVariable());
0799 }
0800 if (r.getSubstituteTerm() != null) {
0801 buffer += " by " + getUtf8(r.getSubstituteTerm());
0802 }
0803 if (r.getReference() != null) {
0804 buffer += " in " + getReference(r.getReference());
0805 }
0806 setReason(buffer);
0807 }
0808
0809 public void visitEnter(final SubstFunc r) throws ModuleDataException {
0810 String buffer = r.getName();
0811 if (r.getFunctionVariable() != null) {
0812 buffer += " " + getUtf8(r.getFunctionVariable());
0813 }
0814 if (r.getSubstituteTerm() != null) {
0815 buffer += " by " + getUtf8(r.getSubstituteTerm());
0816 }
0817 if (r.getReference() != null) {
0818 buffer += " in " + getReference(r.getReference());
0819 }
0820 setReason(buffer);
0821 }
0822
0823 public void visitEnter(final SubstPred r) throws ModuleDataException {
0824 String buffer = r.getName();
0825 if (r.getPredicateVariable() != null) {
0826 buffer += " " + getUtf8(r.getPredicateVariable());
0827 }
0828 if (r.getSubstituteFormula() != null) {
0829 buffer += " by " + getUtf8(r.getSubstituteFormula());
0830 }
0831 if (r.getReference() != null) {
0832 buffer += " in " + getReference(r.getReference());
0833 }
0834 setReason(buffer);
0835 }
0836
0837 public void visitEnter(final Existential r) throws ModuleDataException {
0838 String buffer = r.getName();
0839 if (r.getSubjectVariable() != null) {
0840 buffer += " with " + getUtf8(r.getSubjectVariable());
0841 }
0842 if (r.getReference() != null) {
0843 buffer += " in " + getReference(r.getReference());
0844 }
0845 setReason(buffer);
0846 }
0847
0848 public void visitEnter(final Universal r) throws ModuleDataException {
0849 String buffer = r.getName();
0850 if (r.getSubjectVariable() != null) {
0851 buffer += " with " + getKernelQedeqBo().getElement2Utf8().getUtf8(
0852 r.getSubjectVariable());
0853 }
0854 if (r.getReference() != null) {
0855 buffer += " in " + getReference(r.getReference());
0856 }
0857 setReason(buffer);
0858 }
0859
0860 public void visitEnter(final InitialPredicateDefinition definition) {
0861 final QedeqNumbers numbers = getCurrentNumbers();
0862 printer.print("\u2609 ");
0863 final StringBuffer buffer = new StringBuffer();
0864 if ("de".equals(language)) {
0865 buffer.append("initiale ");
0866 } else {
0867 buffer.append("initial ");
0868 }
0869 buffer.append("Definition " + (numbers.getPredicateDefinitionNumber()
0870 + numbers.getFunctionDefinitionNumber()));
0871 printer.print(buffer.toString());
0872 printer.print(" ");
0873 if (title != null && title.length() > 0) {
0874 printer.print(" (" + title + ")");
0875 }
0876 if (info) {
0877 printer.print(" [" + id + "]");
0878 }
0879 printer.println();
0880 printer.println();
0881 printer.print(" ");
0882 printer.println(getUtf8(definition.getPredCon()));
0883 printer.println();
0884 if (definition.getDescription() != null) {
0885 printer.append(getLatexListEntry("getDescription()", definition.getDescription()));
0886 printer.println();
0887 printer.println();
0888 }
0889 }
0890
0891 public void visitEnter(final PredicateDefinition definition) {
0892 final QedeqNumbers numbers = getCurrentNumbers();
0893 printer.print("\u2609 ");
0894 final StringBuffer buffer = new StringBuffer();
0895 buffer.append("Definition " + (numbers.getPredicateDefinitionNumber()
0896 + numbers.getFunctionDefinitionNumber()));
0897 printer.print(buffer.toString());
0898 printer.print(" ");
0899 if (title != null && title.length() > 0) {
0900 printer.print(" (" + title + ")");
0901 }
0902 if (info) {
0903 printer.print(" [" + id + "]");
0904 }
0905 printer.println();
0906 printer.println();
0907 printer.print(" ");
0908 printer.println(getUtf8(definition.getFormula().getElement()));
0909 printer.println();
0910 if (definition.getDescription() != null) {
0911 printer.append(getLatexListEntry("getDescription()", definition.getDescription()));
0912 printer.println();
0913 printer.println();
0914 }
0915 }
0916
0917 public void visitEnter(final InitialFunctionDefinition definition) {
0918 final QedeqNumbers numbers = getCurrentNumbers();
0919 printer.print("\u2609 ");
0920 final StringBuffer buffer = new StringBuffer();
0921 if ("de".equals(language)) {
0922 buffer.append("initiale ");
0923 } else {
0924 buffer.append("initial ");
0925 }
0926 buffer.append("Definition " + (numbers.getPredicateDefinitionNumber()
0927 + numbers.getFunctionDefinitionNumber()));
0928 printer.print(buffer.toString());
0929 printer.print(" ");
0930 if (title != null && title.length() > 0) {
0931 printer.print(" (" + title + ")");
0932 }
0933 if (info) {
0934 printer.print(" [" + id + "]");
0935 }
0936 printer.println();
0937 printer.println();
0938 printer.print(" ");
0939 printer.println(getUtf8(definition.getFunCon()));
0940 printer.println();
0941 if (definition.getDescription() != null) {
0942 printer.println(getLatexListEntry("getDescription()", definition.getDescription()));
0943 printer.println();
0944 }
0945 }
0946
0947 public void visitEnter(final FunctionDefinition definition) {
0948 final QedeqNumbers numbers = getCurrentNumbers();
0949 printer.print("\u2609 ");
0950 final StringBuffer buffer = new StringBuffer();
0951 buffer.append("Definition " + (numbers.getPredicateDefinitionNumber()
0952 + numbers.getFunctionDefinitionNumber()));
0953 printer.print(buffer.toString());
0954 printer.print(" ");
0955 if (title != null && title.length() > 0) {
0956 printer.print(" (" + title + ")");
0957 }
0958 if (info) {
0959 printer.print(" [" + id + "]");
0960 }
0961 printer.println();
0962 printer.println();
0963 printer.print(" ");
0964 printer.println(getUtf8(definition.getFormula().getElement()));
0965 printer.println();
0966 if (definition.getDescription() != null) {
0967 printer.println(getLatexListEntry("getDescription()", definition.getDescription()));
0968 printer.println();
0969 }
0970 }
0971
0972 public void visitEnter(final Rule rule) {
0973 final QedeqNumbers numbers = getCurrentNumbers();
0974 printer.print("\u2609 ");
0975 if ("de".equals(language)) {
0976 printer.print("Regel");
0977 } else {
0978 printer.print("Rule");
0979 }
0980 printer.print(" " + numbers.getRuleNumber());
0981 printer.print(" ");
0982 if (title != null && title.length() > 0) {
0983 printer.print(" (" + title + ")");
0984 }
0985 if (info) {
0986 printer.print(" [" + id + "]");
0987 }
0988 printer.println();
0989 printer.println((rule.getName() != null ? " Name: " + rule.getName() : "")
0990 + (rule.getVersion() != null ? " - Version: " + rule.getVersion() : ""));
0991 printer.println();
0992 if (rule.getDescription() != null) {
0993 printer.append(getLatexListEntry("getDescription()", rule.getDescription()));
0994 printer.println();
0995 printer.println();
0996 }
0997 }
0998
0999 public void visitEnter(final LinkList linkList) {
1000 if (linkList.size() <= 0) {
1001 return;
1002 }
1003 if ("de".equals(language)) {
1004 printer.println("Basierend auf: ");
1005 } else {
1006 if (!"en".equals(language)) {
1007 printer.println("%%% TODO unknown language: " + language);
1008 }
1009 printer.println("Based on: ");
1010 }
1011 for (int i = 0; i < linkList.size(); i++) {
1012 if (linkList.get(i) != null) {
1013 printer.print(" (" + linkList.get(i) + ")");
1014 }
1015 };
1016 printer.println();
1017 }
1018
1019 public void visitEnter(final ChangedRuleList list) {
1020 if (list.size() <= 0) {
1021 return;
1022 }
1023 printer.println();
1024 if ("de".equals(language)) {
1025 printer.println("Die folgenden Regeln m\u00FCssen erweitert werden.");
1026 } else {
1027 if (!"en".equals(language)) {
1028 printer.println("%%% TODO unknown language: " + language);
1029 }
1030 printer.println("The following rules have to be extended.");
1031 }
1032 printer.println();
1033 }
1034
1035 public void visitEnter(final ChangedRule rule) {
1036 printer.println((rule.getName() != null ? " Name: " + rule.getName() : "")
1037 + (rule.getVersion() != null ? " - Version: " + rule.getVersion() : ""));
1038 printer.println();
1039 if (rule.getDescription() != null) {
1040 printer.append(getLatexListEntry("getDescription()", rule.getDescription()));
1041 printer.println();
1042 printer.println();
1043 }
1044
1045 }
1046
1047 public void visitEnter(final LiteratureItemList list) {
1048 printer.println();
1049 printer.println();
1050 if ("de".equals(language)) {
1051 underlineBig("Literaturverzeichnis");
1052 } else {
1053 underlineBig("Bibliography");
1054 }
1055 printImports();
1056 }
1057
1058 /**
1059 * Print all imports if any.
1060 */
1061 private void printImports() {
1062 final ImportList imports = getKernelQedeqBo().getQedeq().getHeader().getImportList();
1063 if (imports != null && imports.size() > 0) {
1064 printer.println();
1065 printer.println();
1066 if ("de".equals(language)) {
1067 printer.println("Benutzte andere QEDEQ-Module:");
1068 } else {
1069 printer.println("Used other QEDEQ modules:");
1070 }
1071 printer.println();
1072 for (int i = 0; i < imports.size(); i++) {
1073 final Import imp = imports.get(i);
1074 printer.print("[" + imp.getLabel() + "] ");
1075 final Specification spec = imp.getSpecification();
1076 printer.print(spec.getName());
1077 if (spec.getLocationList() != null && spec.getLocationList().size() > 0
1078 && spec.getLocationList().get(0).getLocation().length() > 0) {
1079 printer.print(" ");
1080 printer.print(getUrl(getKernelQedeqBo().getModuleAddress(), spec));
1081 }
1082 printer.println();
1083 }
1084 printer.println();
1085 printer.println();
1086 }
1087 }
1088
1089 public void visitLeave(final LiteratureItemList list) {
1090 final UsedByList usedby = getKernelQedeqBo().getQedeq().getHeader().getUsedByList();
1091 if (usedby != null && usedby.size() > 0) {
1092 printer.println();
1093 printer.println();
1094 if ("de".equals(language)) {
1095 printer.println("QEDEQ-Module, welche dieses hier verwenden:");
1096 } else {
1097 printer.println("QEDEQ modules that use this one:");
1098 }
1099 for (int i = 0; i < usedby.size(); i++) {
1100 final Specification spec = usedby.get(i);
1101 printer.print(spec.getName());
1102 final String url = getUrl(getKernelQedeqBo().getModuleAddress(), spec);
1103 if (url != null && url.length() > 0) {
1104 printer.print(" ");
1105 printer.print(url);
1106 }
1107 printer.println();
1108 }
1109 printer.println();
1110 printer.println();
1111 }
1112 printer.println();
1113 }
1114
1115 public void visitEnter(final LiteratureItem item) {
1116 printer.print("[" + item.getLabel() + "] ");
1117 printer.println(getLatexListEntry("getItem()", item.getItem()));
1118 printer.println();
1119 }
1120
1121 /**
1122 * Print top level formula. If the formula has the form <code>AND(.., .., ..)</code> the
1123 * formula is broken down in several labeled lines.
1124 *
1125 * @param element Formula to print.
1126 * @param mainLabel Main formula label.
1127 */
1128 private void printTopFormula(final Element element, final String mainLabel) {
1129 if (!element.isList() || !element.getList().getOperator().equals("AND")) {
1130 printer.print(" ");
1131 printFormula(element);
1132 return;
1133 }
1134 final ElementList list = element.getList();
1135 for (int i = 0; i < list.size(); i++) {
1136 String label = "";
1137 if (list.size() >= ALPHABET.length() * ALPHABET.length()) {
1138 label = "" + (i + 1);
1139 } else {
1140 if (list.size() > ALPHABET.length()) {
1141 final int div = (i / ALPHABET.length());
1142 label = "" + ALPHABET.charAt(div);
1143 }
1144 label += ALPHABET.charAt(i % ALPHABET.length());
1145 }
1146 printer.println(" (" + label + ") " + getUtf8(list.getElement(i)));
1147 }
1148 }
1149
1150 /**
1151 * Print formula.
1152 *
1153 * @param element Formula to print.
1154 */
1155 private void printFormula(final Element element) {
1156 printer.println(getUtf8(element));
1157 }
1158
1159 /**
1160 * Filters correct entry out of LaTeX list. Filter criterion is for example the correct
1161 * language.
1162 *
1163 * @param method This method was called. Used to get the correct sub context.
1164 * Should not be null. If it is empty the <code>subContext</code>
1165 * is not changed.
1166 * @param list List of LaTeX texts.
1167 * @return Filtered text.
1168 */
1169 private String getLatexListEntry(final String method, final LatexList list) {
1170 if (list == null) {
1171 return "";
1172 }
1173 if (method.length() > 0) {
1174 subContext = method;
1175 }
1176 try {
1177 for (int i = 0; i < list.size(); i++) {
1178 if (language.equals(list.get(i).getLanguage())) {
1179 if (method.length() > 0) {
1180 subContext = method + ".get(" + i + ")";
1181 }
1182 return getUtf8(list.get(i));
1183 }
1184 }
1185 // OK, we didn't found the language, so we take the default language
1186 final String def = getKernelQedeqBo().getOriginalLanguage();
1187 for (int i = 0; i < list.size(); i++) {
1188 if (EqualsUtility.equals(def, list.get(i).getLanguage())) {
1189 if (method.length() > 0) {
1190 subContext = method + ".get(" + i + ")";
1191 }
1192 return "MISSING! OTHER: " + getUtf8(list.get(i));
1193 }
1194 }
1195 // OK, we didn't find wanted and default language, so we take the first non empty one
1196 for (int i = 0; i < list.size(); i++) {
1197 if (method.length() > 0) {
1198 subContext = method + ".get(" + i + ")";
1199 }
1200 if (null != list.get(i) && null != list.get(i).getLatex()
1201 && list.get(i).getLatex().trim().length() > 0) {
1202 return "MISSING! OTHER: " + getUtf8(list.get(i));
1203 }
1204 }
1205 return "MISSING!";
1206 } finally {
1207 if (method.length() > 0) {
1208 subContext = "";
1209 }
1210 }
1211 }
1212
1213 /**
1214 * Get current module context. Uses sub context information.
1215 *
1216 * @param startDelta Skip position (relative to location start). Could be
1217 * <code>null</code>.
1218 * @param endDelta Mark until this column (relative to location start).
1219 * be <code>null</code>
1220 * @return Current module context.
1221 */
1222 private ModuleContext getCurrentContext(final SourcePosition startDelta,
1223 final SourcePosition endDelta) {
1224 if (subContext.length() == 0) {
1225 return super.getCurrentContext();
1226 }
1227 final ModuleContext c = new ModuleContext(super.getCurrentContext().getModuleLocation(),
1228 super.getCurrentContext().getLocationWithinModule() + "." + subContext,
1229 startDelta, endDelta);
1230 return c;
1231 }
1232
1233 /**
1234 * Add warning.
1235 *
1236 * @param code Warning code.
1237 * @param msg Warning message.
1238 * @param startDelta Skip position (relative to location start). Could be
1239 * <code>null</code>.
1240 * @param endDelta Mark until this column (relative to location start). Could be
1241 * be <code>null</code>
1242 */
1243 public void addWarning(final int code, final String msg, final SourcePosition startDelta,
1244 final SourcePosition endDelta) {
1245 Trace.param(CLASS, this, "addWarning", "msg", msg);
1246 if (addWarnings) {
1247 addWarning(new UnicodeException(code, msg, getCurrentContext(startDelta,
1248 endDelta)));
1249 }
1250 }
1251
1252 /**
1253 * Add warning.
1254 *
1255 * @param code Warning code.
1256 * @param msg Warning message.
1257 */
1258 public void addWarning(final int code, final String msg) {
1259 Trace.param(CLASS, this, "addWarning", "msg", msg);
1260 if (addWarnings) {
1261 addWarning(new UnicodeException(code, msg, getCurrentContext()));
1262 }
1263 }
1264
1265 /**
1266 * Get Utf8 element presentation.
1267 *
1268 * @param element Get presentation of this element.
1269 * @param max Maximum column.
1270 * @return UTF-8 form of element.
1271 */
1272 protected String[] getUtf8(final Element element, final int max) {
1273 return getKernelQedeqBo().getElement2Utf8().getUtf8(element, max);
1274 }
1275
1276
1277 /**
1278 * Get Utf8 element presentation.
1279 *
1280 * @param element Get presentation of this element.
1281 * @return UTF-8 form of element.
1282 */
1283 protected String getUtf8(final Element element) {
1284 return getUtf8(getKernelQedeqBo().getElement2Latex().getLatex(element));
1285 }
1286
1287 /**
1288 * Get UTF-8 String for LaTeX.
1289 *
1290 * @param latex LaTeX we got.
1291 * @return UTF-8 result string.
1292 */
1293 private String getUtf8(final Latex latex) {
1294 if (latex == null || latex.getLatex() == null) {
1295 return "";
1296 }
1297 return getUtf8(latex.getLatex());
1298 }
1299
1300 /**
1301 * Transform LaTeX into UTF-8 String..
1302 *
1303 * @param latex LaTeX text.
1304 * @return String.
1305 */
1306 private String getUtf8(final String latex) {
1307 if (latex == null) {
1308 return "";
1309 }
1310 return Latex2UnicodeParser.transform(this, latex, maxColumns);
1311 }
1312
1313 /**
1314 * Print text in one line and print another line with = to underline it.
1315 *
1316 * @param text Line to print.
1317 */
1318 private void underlineBig(final String text) {
1319 printer.println(text);
1320 for (int i = 0; i < text.length(); i++) {
1321 printer.print("\u2550");
1322 }
1323 printer.println();
1324 }
1325
1326 /**
1327 * Print text in one line and print another line with = to underline it.
1328 *
1329 * @param text Line to print.
1330 */
1331 private void underline(final String text) {
1332 printer.println(text);
1333 for (int i = 0; i < text.length(); i++) {
1334 printer.print("\u2015");
1335 }
1336 printer.println();
1337 }
1338
1339 public String getReferenceLink(final String reference, final SourcePosition start,
1340 final SourcePosition end) {
1341 final Reference ref = getReference(reference, getCurrentContext(start, end), addWarnings,
1342 false);
1343
1344 if (ref.isNodeLocalReference() && ref.isSubReference()) {
1345 return "(" + ref.getSubLabel() + ")";
1346 }
1347
1348 if (ref.isNodeLocalReference() && ref.isProofLineReference()) {
1349 return "(" + ref.getProofLineLabel() + ")";
1350 }
1351
1352 if (!ref.isExternal()) {
1353 return getNodeDisplay(ref.getNodeLabel(), ref.getNode())
1354 + (ref.isSubReference() ? " (" + ref.getSubLabel() + ")" : "")
1355 + (ref.isProofLineReference() ? " (" + ref.getProofLineLabel() + ")" : "");
1356 }
1357
1358 // do we have an external module reference without node?
1359 if (ref.isExternalModuleReference()) {
1360 return "[" + ref.getExternalQedeqLabel() + "]";
1361 }
1362
1363 return getNodeDisplay(ref.getNodeLabel(), ref.getNode())
1364 + (ref.isSubReference() ? " (" + ref.getSubLabel() + ")" : "")
1365 + (ref.isProofLineReference() ? " (" + ref.getProofLineLabel() + ")" : "")
1366 + (ref.isExternal() ? " [" + ref.getExternalQedeqLabel() + "]" : "");
1367 }
1368
1369 private String getNodeDisplay(final String label, final KernelNodeBo kNode) {
1370 return getNodeDisplay(label, kNode, language);
1371 }
1372
1373 }
|