Context2SimpleXPath.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.xml.mapper;
0017 
0018 import java.util.ArrayList;
0019 import java.util.HashMap;
0020 import java.util.List;
0021 import java.util.Map;
0022 
0023 import org.qedeq.base.trace.Trace;
0024 import org.qedeq.base.utility.Enumerator;
0025 import org.qedeq.kernel.se.base.list.ElementList;
0026 import org.qedeq.kernel.se.base.module.Add;
0027 import org.qedeq.kernel.se.base.module.Author;
0028 import org.qedeq.kernel.se.base.module.AuthorList;
0029 import org.qedeq.kernel.se.base.module.Axiom;
0030 import org.qedeq.kernel.se.base.module.ChangedRule;
0031 import org.qedeq.kernel.se.base.module.ChangedRuleList;
0032 import org.qedeq.kernel.se.base.module.Chapter;
0033 import org.qedeq.kernel.se.base.module.ChapterList;
0034 import org.qedeq.kernel.se.base.module.Conclusion;
0035 import org.qedeq.kernel.se.base.module.ConditionalProof;
0036 import org.qedeq.kernel.se.base.module.Existential;
0037 import org.qedeq.kernel.se.base.module.FormalProof;
0038 import org.qedeq.kernel.se.base.module.FormalProofLine;
0039 import org.qedeq.kernel.se.base.module.FormalProofLineList;
0040 import org.qedeq.kernel.se.base.module.FormalProofList;
0041 import org.qedeq.kernel.se.base.module.Formula;
0042 import org.qedeq.kernel.se.base.module.FunctionDefinition;
0043 import org.qedeq.kernel.se.base.module.Header;
0044 import org.qedeq.kernel.se.base.module.Hypothesis;
0045 import org.qedeq.kernel.se.base.module.Import;
0046 import org.qedeq.kernel.se.base.module.ImportList;
0047 import org.qedeq.kernel.se.base.module.InitialFunctionDefinition;
0048 import org.qedeq.kernel.se.base.module.InitialPredicateDefinition;
0049 import org.qedeq.kernel.se.base.module.Latex;
0050 import org.qedeq.kernel.se.base.module.LatexList;
0051 import org.qedeq.kernel.se.base.module.LinkList;
0052 import org.qedeq.kernel.se.base.module.LiteratureItem;
0053 import org.qedeq.kernel.se.base.module.LiteratureItemList;
0054 import org.qedeq.kernel.se.base.module.Location;
0055 import org.qedeq.kernel.se.base.module.LocationList;
0056 import org.qedeq.kernel.se.base.module.ModusPonens;
0057 import org.qedeq.kernel.se.base.module.Node;
0058 import org.qedeq.kernel.se.base.module.PredicateDefinition;
0059 import org.qedeq.kernel.se.base.module.Proof;
0060 import org.qedeq.kernel.se.base.module.ProofList;
0061 import org.qedeq.kernel.se.base.module.Proposition;
0062 import org.qedeq.kernel.se.base.module.Qedeq;
0063 import org.qedeq.kernel.se.base.module.Reason;
0064 import org.qedeq.kernel.se.base.module.Rename;
0065 import org.qedeq.kernel.se.base.module.Rule;
0066 import org.qedeq.kernel.se.base.module.Section;
0067 import org.qedeq.kernel.se.base.module.SectionList;
0068 import org.qedeq.kernel.se.base.module.Specification;
0069 import org.qedeq.kernel.se.base.module.Subsection;
0070 import org.qedeq.kernel.se.base.module.SubsectionList;
0071 import org.qedeq.kernel.se.base.module.SubstFree;
0072 import org.qedeq.kernel.se.base.module.SubstFunc;
0073 import org.qedeq.kernel.se.base.module.SubstPred;
0074 import org.qedeq.kernel.se.base.module.Term;
0075 import org.qedeq.kernel.se.base.module.Universal;
0076 import org.qedeq.kernel.se.base.module.UsedByList;
0077 import org.qedeq.kernel.se.common.ModuleContext;
0078 import org.qedeq.kernel.se.common.ModuleDataException;
0079 import org.qedeq.kernel.se.visitor.AbstractModuleVisitor;
0080 import org.qedeq.kernel.se.visitor.QedeqNotNullTraverser;
0081 import org.qedeq.kernel.xml.tracker.SimpleXPath;
0082 
0083 
0084 /**
0085  * Map content string to SimpleXPath string. This class makes it possible to transfer an location
0086  * of an {@link org.qedeq.kernel.se.base.module.Qedeq} object into an XPath like position description
0087  * for an XML file representation of that object.
0088  *
0089  <p>
0090  * See {@link #getXPath(ModuleContext, Qedeq)} for further details.
0091  *
0092  <p>
0093  * TODO mime 20070217: It seems to work this way but: this class assumes that we can find
0094  * QEDEQ/CHAPTER[2]/SECTION[4]/SUBSECTIONS/SUBSECTION[2]
0095  * even if we have some ../NODE s inbetween.
0096  * (Example: NODE, NODE, SUBSECTION, NODE, SUBSECTION, NODE..)
0097  *
0098  * Is this still a correct XPath? (Old solution was usage of "*")
0099  * Seems ok for official XPath specification, but does it work for our SimpleXPathFinder?
0100  *
0101  @author  Michael Meyling
0102  */
0103 public final class Context2SimpleXPath extends AbstractModuleVisitor {
0104 
0105     /** This class. */
0106     private static final Class CLASS = Context2SimpleXPath.class;
0107 
0108     /** Traverse QEDEQ module with this traverser. */
0109     private QedeqNotNullTraverser traverser;
0110 
0111     /** QEDEQ object to work on. */
0112     private Qedeq qedeq;
0113 
0114     /** Search for this context. */
0115     private final ModuleContext find;
0116 
0117     /** We are currently at this position. */
0118     private SimpleXPath current;
0119 
0120     /** Element stack. */
0121     private final List elements;
0122 
0123     /** Current stack level. */
0124     private int level;
0125 
0126     /** Is the current context already matching the beginning of the search context? */
0127     private boolean matching;
0128 
0129     /** Last matching begin of search context. See {@link #matching}. */
0130     private String matchingBegin;
0131 
0132     /** Corresponding XPath for the {@link #matchingBegin}. */
0133     private SimpleXPath matchingPath;
0134 
0135     /**
0136      * Constructor.
0137      *
0138      @param   find    Find this location.
0139      @param   qedeq   Within this QEDEQ object.
0140      */
0141     private Context2SimpleXPath(final ModuleContext find, final Qedeq qedeq) {
0142         this.qedeq = qedeq;
0143         traverser = new QedeqNotNullTraverser(find.getModuleLocation()this);
0144         this.find = find;
0145         elements = new ArrayList(20);
0146     }
0147 
0148     /**
0149      * This method finds a {@link ModuleContext} something like<br>
0150      <code>
0151      * getChapterList().get(4).getSectionList().get(0).getSubsectionList().get(4).getLatex().get(0)
0152      </code><br>
0153      * within a {@link Qedeq} module and returns a kind of XPath location for an associated
0154      * XML document:<br>
0155      <code>QEDEQ/CHAPTER[5]/SECTION/SUBSECTIONS/SUBSECTION[2]/TEXT/LATEX</code>
0156      *
0157      <p>
0158      * At this example one can already see that <code>getSubsectionList().get(4)</code> is
0159      * transformed into <code>SUBSECTIONS/SUBSECTION[2]</code>. This is due to the fact that
0160      <code>SUBSECTION</code> contains a sequence of <code>SUBSECTION</code> or <code>NODE</code>
0161      * elements. The transformation depends not only from the context but also from
0162      * the concrete QEDEQ module.
0163      *
0164      <p>
0165      * Especially the transformation of formula location information in their XML counterpart
0166      * demands parsing the whole formula.
0167      *
0168      @param   find    Find this location.
0169      @param   qedeq   Within this QEDEQ object.
0170      @return  XPath for this location in the XML document.
0171      @throws  ModuleDataException Problem with module data.
0172      */
0173     public static SimpleXPath getXPath(final ModuleContext find, final Qedeq qedeq)
0174             throws ModuleDataException {
0175         final Context2SimpleXPath converter = new Context2SimpleXPath(find, qedeq);
0176         return converter.find();
0177     }
0178 
0179     private final SimpleXPath find() throws ModuleDataException {
0180         final String method = "find()";
0181         Trace.paramInfo(CLASS, this, method, "find", find);
0182         elements.clear();
0183         level = 0;
0184         current = new SimpleXPath();
0185         try {
0186             traverser.accept(qedeq);
0187         catch (LocationFoundException e) {
0188             Trace.paramInfo(CLASS, this, method, "location found", current);
0189             return current;
0190         }
0191         Trace.param(CLASS, this, method, "level", level);  // level should be equal to zero now
0192         Trace.info(CLASS, this, method, "location was not found");
0193         // do we really want to fail?
0194         if (Boolean.TRUE.toString().equalsIgnoreCase(
0195                 System.getProperty("qedeq.test.xmlLocationFailures"))) {
0196             throw new LocationNotFoundException(traverser.getCurrentContext(),
0197                 matchingBegin, find.getLocationWithinModule());
0198         }
0199         throw new LocationFoundException(new ModuleContext(find.getModuleLocation(),
0200             matchingBegin));
0201     }
0202 
0203     public final void visitEnter(final Qedeq qedeqthrows ModuleDataException {
0204         enter("QEDEQ");
0205         final String method = "visitEnter(Qedeq)";
0206         Trace.param(CLASS, this, method, "current", current);
0207         checkMatching(method);
0208     }
0209 
0210     public final void visitLeave(final Qedeq qedeq) {
0211         leave();
0212     }
0213 
0214     public final void visitEnter(final Header headerthrows ModuleDataException {
0215         enter("HEADER");
0216         final String method = "visitEnter(Header)";
0217         Trace.param(CLASS, this, method, "current", current);
0218         final String context = traverser.getCurrentContext().getLocationWithinModule();
0219         checkMatching(method);
0220 
0221         traverser.setLocationWithinModule(context + ".getEmail()");
0222         current.setAttribute("email");
0223         checkIfFound();
0224     }
0225 
0226     public final void visitLeave(final Header header) {
0227         leave();
0228     }
0229 
0230     public final void visitEnter(final Specification specificationthrows ModuleDataException {
0231         enter("SPECIFICATION");
0232         final String method = "visitEnter(Specification)";
0233         Trace.param(CLASS, this, method, "current", current);
0234         final String context = traverser.getCurrentContext().getLocationWithinModule();
0235         checkMatching(method);
0236 
0237         traverser.setLocationWithinModule(context + ".getName()");
0238         current.setAttribute("name");
0239         checkIfFound();
0240 
0241         traverser.setLocationWithinModule(context + ".getRuleVersion()");
0242         current.setAttribute("ruleVersion");
0243         checkIfFound();
0244     }
0245 
0246     public final void visitLeave(final Specification specification) {
0247         leave();
0248     }
0249 
0250     public final void visitEnter(final LatexList latexListthrows ModuleDataException {
0251         final String method = "visitEnter(LatexList)";
0252         final String context = traverser.getCurrentContext().getLocationWithinModule();
0253         final String name;
0254         if (context.endsWith(".getTitle()")) {
0255             name = "TITLE";
0256         else if (context.endsWith(".getSummary()")) {
0257             name = "ABSTRACT";
0258         else if (context.endsWith(".getIntroduction()")) {
0259             name = "INTRODUCTION";
0260         else if (context.endsWith(".getName()")) {
0261             name = "NAME";
0262         else if (context.endsWith(".getPrecedingText()")) {
0263             name = "PRECEDING";
0264         else if (context.endsWith(".getSucceedingText()")) {
0265             name = "SUCCEEDING";
0266         else if (context.endsWith(".getLatex()")) {
0267             name = "TEXT";
0268         else if (context.endsWith(".getDescription()")) {
0269             if (context.indexOf(".getChangedRuleList().get(">= 0) {
0270                 name = null;
0271             else {
0272                 name = "DESCRIPTION";
0273             }
0274         else if (context.endsWith(".getNonFormalProof()")) {  // no extra XSD element
0275             name = null;
0276         else if (context.endsWith(".getItem()")) {            // no extra XSD element
0277             name = null;
0278         else {    // programming error
0279             throw new IllegalArgumentException("unknown LatexList " + context);
0280         }
0281         Trace.param(CLASS, this, method, "name", name);
0282         if (name != null) {
0283             enter(name);
0284         }
0285         Trace.param(CLASS, this, method, "current", current);
0286 
0287         checkMatching(method);
0288     }
0289 
0290     public final void visitLeave(final LatexList latexList) {
0291         final String context = traverser.getCurrentContext().getLocationWithinModule();
0292         if (!context.endsWith(".getNonFormalProof()")       // no extra XSD element
0293                 && !context.endsWith(".getItem()"&& !(context.endsWith(".getDescription()")
0294                 && context.indexOf(".getChangedRuleList().get(">= 0)) {
0295             leave();
0296         }
0297     }
0298 
0299     public final void visitEnter(final Latex latexthrows ModuleDataException {
0300         final String context = traverser.getCurrentContext().getLocationWithinModule();
0301         if (context.indexOf(".getAuthorList().get(">= 0) {    // TODO mime 20070216: why is the
0302             enter("NAME");                                      // XSD so cruel???
0303         }
0304         enter("LATEX");
0305         final String method = "visitEnter(Latex)";
0306         Trace.param(CLASS, this, method, "current", current);
0307         checkMatching(method);
0308 
0309         traverser.setLocationWithinModule(context + ".getLanguage()");
0310         current.setAttribute("language");
0311         checkIfFound();
0312 
0313         traverser.setLocationWithinModule(context + ".getLatex()");
0314         current.setAttribute(null)// element character data of LATEX is LaTeX content
0315         checkIfFound();
0316     }
0317 
0318     public final void visitLeave(final Latex latex) {
0319         // because NAME of AUTHOR/NAME/LATEX has no equivalent in interfaces:
0320         final String context = traverser.getCurrentContext().getLocationWithinModule();
0321         if (context.indexOf(".getAuthorList().get(">= 0) {
0322             leave();
0323         }
0324         leave();
0325     }
0326 
0327     public final void visitEnter(final LocationList locationListthrows ModuleDataException {
0328         enter("LOCATIONS");
0329         final String method = "visitEnter(LocationList)";
0330         Trace.param(CLASS, this, method, "current", current);
0331         checkMatching(method);
0332 
0333     }
0334 
0335     public final void visitLeave(final LocationList locationList) {
0336         leave();
0337     }
0338 
0339     public final void visitEnter(final Location locationthrows ModuleDataException {
0340         enter("LOCATION");
0341         final String method = "visitEnter(Location)";
0342         Trace.param(CLASS, this, method, "current", current);
0343         final String context = traverser.getCurrentContext().getLocationWithinModule();
0344         checkMatching(method);
0345 
0346         traverser.setLocationWithinModule(context + ".getLocation()");
0347         current.setAttribute("value");
0348         checkIfFound();
0349     }
0350 
0351     public final void visitLeave(final Location location) {
0352         leave();
0353     }
0354 
0355     public final void visitEnter(final AuthorList authorListthrows ModuleDataException {
0356         enter("AUTHORS");
0357         final String method = "visitEnter(AuthorList)";
0358         Trace.param(CLASS, this, method, "current", current);
0359         checkMatching(method);
0360     }
0361 
0362     public final void visitLeave(final AuthorList authorList) {
0363         leave();
0364     }
0365 
0366     public final void visitEnter(final Author authorthrows ModuleDataException {
0367         enter("AUTHOR");
0368         final String method = "visitEnter(Author)";
0369         Trace.param(CLASS, this, method, "current", current);
0370         final String context = traverser.getCurrentContext().getLocationWithinModule();
0371         checkMatching(method);
0372 
0373         traverser.setLocationWithinModule(context + ".getEmail()");
0374         current.setAttribute("email");
0375         checkIfFound();
0376     }
0377 
0378     public final void visitLeave(final Author author) {
0379         leave();
0380     }
0381 
0382     public final void visitEnter(final ImportList importListthrows ModuleDataException {
0383         enter("IMPORTS");
0384         final String method = "visitEnter(ImportList)";
0385         Trace.param(CLASS, this, method, "current", current);
0386         checkMatching(method);
0387     }
0388 
0389     public final void visitLeave(final ImportList importList) {
0390         leave();
0391     }
0392 
0393     public final void visitEnter(final Import impthrows ModuleDataException {
0394         enter("IMPORT");
0395         final String method = "visitEnter(Import)";
0396         Trace.param(CLASS, this, method, "current", current);
0397         final String context = traverser.getCurrentContext().getLocationWithinModule();
0398         checkMatching(method);
0399 
0400         traverser.setLocationWithinModule(context + ".getLabel()");
0401         current.setAttribute("label");
0402         checkIfFound();
0403     }
0404 
0405     public final void visitLeave(final Import imp) {
0406         leave();
0407     }
0408 
0409     public final void visitEnter(final UsedByList usedByListthrows ModuleDataException {
0410         enter("USEDBY");
0411         final String method = "visitEnter(UsedByList)";
0412         Trace.param(CLASS, this, method, "current", current);
0413         checkMatching(method);
0414     }
0415 
0416     public final void visitLeave(final UsedByList usedByList) {
0417         leave();
0418     }
0419 
0420     public final void visitEnter(final ChapterList chapterListthrows ModuleDataException {
0421         final String method = "visitEnter(ChapterList)";
0422         // because no equivalent level of "getChapterList()" exists in the XSD we simply
0423         // point to the current location that must be "QEDEQ"
0424         checkMatching(method);
0425     }
0426 
0427     public final void visitLeave(final ChapterList chapterList) {
0428         traverser.setBlocked(false);  // free sub node search
0429     }
0430 
0431     public final void visitEnter(final Chapter chapterthrows ModuleDataException {
0432         enter("CHAPTER");
0433         final String method = "visitEnter(Chapter)";
0434         Trace.param(CLASS, this, method, "current", current);
0435         final String context = traverser.getCurrentContext().getLocationWithinModule();
0436         checkMatching(method);
0437 
0438         traverser.setLocationWithinModule(context + ".getNoNumber()");
0439         current.setAttribute("noNumber");
0440         checkIfFound();
0441     }
0442 
0443     public final void visitLeave(final Chapter chapter) {
0444         leave();
0445     }
0446 
0447     public final void visitEnter(final SectionList sectionListthrows ModuleDataException {
0448         final String method = "visitEnter(SectionList)";
0449         // because no equivalent level of "getSectionList()" exists in the XSD we simply
0450         // point to the current location that must be "QEDEQ/CHAPTER[x]"
0451         checkMatching(method);
0452     }
0453 
0454     public final void visitLeave(final SectionList sectionList) {
0455         traverser.setBlocked(false);  // free node search again
0456     }
0457 
0458     public final void visitEnter(final Section sectionthrows ModuleDataException {
0459         enter("SECTION");
0460         final String method = "visitEnter(Section)";
0461         Trace.param(CLASS, this, method, "current", current);
0462         final String context = traverser.getCurrentContext().getLocationWithinModule();
0463         checkMatching(method);
0464 
0465         traverser.setLocationWithinModule(context + ".getNoNumber()");
0466         current.setAttribute("noNumber");
0467         checkIfFound();
0468     }
0469 
0470     public final void visitLeave(final Section section) {
0471         leave();
0472     }
0473 
0474     public final void visitEnter(final SubsectionList subsectionListthrows ModuleDataException {
0475         enter("SUBSECTIONS");
0476         final String method = "visitEnter(SubsectionList)";
0477         Trace.param(CLASS, this, method, "current", current);
0478         checkMatching(method);
0479     }
0480 
0481     public final void visitLeave(final SubsectionList subsectionList) {
0482         leave();
0483     }
0484 
0485     public final void visitEnter(final Subsection subsectionthrows ModuleDataException {
0486         enter("SUBSECTION");
0487         final String method = "visitEnter(Subsection)";
0488         Trace.param(CLASS, this, method, "current", current);
0489         final String context = traverser.getCurrentContext().getLocationWithinModule();
0490         checkMatching(method);
0491 
0492         traverser.setLocationWithinModule(context + ".getId()");
0493         current.setAttribute("id");
0494         checkIfFound();
0495 
0496         traverser.setLocationWithinModule(context + ".getLevel()");
0497         current.setAttribute("level");
0498         checkIfFound();
0499     }
0500 
0501     public final void visitLeave(final Subsection subsection) {
0502         leave();
0503     }
0504 
0505     public final void visitEnter(final Node nodethrows ModuleDataException {
0506         enter("NODE");
0507         final String method = "visitEnter(Node)";
0508         Trace.param(CLASS, this, method, "current", current);
0509         final String context = traverser.getCurrentContext().getLocationWithinModule();
0510         checkMatching(method);
0511 
0512         traverser.setLocationWithinModule(context + ".getId()");
0513         current.setAttribute("id");
0514         checkIfFound();
0515 
0516         traverser.setLocationWithinModule(context + ".getLevel()");
0517         current.setAttribute("level");
0518         checkIfFound();
0519 
0520         // we dont't differentiate the different node types here and point to the parent element
0521         traverser.setLocationWithinModule(context + ".getNodeType()");
0522         current.setAttribute(null);
0523         checkIfFound();
0524 
0525     }
0526 
0527     public final void visitLeave(final Node node) {
0528         leave();
0529     }
0530 
0531     public final void visitEnter(final Axiom axiomthrows ModuleDataException {
0532         enter("AXIOM");
0533         final String method = "visitEnter(Axiom)";
0534         Trace.param(CLASS, this, method, "current", current);
0535         final String context = traverser.getCurrentContext().getLocationWithinModule();
0536         checkMatching(method);
0537 
0538         traverser.setLocationWithinModule(context + ".getDefinedOperator()");
0539         current.setAttribute("definedOperator");
0540         checkIfFound();
0541     }
0542 
0543     public final void visitLeave(final Axiom axiom) {
0544         leave();
0545     }
0546 
0547     public final void visitEnter(final Proposition propositionthrows ModuleDataException {
0548         enter("THEOREM");
0549         final String method = "visitEnter(Proposition)";
0550         Trace.param(CLASS, this, method, "current", current);
0551         checkMatching(method);
0552     }
0553 
0554     public final void visitLeave(final Proposition proposition) {
0555         leave();
0556     }
0557 
0558     public final void visitEnter(final ProofList proofListthrows ModuleDataException {
0559         final String method = "visitEnter(ProofList)";
0560         // because no equivalent level of "getProofList()" exists in the XSD we simply
0561         // point to the current location that must be within the element "THEOREM" or "RULE"
0562         checkMatching(method);
0563     }
0564 
0565     public final void visitEnter(final Proof proofthrows ModuleDataException {
0566         enter("PROOF");
0567         final String method = "visitEnter(Proof)";
0568         Trace.param(CLASS, this, method, "current", current);
0569         final String context = traverser.getCurrentContext().getLocationWithinModule();
0570         checkMatching(method);
0571 
0572         traverser.setLocationWithinModule(context + ".getKind()");
0573         current.setAttribute("kind");
0574         checkIfFound();
0575 
0576         traverser.setLocationWithinModule(context + ".getLevel()");
0577         current.setAttribute("level");
0578         checkIfFound();
0579     }
0580 
0581     public final void visitLeave(final Proof proof) {
0582         leave();
0583     }
0584 
0585     public final void visitEnter(final FormalProofList proofListthrows ModuleDataException {
0586         final String method = "visitEnter(FormalProofList)";
0587         // because no equivalent level of "getProofList()" exists in the XSD we simply
0588         // point to the current location that must be within the element "THEOREM"
0589         checkMatching(method);
0590     }
0591 
0592     public final void visitEnter(final FormalProof proofthrows ModuleDataException {
0593         enter("FORMAL_PROOF");
0594         final String method = "visitEnter(FormalProof)";
0595         Trace.param(CLASS, this, method, "current", current);
0596         checkMatching(method);
0597     }
0598 
0599     public final void visitLeave(final FormalProof proof) {
0600         leave();
0601     }
0602 
0603     public final void visitEnter(final FormalProofLineList listthrows ModuleDataException {
0604         enter("LINES");
0605         final String method = "visitEnter(FormalProofLineList)";
0606         Trace.param(CLASS, this, method, "current", current);
0607         checkMatching(method);
0608     }
0609 
0610     public final void visitLeave(final FormalProofLineList list) {
0611         leave();
0612     }
0613 
0614     public final void visitEnter(final FormalProofLine linethrows ModuleDataException {
0615         enter("L");
0616         final String method = "visitEnter(FormalProofLine)";
0617         Trace.param(CLASS, this, method, "current", current);
0618         final String context = traverser.getCurrentContext().getLocationWithinModule();
0619         checkMatching(method);
0620 
0621         traverser.setLocationWithinModule(context + ".getLabel()");
0622         current.setAttribute("label");
0623         checkIfFound();
0624     }
0625 
0626     public final void visitLeave(final FormalProofLine line) {
0627         leave();
0628     }
0629 
0630     public final void visitEnter(final ConditionalProof reasonthrows ModuleDataException {
0631         enter("CP");
0632         final String method = "visitEnter(ConditionalProof)";
0633         Trace.param(CLASS, this, method, "current", current);
0634         checkMatching(method);
0635     }
0636 
0637     public final void visitLeave(final ConditionalProof reason) {
0638         leave();
0639     }
0640 
0641     public final void visitEnter(final Reason reasonthrows ModuleDataException {
0642         // nothing to enter in XML
0643         final String method = "visitEnter(Reason)";
0644         Trace.param(CLASS, this, method, "current", current);
0645         checkMatching(method);
0646 
0647     }
0648 
0649     public final void visitLeave(final Reason reason) {
0650         // nothing to leave in XML
0651     }
0652 
0653     public final void visitEnter(final Add reasonthrows ModuleDataException {
0654         enter("ADD");
0655         final String method = "visitEnter(Add)";
0656         Trace.param(CLASS, this, method, "current", current);
0657         final String context = traverser.getCurrentContext().getLocationWithinModule();
0658         checkMatching(method);
0659 
0660         traverser.setLocationWithinModule(context + ".getReference()");
0661         current.setAttribute("ref");
0662         checkIfFound();
0663     }
0664 
0665     public final void visitLeave(final Add reason) {
0666         leave();
0667     }
0668 
0669     public final void visitEnter(final ModusPonens reasonthrows ModuleDataException {
0670         enter("MP");
0671         final String method = "visitEnter(ModusPonens)";
0672         Trace.param(CLASS, this, method, "current", current);
0673         final String context = traverser.getCurrentContext().getLocationWithinModule();
0674         checkMatching(method);
0675 
0676         traverser.setLocationWithinModule(context + ".getReference1()");
0677         current.setAttribute("ref1");
0678         checkIfFound();
0679 
0680         traverser.setLocationWithinModule(context + ".getReference2()");
0681         current.setAttribute("ref2");
0682         checkIfFound();
0683     }
0684 
0685     public final void visitLeave(final ModusPonens reason) {
0686         leave();
0687     }
0688 
0689     public final void visitEnter(final Rename reasonthrows ModuleDataException {
0690         enter("RENAME");
0691         final String method = "visitEnter(Add)";
0692         Trace.param(CLASS, this, method, "current", current);
0693         final String context = traverser.getCurrentContext().getLocationWithinModule();
0694         checkMatching(method);
0695 
0696         traverser.setLocationWithinModule(context + ".getReference()");
0697         current.setAttribute("ref");
0698         checkIfFound();
0699 
0700         traverser.setLocationWithinModule(context + ".getOccurrence()");
0701         current.setAttribute("occurrence");
0702         checkIfFound();
0703     }
0704 
0705     public final void visitLeave(final Rename reason) {
0706         leave();
0707     }
0708 
0709     public final void visitEnter(final SubstFree reasonthrows ModuleDataException {
0710         enter("SUBST_FREE");
0711         final String method = "visitEnter(SubstFree)";
0712         Trace.param(CLASS, this, method, "current", current);
0713         final String context = traverser.getCurrentContext().getLocationWithinModule();
0714         checkMatching(method);
0715 
0716         traverser.setLocationWithinModule(context + ".getReference()");
0717         current.setAttribute("ref");
0718         checkIfFound();
0719     }
0720 
0721     public final void visitLeave(final SubstFree reason) {
0722         leave();
0723     }
0724 
0725     public final void visitEnter(final SubstFunc reasonthrows ModuleDataException {
0726         enter("SUBST_FUNVAR");
0727         final String method = "visitEnter(SubstFunc)";
0728         Trace.param(CLASS, this, method, "current", current);
0729         final String context = traverser.getCurrentContext().getLocationWithinModule();
0730         checkMatching(method);
0731 
0732         traverser.setLocationWithinModule(context + ".getReference()");
0733         current.setAttribute("ref");
0734         checkIfFound();
0735     }
0736 
0737     public final void visitLeave(final SubstFunc reason) {
0738         leave();
0739     }
0740 
0741     public final void visitEnter(final SubstPred reasonthrows ModuleDataException {
0742         enter("SUBST_PREDVAR");
0743         final String method = "visitEnter(SubstPred)";
0744         Trace.param(CLASS, this, method, "current", current);
0745         final String context = traverser.getCurrentContext().getLocationWithinModule();
0746         checkMatching(method);
0747 
0748         traverser.setLocationWithinModule(context + ".getReference()");
0749         current.setAttribute("ref");
0750         checkIfFound();
0751     }
0752 
0753     public final void visitLeave(final SubstPred reason) {
0754         leave();
0755     }
0756 
0757     public final void visitEnter(final Existential reasonthrows ModuleDataException {
0758         enter("EXISTENTIAL");
0759         final String method = "visitEnter(Existential)";
0760         Trace.param(CLASS, this, method, "current", current);
0761         final String context = traverser.getCurrentContext().getLocationWithinModule();
0762         checkMatching(method);
0763 
0764         traverser.setLocationWithinModule(context + ".getReference()");
0765         current.setAttribute("ref");
0766         checkIfFound();
0767     }
0768 
0769     public final void visitLeave(final Existential reason) {
0770         leave();
0771     }
0772 
0773     public final void visitEnter(final Universal reasonthrows ModuleDataException {
0774         enter("UNIVERSAL");
0775         final String method = "visitEnter(Universal)";
0776         Trace.param(CLASS, this, method, "current", current);
0777         final String context = traverser.getCurrentContext().getLocationWithinModule();
0778         checkMatching(method);
0779 
0780         traverser.setLocationWithinModule(context + ".getReference()");
0781         current.setAttribute("ref");
0782         checkIfFound();
0783     }
0784 
0785     public final void visitLeave(final Universal reason) {
0786         leave();
0787     }
0788 
0789     public final void visitEnter(final Hypothesis hypothesisthrows ModuleDataException {
0790         enter("HYPOTHESIS");
0791         final String method = "visitEnter(Hypothesis)";
0792         Trace.param(CLASS, this, method, "current", current);
0793         final String context = traverser.getCurrentContext().getLocationWithinModule();
0794         checkMatching(method);
0795 
0796         traverser.setLocationWithinModule(context + ".getLabel()");
0797         current.setAttribute("label");
0798         checkIfFound();
0799     }
0800 
0801     public final void visitLeave(final Hypothesis hypothesis) {
0802         leave();
0803     }
0804 
0805     public final void visitEnter(final Conclusion conclusionthrows ModuleDataException {
0806         enter("CONCLUSION");
0807         final String method = "visitEnter(Conclusion)";
0808         Trace.param(CLASS, this, method, "current", current);
0809         final String context = traverser.getCurrentContext().getLocationWithinModule();
0810         checkMatching(method);
0811 
0812         traverser.setLocationWithinModule(context + ".getLabel()");
0813         current.setAttribute("label");
0814         checkIfFound();
0815     }
0816 
0817     public final void visitLeave(final Conclusion conclusion) {
0818         leave();
0819     }
0820 
0821     public final void visitEnter(final InitialPredicateDefinition definitionthrows ModuleDataException {
0822         enter("DEFINITION_PREDICATE_INITIAL");
0823         final String method = "visitEnter(InitialPredicateDefinition)";
0824         Trace.param(CLASS, this, method, "current", current);
0825         final String context = traverser.getCurrentContext().getLocationWithinModule();
0826         checkMatching(method);
0827 
0828         traverser.setLocationWithinModule(context + ".getArgumentNumber()");
0829         current.setAttribute("arguments");
0830         checkIfFound();
0831 
0832         traverser.setLocationWithinModule(context + ".getName()");
0833         current.setAttribute("name");
0834         checkIfFound();
0835 
0836         traverser.setLocationWithinModule(context + ".getLatexPattern()");
0837         enter("LATEXPATTERN");
0838         if (find.getLocationWithinModule().equals(traverser.getCurrentContext()
0839                 .getLocationWithinModule())) {
0840             if (definition.getLatexPattern() == null) { // NOT FOUND
0841                 leave();
0842             }
0843             throw new LocationFoundException(traverser.getCurrentContext());
0844         }
0845         leave();
0846     }
0847 
0848     public final void visitLeave(final InitialPredicateDefinition definition) {
0849         leave();
0850     }
0851 
0852     public final void visitEnter(final PredicateDefinition definitionthrows ModuleDataException {
0853         enter("DEFINITION_PREDICATE");
0854         final String method = "visitEnter(PredicateDefinition)";
0855         Trace.param(CLASS, this, method, "current", current);
0856         final String context = traverser.getCurrentContext().getLocationWithinModule();
0857         checkMatching(method);
0858 
0859         traverser.setLocationWithinModule(context + ".getArgumentNumber()");
0860         current.setAttribute("arguments");
0861         checkIfFound();
0862 
0863         traverser.setLocationWithinModule(context + ".getName()");
0864         current.setAttribute("name");
0865         checkIfFound();
0866 
0867         traverser.setLocationWithinModule(context + ".getLatexPattern()");
0868         enter("LATEXPATTERN");
0869         if (find.getLocationWithinModule().equals(traverser.getCurrentContext()
0870                 .getLocationWithinModule())) {
0871             if (definition.getLatexPattern() == null) { // NOT FOUND
0872                 leave();
0873             }
0874             throw new LocationFoundException(traverser.getCurrentContext());
0875         }
0876         leave();
0877     }
0878 
0879     public final void visitLeave(final PredicateDefinition definition) {
0880         leave();
0881     }
0882 
0883     public final void visitEnter(final InitialFunctionDefinition definitionthrows ModuleDataException {
0884         enter("DEFINITION_FUNCTION_INITIAL");
0885         final String method = "visitEnter(InitialFunctionDefinition)";
0886         Trace.param(CLASS, this, method, "current", current);
0887         final String context = traverser.getCurrentContext().getLocationWithinModule();
0888         checkMatching(method);
0889 
0890         traverser.setLocationWithinModule(context + ".getArgumentNumber()");
0891         current.setAttribute("arguments");
0892         checkIfFound();
0893 
0894         traverser.setLocationWithinModule(context + ".getName()");
0895         current.setAttribute("name");
0896         checkIfFound();
0897 
0898         traverser.setLocationWithinModule(context + ".getLatexPattern()");
0899         enter("LATEXPATTERN");
0900         if (find.getLocationWithinModule().equals(traverser.getCurrentContext()
0901                 .getLocationWithinModule())) {
0902             if (definition.getLatexPattern() == null) { // NOT FOUND
0903                 leave();
0904             }
0905             throw new LocationFoundException(traverser.getCurrentContext());
0906         }
0907         leave();
0908     }
0909 
0910     public final void visitLeave(final InitialFunctionDefinition definition) {
0911         leave();
0912     }
0913 
0914     public final void visitEnter(final FunctionDefinition definitionthrows ModuleDataException {
0915         enter("DEFINITION_FUNCTION");
0916         final String method = "visitEnter(FunctionDefinition)";
0917         Trace.param(CLASS, this, method, "current", current);
0918         final String context = traverser.getCurrentContext().getLocationWithinModule();
0919         checkMatching(method);
0920 
0921         traverser.setLocationWithinModule(context + ".getArgumentNumber()");
0922         current.setAttribute("arguments");
0923         checkIfFound();
0924 
0925         traverser.setLocationWithinModule(context + ".getName()");
0926         current.setAttribute("name");
0927         checkIfFound();
0928 
0929         traverser.setLocationWithinModule(context + ".getLatexPattern()");
0930         enter("LATEXPATTERN");
0931         if (find.getLocationWithinModule().equals(traverser.getCurrentContext()
0932                 .getLocationWithinModule())) {
0933             if (definition.getLatexPattern() == null) { // NOT FOUND
0934                 leave();
0935             }
0936             throw new LocationFoundException(traverser.getCurrentContext());
0937         }
0938         leave();
0939     }
0940 
0941     public final void visitLeave(final FunctionDefinition definition) {
0942         leave();
0943     }
0944 
0945     public final void visitEnter(final Rule rulethrows ModuleDataException {
0946         enter("RULE");
0947         final String method = "visitEnter(Rule)";
0948         Trace.param(CLASS, this, method, "current", current);
0949         final String context = traverser.getCurrentContext().getLocationWithinModule();
0950         checkMatching(method);
0951 
0952         traverser.setLocationWithinModule(context + ".getName()");
0953         current.setAttribute("name");
0954         checkIfFound();
0955 
0956         traverser.setLocationWithinModule(context + ".getVersion()");
0957         current.setAttribute("version");
0958         checkIfFound();
0959     }
0960 
0961     public final void visitLeave(final Rule rule) {
0962         leave();
0963     }
0964 
0965     public final void visitEnter(final ChangedRuleList listthrows ModuleDataException {
0966         final String method = "visitEnter(ChangedRuleList)";
0967         // because no equivalent level of "getChangedRuleList()" exists in the XSD we simply
0968         // point to the current location that must be within the element "RULE"
0969         checkMatching(method);
0970     }
0971 
0972     public final void visitLeave(final ChangedRuleList list) {
0973         traverser.setBlocked(false);  // free node search again
0974     }
0975 
0976     public final void visitEnter(final ChangedRule rulethrows ModuleDataException {
0977         enter("CHANGED_RULE");
0978         final String method = "visitEnter(ChangedRule)";
0979         Trace.param(CLASS, this, method, "current", current);
0980         final String context = traverser.getCurrentContext().getLocationWithinModule();
0981         checkMatching(method);
0982 
0983         traverser.setLocationWithinModule(context + ".getName()");
0984         current.setAttribute("name");
0985         checkIfFound();
0986 
0987         traverser.setLocationWithinModule(context + ".getVersion()");
0988         current.setAttribute("version");
0989         checkIfFound();
0990     }
0991 
0992     public final void visitLeave(final ChangedRule rule) {
0993         leave();
0994     }
0995 
0996     public final void visitEnter(final LinkList linkListthrows ModuleDataException {
0997         final String method = "visitEnter(LinkList)";
0998         Trace.param(CLASS, this, method, "current", current);
0999         final String context = traverser.getCurrentContext().getLocationWithinModule();
1000         checkMatching(method);
1001 
1002         for (int i = 0; i < linkList.size(); i++) {
1003             enter("LINK");
1004             if (linkList.get(i!= null) {
1005                 traverser.setLocationWithinModule(context + ".get(" + i + ")");
1006                 current.setAttribute("id");
1007                 checkIfFound();
1008             }
1009             leave();
1010         };
1011     }
1012 
1013     public final void visitLeave(final LinkList linkList) {
1014         // nothing to do
1015     }
1016 
1017     public final void visitEnter(final Formula formulathrows ModuleDataException {
1018         enter("FORMULA");
1019         final String method = "visitEnter(Formula)";
1020         Trace.param(CLASS, this, method, "current", current);
1021         checkMatching(method);
1022     }
1023 
1024     public final void visitLeave(final Formula formula) {
1025         leave();
1026     }
1027 
1028     public final void visitEnter(final Term termthrows ModuleDataException {
1029         enter("TERM");
1030         final String method = "visitEnter(Term)";
1031         Trace.param(CLASS, this, method, "current", current);
1032         checkMatching(method);
1033     }
1034 
1035     public final void visitLeave(final Term term) {
1036         leave();
1037     }
1038 
1039     public final void visitEnter(final ElementList listthrows ModuleDataException {
1040         final String operator = list.getOperator();
1041         enter(operator);
1042         final String method = "visitEnter(ElementList)";
1043         Trace.param(CLASS, this, method, "current", current);
1044         String context = traverser.getCurrentContext().getLocationWithinModule();
1045 
1046         // to find something like getElement(0).getList().getElement(0)
1047         if (context.startsWith(find.getLocationWithinModule())) {
1048             throw new LocationFoundException(find);
1049         }
1050 
1051         checkMatching(method);
1052 
1053         traverser.setLocationWithinModule(context + ".getOperator()");
1054         checkIfFound();
1055         traverser.setLocationWithinModule(context);
1056         final boolean firstIsAtom = list.size() && list.getElement(0).isAtom();
1057         if (firstIsAtom) {
1058             traverser.setLocationWithinModule(context + ".getElement(0)");
1059             if ("VAR".equals(operator|| "PREDVAR".equals(operator)
1060                     || "FUNVAR".equals(operator)) {
1061                 current.setAttribute("id");
1062                 checkIfFound();
1063                 traverser.setLocationWithinModule(context + ".getElement(0).getAtom()");
1064                 checkIfFound();
1065             else if ("PREDCON".equals(operator|| "FUNCON".equals(operator)) {
1066                 current.setAttribute("ref");
1067                 checkIfFound();
1068                 traverser.setLocationWithinModule(context + ".getElement(0).getAtom()");
1069                 checkIfFound();
1070             else {    // should not occur, but just in case
1071                 current.setAttribute(null);
1072                 Trace.info(CLASS, this, method, "unknown operator " + operator);
1073                 throw new LocationFoundException(traverser.getCurrentContext());
1074             }
1075         }
1076     }
1077 
1078     public final void visitLeave(final ElementList list) {
1079         leave();
1080     }
1081 
1082 /* we dont need it any more
1083     public final void visitEnter(final Atom atom) throws ModuleDataException {
1084         final String method = "visitEnter(Atom)";
1085         Trace.param(this, method, "current", current);
1086         final String context = traverser.getCurrentContext().getLocationWithinModule();
1087         // mime 20070217: should never occur
1088         checkMatching(method);
1089     }
1090 */
1091     public final void visitEnter(final LiteratureItemList listthrows ModuleDataException {
1092         enter("BIBLIOGRAPHY");
1093         final String method = "visitEnter(LiteratureItemList)";
1094         Trace.param(CLASS, this, method, "current", current);
1095         checkMatching(method);
1096     }
1097 
1098     public final void visitLeave(final LiteratureItemList list) {
1099         leave();
1100     }
1101 
1102     public final void visitEnter(final LiteratureItem itemthrows ModuleDataException {
1103         enter("ITEM");
1104         final String method = "visitEnter(LiteratureItem)";
1105         Trace.param(CLASS, this, method, "current", current);
1106         final String context = traverser.getCurrentContext().getLocationWithinModule();
1107         checkMatching(method);
1108 
1109         traverser.setLocationWithinModule(context + ".getLabel()");
1110         current.setAttribute("label");
1111         checkIfFound();
1112     }
1113 
1114     public final void visitLeave(final LiteratureItem item) {
1115         leave();
1116     }
1117 
1118     /**
1119      * Check if searched for context is already reached.
1120      *
1121      @throws  LocationFoundException  We have found it.
1122      */
1123     private final void checkIfFound() throws LocationFoundException {
1124         if (find.getLocationWithinModule().equals(traverser.getCurrentContext()
1125                 .getLocationWithinModule())) {
1126             throw new LocationFoundException(traverser.getCurrentContext());
1127         }
1128     }
1129 
1130     /**
1131      * Checks if the current context matches the beginning of the context we want to find.
1132      * This method must be called at the beginning of the <code>visitEnter</code> method when
1133      {@link #current} is correctly set. If the context of a previously visited node was already
1134      * matching and the current node doesn't start with the old matching context any longer we
1135      * throw a {@link LocationNotFoundException}.
1136      *
1137      @param   method  Method we were called from.
1138      @throws  LocationNotFoundException   Not found.
1139      @throws  LocationFoundException      Success!
1140      */
1141     private final void checkMatching(final String method)
1142             throws LocationNotFoundException, LocationFoundException {
1143         final String context = traverser.getCurrentContext().getLocationWithinModule();
1144         if (find.getLocationWithinModule().startsWith(context)) {
1145             Trace.info(CLASS, this, method, "beginning matches");
1146             Trace.paramInfo(CLASS, this, method, "context", context);
1147             matching = true;
1148             matchingBegin = context;                    // remember matching context
1149             matchingPath = new SimpleXPath(current);    // remember last matching XPath
1150         else {
1151             if (context.startsWith(find.getLocationWithinModule())) {
1152                 // our current location is more specific than our search location
1153                 // so the current location is the best match for our search
1154                 throw new LocationFoundException(traverser.getCurrentContext());
1155             }
1156             if (matching) {
1157                 // for example we are looking for "getHeader().getImportList().getImport(2)"
1158                 // getHeader()                    matches, we remember "getHeader()"
1159                 // getHeader().getSpecification() doesn't match, but still starts with "getHeader()"
1160                 // getHeader().getImportList()    matches, we remember "getHeader.getImportList()"
1161                 // getHeader().getImportList().get(0)  doesn't match but still starts with
1162                 //                                     "getHeader.getImportList()"
1163                 if (!context.startsWith(matchingBegin)) {
1164                     // Matching lost, that means we will never found the location
1165                     // so what can we do? We just return the last matching location and hope
1166                     // it is close enough to the searched one. But at least we do some
1167                     // logging here:
1168                     Trace.info(CLASS, this, method, "matching lost, when finding error location");
1169                     Trace.paramInfo(CLASS, this, method, "last match     ", matchingBegin);
1170                     Trace.paramInfo(CLASS, this, method, "current context", context);
1171                     Trace.paramInfo(CLASS, this, method, "find context   ", find.getLocationWithinModule());
1172 
1173                     Trace.traceStack(CLASS, this, method);
1174                     Trace.info(CLASS, this, method, "changing XPath to last matching one");
1175 
1176                     // do we really want to fail?
1177                     if (Boolean.TRUE.toString().equalsIgnoreCase(
1178                             System.getProperty("qedeq.test.xmlLocationFailures"))) {
1179                         throw new LocationNotFoundException(traverser.getCurrentContext(),
1180                             matchingBegin, find.getLocationWithinModule());
1181                     }
1182 
1183                     // now we change the current XPath to the last matching one because the
1184                     // contents of "current" is used as the resulting XPath later on when
1185                     // catching the exception in {@link #find()}
1186                     current = matchingPath;
1187                     throw new LocationFoundException(new ModuleContext(find.getModuleLocation(),
1188                         matchingBegin));
1189                 }
1190             }
1191             traverser.setBlocked(true);   // block further search in sub nodes
1192         }
1193         checkIfFound();
1194     }
1195 
1196     /**
1197      * Enter new XML element.
1198      *
1199      @param   element     Element name.
1200      */
1201     private final void enter(final String element) {
1202         level++;
1203         current.addElement(element, addOccurence(element));
1204     }
1205 
1206     /**
1207      * Leave last XML element.
1208      */
1209     private final void leave() {
1210         level--;
1211         current.deleteLastElement();
1212         traverser.setBlocked(false);  //  enable further search in nodes
1213     }
1214 
1215     /**
1216      * Add element occurrence. For example we have <code>getHeader().getImportList().get(2)</code>
1217      * and we want to get <code>QEDEQ/HEADER/IMPORTS/IMPORT[3]</code>.
1218      * So we call <code>enter("QEDEQ")</code><code>enter("HEADER")</code>,
1219      <code>enter("IMPORTS")</code> and last but not least
1220      * three times the sequence <code>enter("IMPORT")</code><code>leave("IMPORT")</code>,
1221      *
1222      @param   name    Element that occurred.
1223      @return  Number of occurrences including this one.
1224      */
1225     private final int addOccurence(final String name) {
1226         while (level < elements.size()) {
1227             elements.remove(elements.size() 1);
1228         }
1229         while (level > elements.size()) {
1230             elements.add(new HashMap());
1231         }
1232         final Map levelMap = (Mapelements.get(level - 1);
1233         final Enumerator counter;
1234         if (levelMap.containsKey(name)) {
1235             counter = (EnumeratorlevelMap.get(name);
1236             counter.increaseNumber();
1237         else {
1238             counter = new Enumerator(1);
1239             levelMap.put(name, counter);
1240         }
1241         return counter.getNumber();
1242     }
1243 
1244 }