src/java/isac/util/parser/XMLParserDigest.java
author mkoschuc
Mon, 27 Jun 2005 15:01:06 +0200
changeset 2540 d1e82a86ae1f
parent 2515 562479af0531
child 2767 6898d6fa86f6
permissions -rw-r--r--
MK: cosmetics
     1 /*
     2  * Created on Oct 31, 2003
     3  */
     4 package isac.util.parser;
     5 
     6 import isac.util.CalcChanged;
     7 import isac.util.Message;
     8 import isac.util.ResponseWrapper;
     9 import isac.util.formulae.Assumptions;
    10 import isac.util.formulae.CalcHead;
    11 import isac.util.formulae.KEStoreID;
    12 import isac.util.formulae.Model;
    13 import isac.util.formulae.ModelItem;
    14 import isac.util.formulae.ModelItemList;
    15 import isac.util.formulae.CalcHeadSimpleID;
    16 import isac.util.formulae.FormHeadsContainer;
    17 import isac.util.formulae.Formula;
    18 import isac.util.formulae.CalcFormula;
    19 import isac.util.formulae.Position;
    20 import isac.util.formulae.Specification;
    21 import isac.util.tactics.Rewrite;
    22 import isac.util.tactics.RewriteInst;
    23 import isac.util.tactics.RewriteSet;
    24 import isac.util.tactics.RewriteSetInst;
    25 import isac.util.tactics.SimpleTactic;
    26 import isac.util.tactics.StringListTactic;
    27 import isac.util.tactics.SubProblemTactic;
    28 import isac.util.tactics.TacticsContainer;
    29 import isac.util.tactics.Theorem;
    30 
    31 import java.io.BufferedReader;
    32 import java.io.FileNotFoundException;
    33 import java.io.FileReader;
    34 import java.io.IOException;
    35 import java.io.StringReader;
    36 
    37 import org.apache.commons.digester.Digester;
    38 import org.apache.log4j.Logger;
    39 import org.xml.sax.EntityResolver;
    40 import org.xml.sax.ErrorHandler;
    41 import org.xml.sax.InputSource;
    42 import org.xml.sax.SAXException;
    43 import org.xml.sax.SAXParseException;
    44 
    45 /**
    46  * parses Objects from XML-Output of the Kernel.
    47  * 
    48  * @author Richard Gradischnegg
    49  */
    50 public class XMLParserDigest {
    51 
    52     private Digester digester_;
    53 
    54     private String dtd_path_;
    55 
    56     class BridgeErrorHandler implements ErrorHandler {
    57 
    58         public void error(SAXParseException e) {
    59             System.out.println("---xml-error " + e);
    60         }
    61 
    62         public void fatalError(SAXParseException e) {
    63             System.out.println("---xml-fatalerror " + e);
    64         }
    65 
    66         public void warning(SAXParseException e) {
    67             System.out.println("---xml-warning " + e);
    68         }
    69     }
    70 
    71     // auxillary class for feeding the dtd_
    72     class BridgeEntityResolver implements EntityResolver {
    73 
    74         String dtd_;
    75 
    76         public BridgeEntityResolver(String dtd) {
    77             this.dtd_ = dtd;
    78         }
    79 
    80         public InputSource resolveEntity(String publicId, String systemId)
    81                 throws SAXException, IOException {
    82             if ((systemId != null) && systemId.endsWith("isac.dtd")) {
    83                 return new InputSource(new StringReader(dtd_));
    84             } else {
    85                 System.out.println("BridgeEntityResolver: return null");
    86                 return null;
    87             }
    88         }
    89     }
    90 
    91     static Logger logger_ = Logger.getLogger(XMLParserDigest.class.getName());
    92 
    93     /**
    94      * Constructor: create a new XMLParserDigest object and fill it with the
    95      * rules.
    96      * 
    97      * @param dtd_path_
    98      *            Path to the DTD-File (Document Type Description)
    99      */
   100     public XMLParserDigest(String dtdPath) {
   101         logger_.debug("XMLParserDigest: dtd_path_=" + dtdPath);
   102         digester_ = new Digester();
   103         digester_.setErrorHandler(new BridgeErrorHandler());
   104         this.dtd_path_ = dtdPath;
   105         //dtd_-File --> String (faster validating)
   106         StringBuffer sb;
   107         try {
   108             BufferedReader br = new BufferedReader(new FileReader(dtdPath));
   109             sb = new StringBuffer();
   110             while (br.ready()) {
   111                 sb.append(br.readLine() + "\n");
   112             }
   113             // Set dtd_ for parser validation
   114             digester_
   115                     .setEntityResolver(new BridgeEntityResolver(sb.toString()));
   116         } catch (FileNotFoundException e) {
   117             e.printStackTrace();
   118         } catch (IOException e) {
   119             e.printStackTrace();
   120         }
   121 
   122         // Rules for the digester_ to create Objects and fill them from
   123         // XML-Files
   124         digester_.addObjectCreate("ISAC", ResponseWrapper.class);
   125         digester_.addObjectCreate("*/CALCID", CalcHeadSimpleID.class);
   126         digester_.addCallMethod("*/CALCID", "setID", 0);
   127         digester_.addSetRoot("*/CALCID", "setCalcID");
   128 
   129         // Rules for parsing Position
   130         digester_.addObjectCreate("*/POSITION", Position.class);
   131         digester_.addCallMethod("*/POSITION/INTLIST/INT", "addInt", 0);
   132         digester_.addCallMethod("*/POSITION/POS", "setKind", 0);
   133         digester_.addSetNext("*/POSITION", "setResponse");
   134         //		digester_.addSetNext("*/POSITION", "setPosition");
   135 
   136         // 3 different Positions in CalcChangedEvent
   137         digester_.addObjectCreate("*/UNCHANGED", Position.class);
   138         digester_.addCallMethod("*/UNCHANGED/INTLIST/INT", "addInt", 0);
   139         digester_.addCallMethod("*/UNCHANGED/POS", "setKind", 0);
   140         digester_.addSetNext("*/UNCHANGED", "setLastUnchanged");
   141 
   142         digester_.addObjectCreate("*/DELETED", Position.class);
   143         digester_.addCallMethod("*/DELETED/INTLIST/INT", "addInt", 0);
   144         digester_.addCallMethod("*/DELETED/POS", "setKind", 0);
   145         digester_.addSetNext("*/DELETED", "setLastDeleted");
   146 
   147         digester_.addObjectCreate("*/GENERATED", Position.class);
   148         digester_.addCallMethod("*/GENERATED/INTLIST/INT", "addInt", 0);
   149         digester_.addCallMethod("*/GENERATED/POS", "setKind", 0);
   150         digester_.addSetNext("*/GENERATED", "setLastGenerated");
   151 
   152         // Rules for parsing Formula
   153         digester_.addObjectCreate("*/FORMULA", Formula.class);
   154         //CalcHeadItems have no <FORMULA> ...
   155         digester_.addCallMethod("*/MATHML/ISA", "setText", 0);
   156         digester_.addSetNext("*/FORMULA", "setFormula");
   157 
   158         // Rules for parsing CalcFormula with Position
   159         digester_.addObjectCreate("*/CALCFORMULA", CalcFormula.class);
   160         digester_.addSetNext("*/CALCFORMULA", "setResponse");
   161 
   162         //============== Rules for parsing CalcHead
   163         digester_.addObjectCreate("*/CALCHEAD", CalcHead.class);
   164         digester_.addSetProperties("*/CALCHEAD", "status", "statusString");
   165 
   166         digester_.addObjectCreate("*/HEAD/MATHML", Formula.class);
   167         digester_.addSetNext("*/HEAD/MATHML", "setHeadLine");
   168 
   169         digester_.addCallMethod("*/CALCHEAD/BELONGSTO", "setBelongsTo", 0);
   170 
   171         digester_.addObjectCreate("*/CALCHEAD/MODEL", Model.class);
   172         //..........................................................WN050624xx
   173         addItemList(digester_, "Given");
   174         addItemList(digester_, "Where");
   175         addItemList(digester_, "Find");
   176         addItemList(digester_, "Relate");
   177         digester_.addSetNext("*/CALCHEAD/MODEL", "setModel");
   178         //..........................................................WN050624xx
   179 
   180         digester_.addObjectCreate("*/CALCHEAD/SPECIFICATION",
   181                 Specification.class);
   182         digester_.addObjectCreate("*/CALCHEAD/SPECIFICATION/THEORYID",
   183                 CalcHeadSimpleID.class);
   184         digester_
   185                 .addCallMethod("*/CALCHEAD/SPECIFICATION/THEORYID", "setID", 0);
   186         digester_.addSetNext("*/CALCHEAD/SPECIFICATION/THEORYID", "setTheory");
   187         digester_.addObjectCreate("*/CALCHEAD/SPECIFICATION/PROBLEMID",
   188                 KEStoreID.class);
   189         digester_.addCallMethod(
   190                 "*/CALCHEAD/SPECIFICATION/PROBLEMID/STRINGLIST/STRING",
   191                 "addString", 0);
   192         digester_
   193                 .addSetNext("*/CALCHEAD/SPECIFICATION/PROBLEMID", "setProblem");
   194         digester_.addObjectCreate("*/CALCHEAD/SPECIFICATION/METHODID",
   195                 KEStoreID.class);
   196         digester_.addCallMethod(
   197                 "*/CALCHEAD/SPECIFICATION/METHODID/STRINGLIST/STRING",
   198                 "addString", 0);
   199         digester_.addSetNext("*/CALCHEAD/SPECIFICATION/METHODID", "setMethod");
   200         digester_.addSetNext("*/CALCHEAD/SPECIFICATION", "setSpecification");
   201         digester_.addSetNext("*/CALCHEAD", "setResponse");
   202 
   203         //============== Rules for parsing various Tactic Objects
   204         //	Rules for parsing SimpleTactic
   205         digester_.addObjectCreate("*/SIMPLETACTIC", SimpleTactic.class);
   206         digester_.addCallMethod("*/SIMPLETACTIC/MATHML/ISA", "setArgument", 0);
   207         digester_.addSetProperties("*/SIMPLETACTIC", "name", "name");
   208         digester_.addSetNext("*/SIMPLETACTIC", "setResponse");
   209 
   210         //	Rules for parsing KeyListTactic
   211         digester_.addObjectCreate("*/STRINGLISTTACTIC", StringListTactic.class);
   212         digester_.addCallMethod("*/STRINGLISTTACTIC/STRINGLIST/STRING",
   213                 "addKey", 0);
   214         digester_.addSetProperties("*/STRINGLISTTACTIC", "name", "name");
   215         digester_.addSetNext("*/STRINGLISTTACTIC", "setResponse");
   216 
   217         //  Rules for parsing Theorem
   218         digester_.addObjectCreate("*/THEOREM", Theorem.class);
   219         digester_.addCallMethod("*/THEOREM/ID", "setId", 0);
   220         digester_
   221                 .addCallMethod("*/THEOREM/FORMULA/MATHML/ISA", "setFormula", 0);
   222         digester_.addSetNext("*/THEOREM", "setTheorem");
   223 
   224         //  Rules for parsing RewriteTactic
   225         digester_.addObjectCreate("*/REWRITETACTIC", Rewrite.class);
   226         digester_.addSetProperties("*/REWRITETACTIC", "name", "name");
   227         digester_.addSetNext("*/REWRITETACTIC", "setResponse");
   228 
   229         //  Rules for parsing RewriteInstTactic
   230         digester_.addObjectCreate("*/REWRITEINSTTACTIC", RewriteInst.class);
   231         digester_.addSetProperties("*/REWRITEINSTTACTIC", "name", "name");
   232         digester_.addSetNext("*/REWRITEINSTTACTIC", "setResponse");
   233         digester_.addCallMethod(
   234                 "*/REWRITEINSTTACTIC/SUBSTITUTION/PAIR/VARIABLE/MATHML/ISA",
   235                 "setVariable", //WN0501 ^^^ this seems to work only on
   236                 // spec.case
   237                 0);
   238         digester_.addCallMethod(
   239                 "*/REWRITEINSTTACTIC/SUBSTITUTION/PAIR/VALUE/MATHML/ISA",
   240                 "setValue", //WN0501 ^^^ this seems to work only on spec_.case
   241                 0);
   242 
   243         //	Rules for parsing RewriteSetTactic
   244         digester_.addObjectCreate("*/REWRITESETTACTIC", RewriteSet.class);
   245         digester_.addCallMethod("*/REWRITESETTACTIC/RULESET", "setRuleSet", 0);
   246         digester_.addSetProperties("*/REWRITESETTACTIC", "name", "name");
   247         digester_.addSetNext("*/REWRITESETTACTIC", "setResponse");
   248 
   249         //	Rules for parsing RewriteSetInstTactic
   250         digester_.addObjectCreate("*/REWRITESETINSTTACTIC",
   251                 RewriteSetInst.class);
   252         digester_.addCallMethod("*/REWRITESETINSTTACTIC/RULESET", "setRuleSet",
   253                 0);
   254         digester_.addCallMethod(
   255                 "*/REWRITESETINSTTACTIC/SUBSTITUTION/PAIR/VARIABLE/MATHML/ISA",
   256                 "setVariable", //WN0501 ^^^ this seems to work only on
   257                 // spec_.case
   258                 0);
   259         digester_.addCallMethod(
   260                 "*/REWRITESETINSTTACTIC/SUBSTITUTION/PAIR/VALUE/MATHML/ISA",
   261                 "setValue", //WN0501 ^^^ this seems to work only on spec_.case
   262                 0);
   263         digester_.addSetProperties("*/REWRITESETINSTTACTIC", "name", "name");
   264         digester_.addSetNext("*/REWRITESETINSTTACTIC", "setResponse");
   265 
   266         // Rules for parsing SubProblemTactic
   267         digester_.addObjectCreate("*/SUBPROBLEMTACTIC", SubProblemTactic.class);
   268         digester_.addCallMethod("*/SUBPROBLEMTACTIC/THEORY", "setTheoryID", 0);
   269         digester_.addCallMethod("*/SUBPROBLEMTACTIC/PROBLEM/STRINGLIST/STRING",
   270                 "addProblemString", 0);
   271         digester_.addSetProperties("*/SUBPROBLEMTACTIC", "name", "name");
   272         digester_.addSetNext("*/SUBPROBLEMTACTIC", "setResponse");
   273 
   274         //	Rules for parsing CalcIterator move message
   275         digester_.addObjectCreate("*/CALCITERATOR/ERROR", Message.class);
   276         digester_.addCallMethod("*/CALCITERATOR/ERROR", "setError", 0);
   277         digester_.addSetNext("*/CALCITERATOR/ERROR", "setResponse");
   278 
   279         //	Rules for parsing CalcIterator constructor message
   280         digester_.addObjectCreate("*/ADDUSER", CalcHeadSimpleID.class);
   281         digester_.addCallMethod("*/ADDUSER/USERID", "setID", 0);
   282         digester_.addSetNext("*/ADDUSER", "setResponse");
   283 
   284         //  Rules for parsing autoCalculateResponse
   285         digester_.addCallMethod("*/AUTOCALC/ERROR", "setError", 0);
   286         digester_.addObjectCreate("*/CALCCHANGED", CalcChanged.class);
   287         digester_.addSetNext("*/CALCCHANGED", "setResponse");
   288 
   289         // Rules for parsing fetchApplicableTactics
   290         digester_.addObjectCreate("*/APPLICABLETACTICS/TACLIST",
   291                 TacticsContainer.class);
   292         digester_.addSetNext("*/APPLICABLETACTICS/TACLIST", "setResponse");
   293 
   294         // Rules for getElementsFromTo
   295         digester_.addObjectCreate("*/GETELEMENTSFROMTO/FORMHEADS",
   296                 FormHeadsContainer.class);
   297         digester_.addSetNext("*/GETELEMENTSFROMTO/FORMHEADS", "setResponse");
   298 
   299         // getAssumptions (and still getAccumulatedAsms)
   300         digester_.addObjectCreate("*/ASMLIST", Assumptions.class);
   301         digester_.addSetNext("*/ASMLIST", "setResponse");
   302     }
   303 
   304     /**
   305      * parse a ModelItemList
   306      * 
   307      * @param modPart
   308      *            is "GIVEN" or "WHERE" or "FIND" or "RELATE"
   309      */
   310     private void addItemList(Digester digester, String modPart) {
   311         String modPartUp = modPart.toUpperCase();
   312         // Rules for parsing ItemLists in the model part of a CalcHead: Given
   313         // Find Where Relate
   314         digester.addObjectCreate("*/CALCHEAD/MODEL/" + modPartUp,
   315                 ModelItemList.class);
   316         digester.addObjectCreate("*/CALCHEAD/MODEL/" + modPartUp + "/ITEM",
   317                 ModelItem.class);
   318         digester.addSetProperties("*/CALCHEAD/MODEL/" + modPartUp + "/ITEM",
   319                 "status", "itemStatus");
   320         digester.addCallMethod("*/CALCHEAD/MODEL/" + modPartUp
   321                 + "/ITEM/MATHML/ISA", "setText", 0);
   322         digester.addSetNext("*/CALCHEAD/MODEL/" + modPartUp + "/ITEM",
   323                 "addItem");
   324         digester.addSetNext("*/CALCHEAD/MODEL/" + modPartUp, "set" + modPart);
   325     }
   326 
   327     /**
   328      * Set whether or not using the DTD for validating
   329      * 
   330      * @param validating
   331      *            <UL>
   332      *            <LI>true: XML is tested for validity against DTD
   333      *            <LI>
   334      *            <LI>false: XML is only tested for well-formed-ness
   335      *            <LI>
   336      *            </UL>
   337      */
   338     public void setValidating(boolean validating) {
   339         logger_.warn("setValidating: validating=" + validating);
   340         digester_.setValidating(validating);
   341     }
   342 
   343     /**
   344      * Parse an XML string to Java Object(s)
   345      * 
   346      * @param xmlString
   347      *            the string containing the XML content
   348      * @return ResponseWrapper containing the CalcID and the parsed Object
   349      */
   350     public ResponseWrapper parse(String xmlString) {
   351         Object o = null;
   352         xmlString = "<?xml version=\"1.0\"?><!DOCTYPE ISAC SYSTEM \""
   353                 + dtd_path_ + "\"><ISAC>" + xmlString + "</ISAC>";
   354 
   355         encodeEntities(xmlString);
   356         try {
   357             digester_.clear();
   358             o = digester_.parse(new InputSource(new StringReader(xmlString)));
   359         } catch (IOException e) {
   360             e.printStackTrace();
   361         } catch (SAXException e) {
   362             e.printStackTrace();
   363         }
   364         ResponseWrapper wrapper = (ResponseWrapper) o;
   365         //System.out.println(wrapper.getCalcID().toSMLString());
   366         return wrapper;
   367     }
   368 
   369     public static void encodeEntities(String xmlString) {
   370         xmlString = xmlString.replaceAll(" & ", "&amp;");
   371         xmlString = xmlString.replaceAll(" > ", "&gt;");
   372         xmlString = xmlString.replaceAll(" < ", "&lt;");
   373     }
   374 
   375     public static void decodeEntities(String xmlString) {
   376         xmlString = xmlString.replaceAll("&amp;", " & ");
   377         xmlString = xmlString.replaceAll("&gt;", " > ");
   378         xmlString = xmlString.replaceAll("&lt;", " < ");
   379     }
   380 }