home *** CD-ROM | disk | FTP | other *** search
/ Dynamic HTML in Action / Dynamicke-HTML-v-akci-covermount.bin / XML / PARSER / XMLINST.EXE / classes / com / ms / xml / parser / ElementDecl.java < prev    next >
Encoding:
Java Source  |  1998-05-26  |  12.6 KB  |  443 lines

  1. /*
  2.  * @(#)ElementDecl.java 1.0 6/3/97
  3.  * 
  4.  * Copyright (c) 1997 Microsoft, Corp. All Rights Reserved.
  5.  * 
  6.  */
  7.  
  8. package com.ms.xml.parser;
  9.  
  10. import com.ms.xml.om.ElementImpl;
  11. import com.ms.xml.om.Element;
  12. import com.ms.xml.om.ElementFactoryImpl;
  13. import com.ms.xml.util.Name;
  14. import com.ms.xml.util.Atom;
  15. import com.ms.xml.util.XMLOutputStream;
  16.  
  17. import java.lang.String;
  18. import java.util.Vector;
  19. import java.util.Enumeration;
  20. import java.net.URL;
  21. import java.io.IOException;
  22.  
  23. /**
  24.  * The class represents an element declaration in an XML Document Type Definition (DTD).
  25.  *
  26.  * @version 1.0, 6/3/97
  27.  */
  28. public class ElementDecl extends ElementImpl
  29. {    
  30.     /**
  31.      * name of element declared
  32.      */
  33.     Name name;
  34.     
  35.     /**
  36.      * attribute list
  37.      * @see AttDef
  38.      */    
  39.     private Vector attdefs;
  40.  
  41.     /**
  42.      * Shared content
  43.      */
  44.     private ContentModel content;
  45.  
  46.     /**
  47.      * Super class
  48.      */
  49.     ElementDecl base;
  50.  
  51.     /**
  52.      * Interfaces
  53.      */
  54.     Vector interfaces;
  55.  
  56.     /**
  57.      * Schema representation
  58.      */    
  59.     Element schema = null;
  60.  
  61.     ElementDecl(Name name)
  62.     {
  63.         super(name,Element.ELEMENTDECL);
  64.         this.name = name;
  65.     }
  66.     
  67.     /**
  68.      * Parse element declaration:
  69.      */
  70.     final void parseModel(Parser parser) throws ParseException
  71.     {
  72.         content = new ContentModel();
  73.         parser.parseKeyword(0, "EMPTY|...");
  74.  
  75.         // check for extends NAME
  76.         if (parser.token == Parser.EXTENDS)
  77.         {
  78.             parser.parseToken(Parser.NAME, "base element declaration");
  79.             base = parser.dtd.findElementDecl(parser.name);
  80.             if (base == null)
  81.             {
  82.                 parser.error("Didn't find element declaration to extend " + parser.name);
  83.             }
  84.             parser.parseKeyword(0, "EMPTY|...");
  85.         }
  86.  
  87.         // check for implements NAME, NAME, ...
  88.         if (parser.token == Parser.IMPLEMENTS)
  89.         {
  90.             interfaces = new Vector();
  91.             int i = parser.parseNames(interfaces, Parser.COMMA, null);
  92.             for (--i; i >= 0; i--)
  93.             {
  94.                 ElementDecl ed = parser.dtd.findElementDecl((Name)interfaces.elementAt(i));
  95.                 if (ed == null)
  96.                 {
  97.                     parser.error("Didn't find element declaration to implement " + interfaces.elementAt(i));
  98.                 }
  99.                 else
  100.                 {
  101.                     interfaces.setElementAt(ed, i);
  102.                 }
  103.             }
  104.             // parseNames called nextToken() already...
  105.             if (parser.token == Parser.NAME)
  106.             {
  107.                 parser.token = parser.lookup(name.getName());
  108.             }
  109.         }
  110.  
  111.         switch (parser.token)
  112.         {
  113.             case Parser.EMPTY:
  114.                 content.type = ContentModel.EMPTY;
  115.                 parser.nextToken();
  116.                 break;
  117.             case Parser.ANY:
  118.                 content.type = ContentModel.ANY;
  119.                 parser.nextToken();
  120.                 break;
  121.             case Parser.LPAREN:
  122.                 content.type = ContentModel.ELEMENTS;
  123.                 content.parseModel(parser);
  124.                 break;
  125.             case Parser.TAGEND:
  126.                 // it's ok to not to have content model if inherited
  127.                 if (base != null)
  128.                 {
  129.                     content = base.content;
  130.                     break;
  131.                 }
  132.             default:
  133.                 parser.error("Expected EMPTY, ANY, or '('.");
  134.         }
  135.         if (parser.token != Parser.TAGEND)
  136.         {
  137.             parser.error("Element declaration syntax error. Expected '>' instead of '" + parser.tokenString(parser.token) + "'");
  138.         }
  139.     }
  140.     
  141.     final void parseAttList(Parser parser) throws ParseException
  142.     {
  143.         int i;
  144.         Vector names;
  145.         AttDef attdef;       
  146.         parser.nextToken();
  147.         while (parser.token == Parser.NAME)
  148.         {
  149.             Name n = parser.name;
  150.  
  151.             // make sure XML-SPACE belongs to the XML namespace.
  152.             if (n.getName().equals(parser.nameXMLSpace.getName()))
  153.                 n = parser.nameXMLSpace;
  154.  
  155.             parser.parseKeyword(0, "Attdef");
  156.             switch (parser.token)
  157.             {
  158.                 case Parser.CDATA:
  159.                 case Parser.ID:
  160.                 case Parser.IDREF:
  161.                 case Parser.IDREFS:
  162.                 case Parser.ENTITY:
  163.                 case Parser.ENTITIES:
  164.                 case Parser.NMTOKEN:
  165.                 case Parser.NMTOKENS:
  166.                    attdef = new AttDef(n, Parser.CDATA - parser.token + AttDef.CDATA);
  167.                    break;
  168.                 case Parser.NOTATION:
  169.                     parser.parseToken(Parser.LPAREN, "(");
  170.                     names = new Vector();
  171.                     i = parser.parseNames(names, Parser.INVALIDTOKEN, null);
  172.                     for (--i; i >= 0; i--)
  173.                     {
  174.                         Name name = (Name)names.elementAt(i);
  175.                         if (parser.dtd.findNotation(name) == null)
  176.                         {
  177.                             parser.error("Notation not declared '" + name + "'");
  178.                         }
  179.                     }
  180.                     parser.parseToken(Parser.RPAREN, ")");
  181.                     attdef = new AttDef(n, AttDef.NOTATION, names);
  182.                     break;
  183.                 case Parser.LPAREN:
  184.                     parser.nametoken++;
  185.                     names = new Vector();
  186.                     i = parser.parseNames(names, Parser.OR, null);
  187.                     parser.nametoken--;
  188.                     if (parser.token != Parser.RPAREN)
  189.                     {
  190.                         parser.error("Expected )");
  191.                     }
  192.                     attdef = new AttDef(n, AttDef.ENUMERATION, names);
  193.                     break;
  194.                 default:
  195.                     attdef = null;
  196.                     parser.error("Unknown token in attlist declaration " + parser.token);
  197.                     break;
  198.             }
  199.        
  200.             if (parser.nextToken() == Parser.HASH)
  201.             {
  202.                 parser.parseKeyword(0, "attribute default");
  203.                 switch (parser.token)
  204.                 {
  205.                     case Parser.REQUIRED:
  206.                         attdef.presence = (byte)AttDef.REQUIRED;
  207.                         break;
  208.                     case Parser.IMPLIED:
  209.                         attdef.presence = (byte)AttDef.IMPLIED;
  210.                         break;
  211.                     case Parser.FIXED:    
  212.                         attdef.presence = (byte)AttDef.FIXED;
  213.                         break;
  214.                     default:
  215.                         parser.error("Expected 'REQUIRED', 'IMPLIED', or 'FIXED'.");
  216.                 }
  217.                 parser.nextToken();
  218.             }
  219.             if (attdef.presence == (byte)AttDef.FIXED || 
  220.                 attdef.presence == (byte)AttDef.DEFAULT)
  221.             {
  222.                 switch(parser.token)
  223.                 {
  224.                     case Parser.QUOTE:
  225.                         attdef.def = attdef.parseAttValue(this, parser, true);
  226.                         parser.nextToken();
  227.                         break;
  228.                     default:
  229.                         parser.error("Expected FIXED or DEFAULT value for " + attdef.name);
  230.                 }
  231.             }
  232.             addAttDef(attdef);
  233.         }
  234.     }
  235.     
  236.     final void initContent(Context context, Parser parser) throws ParseException
  237.     {
  238.         context.ed = this;
  239.         AttDef attdef = findAttDef(parser.nameXMLSpace);
  240.         if (attdef != null) {
  241.             Object defval = attdef.getDefault();
  242.             if (defval != null) {
  243.                 // The XML-SPACE declaration has a default value, which
  244.                 // should be used as default for context.preserveWS field.
  245.                 String s = (String)defval;
  246.                 context.preserveWS = s.equalsIgnoreCase("preserve");
  247.             }
  248.         }
  249.         content.initContent(context, parser);
  250.     }
  251.  
  252.     final boolean checkContent(Context context, Element e, Parser parser) throws ParseException
  253.     {
  254.         return content.checkContent(context, e, parser);
  255.     }
  256.  
  257.     final boolean acceptEmpty(Context context)
  258.     {
  259.         return content.acceptEmpty(context);
  260.     }
  261.  
  262.     final Vector expectedElements(int state)
  263.     {
  264.         return content.expectedElements(state);
  265.     }
  266.  
  267.     final void checkOwnAttributes(Element e, Parser parser) throws ParseException
  268.     {
  269.         if (attdefs == null) return;
  270.  
  271.         for (Enumeration en =  attdefs.elements(); en.hasMoreElements();)
  272.         {
  273.             AttDef ad = (AttDef)en.nextElement(); 
  274.             if (ad.getPresence() == AttDef.REQUIRED && e.getAttribute(ad.getName()) == null)
  275.                 parser.error("Attribute '" + ad.getName() + "' is required.");
  276.         }
  277.     }
  278.  
  279.     final void checkAttributes(Element e, Parser parser) throws ParseException
  280.     {
  281.         checkOwnAttributes(e, parser);
  282.         if (base != null)
  283.         {
  284.             base.checkOwnAttributes(e, parser);
  285.         }
  286.         if (interfaces != null)
  287.         {
  288.             for (Enumeration en = interfaces.elements(); en.hasMoreElements(); )
  289.             {
  290.                 ((ElementDecl)en.nextElement()).checkOwnAttributes(e, parser);
  291.             }
  292.         }
  293.     }
  294.  
  295.     /**
  296.      * Retrieves the content model object for the element declaration.
  297.      * @return  the content model for the element.
  298.      */
  299.     public final ContentModel getContent()
  300.     {
  301.         return content;
  302.     }
  303.  
  304.    /**
  305.     * Retrieves the name of the element declaration.
  306.     * @return  the <code>Name</code> object containing the element declaration 
  307.       * name.
  308.     */
  309.     public final Name getName()
  310.     {
  311.         return name;
  312.     }
  313.  
  314.     final void parseAttribute(Element e, Name name, Parser parser) throws ParseException
  315.     {
  316.         AttDef attdef = findAttDef(name);
  317.         if (attdef == null)
  318.         {
  319.             parser.error("Illegal attribute name " + name);
  320.         }
  321.         Object value = attdef.parseAttribute(e, parser);
  322.         e.setAttribute(name, value);
  323.     }
  324.     
  325.     final void addAttDef(AttDef attdef)
  326.     {
  327.         if (attdefs == null)
  328.         {
  329.             attdefs = new Vector();
  330.         }
  331.         attdefs.addElement(attdef);
  332.     }
  333.  
  334.     /**
  335.      * Retrieves the attribute definition of the named attribute.
  336.      * @param name  The name of the attribute.
  337.      * @return  an attribute definition object; returns null if it is not found.
  338.      */
  339.     public final AttDef findAttDef(Name name)
  340.     {
  341.         if (attdefs != null)
  342.         {
  343.             for (Enumeration en =  attdefs.elements(); en.hasMoreElements();)
  344.             {
  345.                 AttDef attdef = (AttDef)en.nextElement(); 
  346.                 if (attdef.name == name)
  347.                     return attdef;
  348.             }
  349.         }
  350.         if (base != null)
  351.         {
  352.             AttDef attdef = base.findAttDef(name);
  353.             if (attdef != null)
  354.                 return attdef;
  355.         }
  356.         if (interfaces != null)
  357.         {
  358.             for (Enumeration en = interfaces.elements(); en.hasMoreElements(); )
  359.             {
  360.                 AttDef attdef = ((ElementDecl)en.nextElement()).findAttDef(name);
  361.                 if (attdef != null)
  362.                     return attdef;
  363.             }
  364.         }
  365.         return null;
  366.     }
  367.  
  368.     public Element toSchema()
  369.     {
  370.         if( schema == null )
  371.         {
  372.             Element elementType = new ElementImpl( nameELEMENTTYPE, Element.ELEMENT );
  373.             elementType.setAttribute( nameID, name );
  374.  
  375.             Element elementContent = content.toSchema();
  376.             elementType.addChild( elementContent, null );
  377.  
  378.             if (attdefs != null) 
  379.             {
  380.                 Enumeration e = attdefs.elements();
  381.                 while (e.hasMoreElements()) 
  382.                 {
  383.                     AttDef def = (AttDef)e.nextElement();
  384.                     elementType.addChild( def.toSchema(), null );
  385.                 }
  386.             }
  387.  
  388.             schema = elementType;
  389.         }
  390.           
  391.         return schema;
  392.     }
  393.  
  394.     /**
  395.      * Saves the element declaration in DTD syntax to the given
  396.      * output stream.
  397.      * @param o  The output stream to write to.
  398.       * @return No return value.
  399.      * @exception  IOException if there is a problem writing to the output 
  400.       * stream.
  401.      */
  402.     public void save(XMLOutputStream o) throws IOException
  403.     {
  404.         o.writeIndent();
  405.         o.writeChars("<!ELEMENT ");
  406.         o.writeQualifiedName(name, null);
  407.         o.writeChars(" ");    
  408.         Atom ns = name.getNameSpace();
  409.         content.save(ns, o);
  410.         o.write('>');
  411.  
  412.         if (attdefs != null) {
  413.             // have to turn on PRETTY output for this to work properly.
  414.             int style = o.getOutputStyle();
  415.             if (style != XMLOutputStream.COMPACT)
  416.                 o.setOutputStyle(XMLOutputStream.PRETTY);
  417.             o.writeNewLine();
  418.             Enumeration e = attdefs.elements();
  419.             o.writeIndent();
  420.             o.writeChars("<!ATTLIST ");
  421.             o.writeQualifiedName(name, null);
  422.             o.writeChars(" ");
  423.             while (e.hasMoreElements()) {
  424.                 o.writeNewLine();
  425.                 AttDef def = (AttDef)e.nextElement();
  426.                 o.addIndent(1);
  427.                 o.writeIndent();
  428.                 o.addIndent(-1);
  429.                 def.save(ns, o);
  430.             }
  431.             o.write('>');
  432.             o.setOutputStyle(style);
  433.         } 
  434.         o.writeNewLine();        
  435.     }
  436.  
  437.     static Name nameELEMENTTYPE = Name.create("ELEMENTTYPE","XML");
  438.     static Name nameID = Name.create("ID", "XML");
  439. }
  440.  
  441.  
  442.  
  443.