home *** CD-ROM | disk | FTP | other *** search
/ Online Today 2000 January / Onto0100.iso / pc / JAVA / MSJAVX86.EXE / xmldso.cab / com / ms / xml / parser / ContentModel.class (.txt) < prev    next >
Encoding:
Java Class File  |  1998-11-05  |  7.4 KB  |  405 lines

  1. package com.ms.xml.parser;
  2.  
  3. import com.ms.xml.om.Element;
  4. import com.ms.xml.om.ElementImpl;
  5. import com.ms.xml.util.Atom;
  6. import com.ms.xml.util.Name;
  7. import com.ms.xml.util.XMLOutputStream;
  8. import java.io.IOException;
  9. import java.util.BitSet;
  10. import java.util.Enumeration;
  11. import java.util.Hashtable;
  12. import java.util.Vector;
  13.  
  14. public class ContentModel {
  15.    Node content;
  16.    Terminal end;
  17.    Vector terminalnodes;
  18.    Hashtable symboltable;
  19.    Vector symbols;
  20.    Vector Dtrans;
  21.    public static final byte EMPTY = 1;
  22.    public static final byte ANY = 2;
  23.    public static final byte ELEMENTS = 4;
  24.    byte type;
  25.    static Name nameEMPTY = Name.create("EMPTY", "XML");
  26.    static Name nameANY = Name.create("ANY", "XML");
  27.  
  28.    final Node parseList(Parser var1) throws ParseException {
  29.       Hashtable var2 = new Hashtable();
  30.       var2.put(var1.name, var1.name);
  31.       Object var3 = this.parseNode(var1);
  32.       int var4 = var1.token;
  33.       switch (var1.token) {
  34.          case 41:
  35.             return (Node)var3;
  36.          case 44:
  37.             var1.nextToken();
  38.             var3 = new Sequence((Node)var3, this.parseNode(var1));
  39.             break;
  40.          case 124:
  41.             var1.nextToken();
  42.             if (var1.token == -4) {
  43.                if (var2.contains(var1.name)) {
  44.                   var1.error("Warning: Repeated element in content model: " + var1.name);
  45.                } else {
  46.                   var2.put(var1.name, var1.name);
  47.                }
  48.             }
  49.  
  50.             var3 = new Choice((Node)var3, this.parseNode(var1));
  51.             break;
  52.          default:
  53.             var1.error("Illegal token in content model: " + var1.tokenString(var1.token));
  54.       }
  55.  
  56.       while(var1.token != 41) {
  57.          if (var4 == 44 && var1.token == 44) {
  58.             var1.nextToken();
  59.             var3 = new Sequence((Node)var3, this.parseNode(var1));
  60.          } else if (var4 == 124 && var1.token == 124) {
  61.             var1.nextToken();
  62.             if (var1.token == -4) {
  63.                if (var2.contains(var1.name)) {
  64.                   var1.error("Repeated element in content model: " + var1.name);
  65.                } else {
  66.                   var2.put(var1.name, var1.name);
  67.                }
  68.             }
  69.  
  70.             var3 = new Choice((Node)var3, this.parseNode(var1));
  71.          } else {
  72.             var1.error("Illegal token in content model: " + var1.tokenString(var1.token));
  73.          }
  74.       }
  75.  
  76.       return (Node)var3;
  77.    }
  78.  
  79.    public String toString() {
  80.       String var1;
  81.       switch (this.type) {
  82.          case 1:
  83.             var1 = "EMPTY";
  84.             break;
  85.          case 2:
  86.             var1 = "ANY";
  87.             break;
  88.          case 3:
  89.          default:
  90.             var1 = "*UNKNOWN*";
  91.             break;
  92.          case 4:
  93.             var1 = "ELEMENTS";
  94.       }
  95.  
  96.       return "Content: type=" + var1;
  97.    }
  98.  
  99.    final boolean checkContent(Context var1, Element var2, Parser var3) throws ParseException {
  100.       if (this.type == 2) {
  101.          var1.matched = true;
  102.          return true;
  103.       } else {
  104.          Object var4 = null;
  105.          Name var8;
  106.          if (var2.getType() == 11) {
  107.             Entity var5 = var3.dtd.findEntity(var2.getTagName());
  108.             if (var5.getLength() != -1) {
  109.                return true;
  110.             }
  111.  
  112.             var8 = Parser.namePCDATA;
  113.          } else if (var2.getType() == 1) {
  114.             var8 = Parser.namePCDATA;
  115.          } else {
  116.             var8 = var2.getTagName();
  117.          }
  118.  
  119.          if (var8 != null) {
  120.             Integer var9 = (Integer)this.symboltable.get(var8);
  121.             if (var9 != null) {
  122.                int var10 = var9;
  123.                int var7 = ((int[])this.Dtrans.elementAt(var1.state))[var10];
  124.                if (var7 == -1) {
  125.                   var3.error("Pattern mismatch in content of '" + var2.getParent().getTagName() + "'. Expected " + this.expectedElements(var1.state));
  126.                } else {
  127.                   var1.state = var7;
  128.                   var1.matched = ((int[])this.Dtrans.elementAt(var1.state))[this.symbols.size()] > 0;
  129.                }
  130.  
  131.                return true;
  132.             }
  133.  
  134.             Vector var6 = this.expectedElements(var1.state);
  135.             if (var6.isEmpty()) {
  136.                var3.error("Invalid element '" + var8 + "' in content of '" + var1.ed.name + "'.  Expected closing tag.");
  137.             } else {
  138.                var3.error("Invalid element '" + var8 + "' in content of '" + var1.ed.name + "'.  Expected " + var6);
  139.             }
  140.          } else {
  141.             var3.error("Invalid element in content of '" + var1.ed.name + "'");
  142.          }
  143.  
  144.          return false;
  145.       }
  146.    }
  147.  
  148.    final Node parseMixed(Parser var1) throws ParseException {
  149.       Hashtable var3 = new Hashtable();
  150.       var1.parseKeyword(-18, "PCDATA");
  151.       Object var2 = new Terminal(this, var1.name);
  152.       var3.put(var1.name, var1.name);
  153.       var1.nextToken();
  154.       switch (var1.token) {
  155.          case 41:
  156.             var2 = new Closure((Node)var2);
  157.             if (var1.lookahead == 42) {
  158.                var1.nextToken();
  159.             }
  160.             break;
  161.          case 124:
  162.             for(; var1.token == 124; var2 = new Choice((Node)var2, this.parseNode(var1))) {
  163.                var1.nextToken();
  164.                if (var1.token == -4) {
  165.                   if (var3.contains(var1.name)) {
  166.                      var1.error("Repeated element in content model: " + var1.name);
  167.                   } else {
  168.                      var3.put(var1.name, var1.name);
  169.                   }
  170.                }
  171.             }
  172.  
  173.             if (var1.token == 41) {
  174.                if (var1.lookahead == 42) {
  175.                   var1.nextToken();
  176.                   var2 = new Closure((Node)var2);
  177.                } else {
  178.                   var1.error("Expected '*' instead of: " + var1.tokenString(var1.token));
  179.                }
  180.             } else {
  181.                var1.error("Illegal token in content model: " + var1.tokenString(var1.token));
  182.             }
  183.             break;
  184.          default:
  185.             var1.error("Illegal token in content model: " + var1.tokenString(var1.token));
  186.       }
  187.  
  188.       var1.nextToken();
  189.       return (Node)var2;
  190.    }
  191.  
  192.    final Node finishNode(Parser var1, Node var2) throws ParseException {
  193.       Object var3;
  194.       switch (var1.lookahead) {
  195.          case 42:
  196.             var1.nextToken();
  197.             var3 = new Closure(var2);
  198.             break;
  199.          case 43:
  200.             var1.nextToken();
  201.             var3 = new ClosurePlus(var2);
  202.             break;
  203.          case 63:
  204.             var1.nextToken();
  205.             var3 = new Qmark(var2);
  206.             break;
  207.          default:
  208.             var3 = var2;
  209.       }
  210.  
  211.       var1.nextToken();
  212.       return (Node)var3;
  213.    }
  214.  
  215.    public Element toSchema() {
  216.       Object var1 = null;
  217.       switch (this.type) {
  218.          case 1:
  219.             var1 = new ElementImpl(nameEMPTY, 0);
  220.             break;
  221.          case 2:
  222.             var1 = new ElementImpl(nameANY, 0);
  223.          case 3:
  224.          default:
  225.             break;
  226.          case 4:
  227.             if (this.content != null) {
  228.                ElementImpl var2 = new ElementImpl(Name.create("DUMMYNODE"), 0);
  229.                ((Sequence)this.content).left.toSchema(35, 0, var2);
  230.                var1 = var2.getChild(0);
  231.             }
  232.       }
  233.  
  234.       return (Element)var1;
  235.    }
  236.  
  237.    public void save(Atom var1, XMLOutputStream var2) throws IOException {
  238.       switch (this.type) {
  239.          case 1:
  240.             var2.writeChars("EMPTY");
  241.             return;
  242.          case 2:
  243.             var2.writeChars("ANY");
  244.             return;
  245.          case 4:
  246.             if (this.content != null) {
  247.                ((Sequence)this.content).left.save(var2, 35, 0, var1);
  248.                return;
  249.             }
  250.          case 3:
  251.          default:
  252.       }
  253.    }
  254.  
  255.    public byte getType() {
  256.       return this.type;
  257.    }
  258.  
  259.    final boolean acceptEmpty(Context var1) {
  260.       if (this.type != 2 && this.type != 1) {
  261.          return ((int[])this.Dtrans.elementAt(var1.state))[this.symbols.size()] > 0;
  262.       } else {
  263.          return true;
  264.       }
  265.    }
  266.  
  267.    final Vector expectedElements(int var1) {
  268.       int[] var2 = (int[])this.Dtrans.elementAt(var1);
  269.       Vector var3 = new Vector();
  270.       Enumeration var4 = this.terminalnodes.elements();
  271.  
  272.       while(var4.hasMoreElements()) {
  273.          Name var5 = ((Terminal)var4.nextElement()).name;
  274.          if (var5 != null && !var3.contains(var5)) {
  275.             Integer var6 = (Integer)this.symboltable.get(var5);
  276.             if (var6 != null && var2[var6] != -1) {
  277.                var3.addElement(var5);
  278.             }
  279.          }
  280.       }
  281.  
  282.       return var3;
  283.    }
  284.  
  285.    final void initContent(Context var1, Parser var2) throws ParseException {
  286.       var1.state = 0;
  287.       if (this.Dtrans != null && this.Dtrans.size() > 0) {
  288.          var1.matched = ((int[])this.Dtrans.elementAt(var1.state))[this.symbols.size()] > 0;
  289.       } else {
  290.          var1.matched = true;
  291.       }
  292.    }
  293.  
  294.    final void parseModel(Parser var1) throws ParseException {
  295.       this.terminalnodes = new Vector();
  296.       this.symboltable = new Hashtable();
  297.       this.symbols = new Vector();
  298.       this.content = this.parseRootNode(var1);
  299.       this.end = new Terminal(this, (Name)null);
  300.       this.content = new Sequence(this.content, this.end);
  301.       int var2 = this.terminalnodes.size();
  302.       BitSet[] var3 = new BitSet[var2];
  303.  
  304.       for(int var4 = 0; var4 < var2; ++var4) {
  305.          var3[var4] = new BitSet(var2);
  306.       }
  307.  
  308.       this.content.calcfollowpos(var3);
  309.       Vector var17 = new Vector();
  310.       this.Dtrans = new Vector();
  311.       Vector var5 = new Vector();
  312.       Hashtable var6 = new Hashtable();
  313.       BitSet var7 = new BitSet(var2);
  314.       var6.put(var7, new Integer(-1));
  315.       int var8 = 0;
  316.       BitSet var9 = this.content.firstpos(var2);
  317.       var6.put(var9, new Integer(var17.size()));
  318.       var5.addElement(var9);
  319.       var17.addElement(var9);
  320.       int[] var10 = new int[this.symbols.size() + 1];
  321.       this.Dtrans.addElement(var10);
  322.       if (var9.get(this.end.pos)) {
  323.          var10[this.symbols.size()] = 1;
  324.       }
  325.  
  326.       while(var5.size() > 0) {
  327.          int[] var11 = (int[])this.Dtrans.elementAt(var8);
  328.          var9 = (BitSet)var5.elementAt(0);
  329.          var5.removeElementAt(0);
  330.  
  331.          for(int var12 = 0; var12 < this.symbols.size(); ++var12) {
  332.             Name var13 = (Name)this.symbols.elementAt(var12);
  333.             BitSet var14 = new BitSet(var2);
  334.  
  335.             for(int var15 = 0; var15 < var2; ++var15) {
  336.                if (var9.get(var15) && ((Terminal)this.terminalnodes.elementAt(var15)).name == var13) {
  337.                   var14.or(var3[var15]);
  338.                }
  339.             }
  340.  
  341.             Integer var20 = (Integer)var6.get(var14);
  342.             int var16;
  343.             if (var20 == null) {
  344.                var16 = var17.size();
  345.                var6.put(var14, new Integer(var16));
  346.                var5.addElement(var14);
  347.                var17.addElement(var14);
  348.                var10 = new int[this.symbols.size() + 1];
  349.                this.Dtrans.addElement(var10);
  350.                if (var14.get(this.end.pos)) {
  351.                   var10[this.symbols.size()] = 1;
  352.                }
  353.             } else {
  354.                var16 = var20;
  355.             }
  356.  
  357.             var11[var12] = var16;
  358.          }
  359.  
  360.          ++var8;
  361.       }
  362.  
  363.    }
  364.  
  365.    final Node parseNode(Parser var1) throws ParseException {
  366.       Object var2;
  367.       switch (var1.token) {
  368.          case -4:
  369.             var2 = new Terminal(this, var1.name);
  370.             break;
  371.          case 40:
  372.             var1.nextToken();
  373.             var2 = this.parseList(var1);
  374.             break;
  375.          default:
  376.             var2 = null;
  377.             var1.error("Illegal token in content model: " + var1.tokenString(var1.token));
  378.       }
  379.  
  380.       return this.finishNode(var1, (Node)var2);
  381.    }
  382.  
  383.    final Node parseRootNode(Parser var1) throws ParseException {
  384.       Object var2;
  385.       switch (var1.token) {
  386.          case -4:
  387.             var2 = new Terminal(this, var1.name);
  388.             break;
  389.          case 40:
  390.             var1.nextToken();
  391.             if (var1.token == 35) {
  392.                return this.parseMixed(var1);
  393.             }
  394.  
  395.             var2 = this.parseList(var1);
  396.             break;
  397.          default:
  398.             var2 = null;
  399.             var1.error("Expected ANY, EMPTY or '(' instead of: " + var1.tokenString(var1.token));
  400.       }
  401.  
  402.       return this.finishNode(var1, (Node)var2);
  403.    }
  404. }
  405.