[Laszlo-checkins] r6726 - in openlaszlo/trunk: WEB-INF/lps/lfc/data WEB-INF/lps/lfc/views WEB-INF/lps/server/src/org/openlaszlo/compiler WEB-INF/lps/server/src/org/openlaszlo/i18n WEB-INF/lps/server/src/org/openlaszlo/servlets/responders lps/components/incubator test/compiler_errors test/lfc/data

hqm@openlaszlo.org hqm at openlaszlo.org
Thu Oct 4 15:49:40 PDT 2007


Author: hqm
Date: 2007-10-04 15:49:36 -0700 (Thu, 04 Oct 2007)
New Revision: 6726

Modified:
   openlaszlo/trunk/WEB-INF/lps/lfc/data/LzDataset.lzs
   openlaszlo/trunk/WEB-INF/lps/lfc/data/LzHTTPDataProvider.lzs
   openlaszlo/trunk/WEB-INF/lps/lfc/views/LzInputText.lzs
   openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/Canvas.java
   openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/CanvasCompiler.java
   openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ClassCompiler.java
   openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ClassModel.java
   openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/CompilationEnvironment.java
   openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/Compiler.java
   openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/FontCompiler.java
   openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ImportCompiler.java
   openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/LibraryCompiler.java
   openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/LibraryWriter.java
   openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/NodeModel.java
   openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/Parser.java
   openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ResourceCompiler.java
   openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/SWFWriter.java
   openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ToplevelCompiler.java
   openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ViewSchema.java
   openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ViewSchema_Test.java
   openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/i18n/laszlomessages.properties
   openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/servlets/responders/ResponderCompile.java
   openlaszlo/trunk/lps/components/incubator/textstyle.lzx
   openlaszlo/trunk/test/compiler_errors/bogus-attribute-error.lzx
   openlaszlo/trunk/test/compiler_errors/redfine-builtin.lzx
   openlaszlo/trunk/test/lfc/data/testheaderresponse.lzx
Log:
Change 20071004-hqm-2 by hqm at IBM-2E06404CB67 on 2007-10-04 18:43:58 EDT
    in /cygdrive/c/users/hqm/openlaszlo/trunk
    for http://svn.openlaszlo.org/openlaszlo/trunk

Summary:  replace jing validator with something better

New Features:

Bugs Fixed: LPP-4644

and other bugs too numerous to mention

Technical Reviewer: ptw
QA Reviewer: pbr
Doc Reviewer:

Documentation:

Release Notes:

Details:

removed JING RNG parser and validator, and all code in ViewSchema which uses it.

All validation is done from the lps/schema/lfc.lzx file now,
all validity  checks done in updateschema or during compilation by
NodeModel and friends.

The "validate" flag is deprecated (we should warn for that I guess),
and can be removed at some point.



Tests:

compiled demos, examples/components, smokecheck, webtop lzmail app
ant runlzunit

tested test cases in test/compiler_errors



Modified: openlaszlo/trunk/WEB-INF/lps/lfc/data/LzDataset.lzs
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/lfc/data/LzDataset.lzs	2007-10-04 20:08:12 UTC (rev 6725)
+++ openlaszlo/trunk/WEB-INF/lps/lfc/data/LzDataset.lzs	2007-10-04 22:49:36 UTC (rev 6726)
@@ -580,12 +580,12 @@
     var proxied_p = canvas.proxied;
     // check if this datasource has a "proxied" attribute which overrides canvas switch
     if (this.proxied != null && this.proxied != "inherit") {
-        proxied_p = (this.proxied == "true"); // coerce to boolean
+        proxied_p = (this.proxied == true); // coerce to boolean
     }
 
     // Check if the dataset has a "proxied" attribute which overrides dataset's value
     if (this.proxied != null && this.proxied != "inherit") {
-        proxied_p = (this.proxied == "true");
+        proxied_p = (this.proxied == true);
     }
     return proxied_p;
 }

Modified: openlaszlo/trunk/WEB-INF/lps/lfc/data/LzHTTPDataProvider.lzs
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/lfc/data/LzHTTPDataProvider.lzs	2007-10-04 20:08:12 UTC (rev 6725)
+++ openlaszlo/trunk/WEB-INF/lps/lfc/data/LzHTTPDataProvider.lzs	2007-10-04 22:49:36 UTC (rev 6726)
@@ -96,6 +96,9 @@
         tloader.setOption('timeout',        dreq.timeout);
         tloader.setOption('trimwhitespace', dreq.trimwhitespace == true);
         tloader.setOption('nsprefix',       dreq.nsprefix == true);
+        Debug.info("setting option sendheaders to ",dreq.getresponseheaders == true);
+        Debug.info("dreq.proxied = ", proxied);
+        Debug.info(tloader);
         tloader.setOption('sendheaders',    dreq.getresponseheaders == true);
 
         if ( dreq.clientcacheable != null ){
@@ -256,6 +259,7 @@
         dreq.responseheaders = headers;
         dreq.rawdata = dreq.loader.getResponse();
 
+        Debug.info("loadResponse", this, dreq, data);
         dreq.onstatus.sendEvent( dreq );
 
     }

Modified: openlaszlo/trunk/WEB-INF/lps/lfc/views/LzInputText.lzs
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/lfc/views/LzInputText.lzs	2007-10-04 20:08:12 UTC (rev 6725)
+++ openlaszlo/trunk/WEB-INF/lps/lfc/views/LzInputText.lzs	2007-10-04 22:49:36 UTC (rev 6726)
@@ -67,50 +67,6 @@
   * <tagname>inputtext</tagname> view can keep up with typing speed even
   * at large sizes or on a slow computer.</p>
   * 
-  * <p>A program can request an optimized <tagname>inputtext</tagname> by
-  * setting the <attribute>resizable</attribute> attribute to
-  * <code>false</code>, and supplying recognizable
-  * <attribute>width</attribute> and <attribute>height</attribute>
-  * dimension attributes.  A recognizable dimension attribute is an
-  * attribute that is defined as a numeric literal, such as
-  * <code>width="100"</code>, or that is defined as a simple
-  * <code>$once</code> expression that adds or subtracts a numeric literal
-  * to the <attribute>width</attribute> or <attribute>height</attribute>
-  * attribute of the view's parent, its parent's parent, or so on.  This
-  * final optimization allows the optimization to apply to
-  * <tagname>inputtext</tagname> tags within a class definition, as in the
-  * second example below.</p>
-  * 
-  * <example title="Optimized inputtext"><programlisting>
-  * &lt;canvas height="20"&gt;
-  *   &lt;inputtext resizable="false" width="150" height="20"&gt;
-  *     This text is editable.
-  *   &lt;/inputtext&gt;
-  * &lt;/canvas&gt;
-  * </programlisting></example>
-  * 
-  * <example title="Component with optimized inputtext"><programlisting>
-  * &lt;canvas height="20"&gt;
-  *   &lt;class name="mytext" width="150" height="20" bgcolor="gray"&gt;
-  *     &lt;attribute name="text" type="text"/&gt;
-  *     &lt;inputtext resizable="false" text="${parent.text}" bgcolor="white"
-  *       x="1" y="1"
-  *       width="$once{parent.width-2}" height="$once{parent.height-2}"/&gt;
-  *   &lt;/class&gt;
-  *   &lt;mytext&gt;This text is editable.&lt;/mytext&gt;
-  * &lt;/canvas&gt;
-  * </programlisting></example>
-  * 
-  * <p>The compiler can also infer the values of the
-  * <attribute>width</attribute> and <attribute>height</attribute>
-  * attributes if they are not supplied.  If supplied, the value of the
-  * <attribute>font</attribute> must be a constant string in order for the
-  * text field to be optimized.  If supplied, the value of the
-  * <attribute>fontsize</attribute> must be a constant in order to
-  * for the text field to be optimized. Generally these can be omitted and
-  * the inputtext will inherit the parent's font size and style by
-  * default.</p>
-  * 
   * @shortdesc The basic input-text element.
   * @lzxname inputtext
   */

Modified: openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/Canvas.java
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/Canvas.java	2007-10-04 20:08:12 UTC (rev 6725)
+++ openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/Canvas.java	2007-10-04 22:49:36 UTC (rev 6726)
@@ -102,14 +102,6 @@
 
     // Default to proxied deployment
     private boolean mProxied = true;
-
-    /** Width of the root output text object (Flash 5 limits us to
-     * setting this at compile time) */
-    private int mMaxTextWidth = 0;
-
-    /** Height of the root output text object (Flash 5 limits us to
-     * setting this at compile time) */
-    private int mMaxTextHeight = 0;
     
     /** FontInfo for the canvas. */
     private FontInfo mFontInfo = null;
@@ -268,28 +260,6 @@
         mHeightString = h;
     }
 
-
-    /** @return maxTextWidth */
-    public int getMaxTextWidth() {
-        return mMaxTextWidth;
-    }
-
-    /** @param h */
-    public void setMaxTextWidth(int h) {
-        mMaxTextWidth = h;
-    }
-
-    /** @return maxTextHeight */
-    public int getMaxTextHeight() {
-        return mMaxTextHeight;
-    }
-
-    /** @param h */
-    public void setMaxTextHeight(int h) {
-        mMaxTextHeight = h;
-    }
-
-
     /** @return Background color */
     public int getBGColor() {
         return mBGColor;

Modified: openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/CanvasCompiler.java
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/CanvasCompiler.java	2007-10-04 20:08:12 UTC (rev 6725)
+++ openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/CanvasCompiler.java	2007-10-04 22:49:36 UTC (rev 6726)
@@ -170,8 +170,7 @@
         for (Iterator iter = getLibraries(element).iterator();
              iter.hasNext(); ) {
             File file = (File) iter.next();
-            Element library = LibraryCompiler.resolveLibraryElement(
-                file, mEnv, visited, false);
+            Element library = LibraryCompiler.resolveLibraryElement(file, mEnv, visited);
             if (library != null) {
                 collectObjectProperties(library, model, visited);
             }
@@ -316,29 +315,6 @@
         
         canvas.setFontInfo(new FontInfo(font, fontsize, fontstyle));
         
-        // The width of the "root" Flash output text resource. Since
-        // it's fixed at compile time, this gives the developer a way
-        // to specify it. Defaults to canvas width if not specified.
-        String maxtextwidth = elt.getAttributeValue("maxtextwidth");
-        if (maxtextwidth != null) {
-            try {
-                canvas.setMaxTextWidth(Integer.parseInt(maxtextwidth));
-            } catch (NumberFormatException e) {
-                throw new CompilationError(elt, "maxtextwidth", e);
-            }
-        }
-        
-        // The height of the "root" Flash output text resource. Since
-        // it's fixed at compile time, this gives the developer a way
-        // to specify it. Defaults to canvas height if not specified.
-        String maxtextheight = elt.getAttributeValue("maxtextheight");
-        if (maxtextheight != null) {
-            try {
-                canvas.setMaxTextHeight(Integer.parseInt(maxtextheight));
-            } catch (NumberFormatException e) {
-                throw new CompilationError(elt, "maxtextheight", e);
-            }
-        }
     }
     
     private void collectObjectProperties(Element element, NodeModel model,
@@ -350,7 +326,7 @@
                 model.addPropertyElement(child);
             } else if (LibraryCompiler.isElement(child)) {
                 Element libraryElement = LibraryCompiler.resolveLibraryElement(
-                    child, mEnv, visited, false);
+                    child, mEnv, visited);
                 if (libraryElement != null) {
                     collectObjectProperties(libraryElement, model, visited);
                 }

Modified: openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ClassCompiler.java
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ClassCompiler.java	2007-10-04 20:08:12 UTC (rev 6725)
+++ openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ClassCompiler.java	2007-10-04 22:49:36 UTC (rev 6726)
@@ -76,7 +76,8 @@
         String classname = elt.getAttributeValue("name");
         String superclass = elt.getAttributeValue("extends");
         
-        if (classname == null || !ScriptCompiler.isIdentifier(classname)) {
+        if (classname == null ||
+            (schema.enforceValidIdentifier && !ScriptCompiler.isIdentifier(classname))) {
             CompilationError cerr = new CompilationError(
 /* (non-Javadoc)
  * @i18n.test
@@ -105,7 +106,9 @@
         }
         
         ClassModel superclassinfo = schema.getClassModel(superclass);
+
         if (superclassinfo == null) {
+
             throw new CompilationError(
 /* (non-Javadoc)
  * @i18n.test
@@ -125,20 +128,22 @@
             if (o instanceof Element) {
                 Element child = (Element) o;
                 // Is this an element named ATTRIBUTE which is a
-                // direct child of a CLASS tag?
+                // direct child of this CLASS or INTERFACE tag?
                 if (child.getName().equals("attribute")) {
-                    String attrName;
-                    try {
-                        attrName = requireIdentifierAttributeValue(child, "name");
-                    } catch (MissingAttributeException e) {
-                        throw new CompilationError(
-/* (non-Javadoc)
- * @i18n.test
- * @org-mes="'name' is a required attribute of <" + p[0] + "> and must be a valid identifier"
- */
-            org.openlaszlo.i18n.LaszloMessages.getMessage(
-                ClassCompiler.class.getName(),"051018-131", new Object[] {child.getName()})
-, child);
+                    String attrName = child.getAttributeValue("name");
+                    if (schema.enforceValidIdentifier) {
+                        try {
+                            attrName = requireIdentifierAttributeValue(child, "name");
+                        } catch (MissingAttributeException e) {
+                            throw new CompilationError(
+                                /* (non-Javadoc)
+                                 * @i18n.test
+                                 * @org-mes="'name' is a required attribute of <" + p[0] + "> and must be a valid identifier"
+                                 */
+                                org.openlaszlo.i18n.LaszloMessages.getMessage(
+                                    ClassCompiler.class.getName(),"051018-131", new Object[] {child.getName()})
+                                , child);
+                        }
                     }
                     
                     String attrTypeName = child.getAttributeValue("type");
@@ -159,6 +164,7 @@
                         attrType = schema.getTypeForName(attrTypeName);
                     }
                     
+
                     if (attrType == null) {
                         throw new CompilationError(
 /* (non-Javadoc)
@@ -181,12 +187,14 @@
                     }
                     attributeDefs.add(attrSpec);
                 } else if (child.getName().equals("event")) {
-                    String attrName;
-                    try {
-                        attrName = requireIdentifierAttributeValue(child, "name");
-                    } catch (MissingAttributeException e) {
-                        throw new CompilationError(
-                            "'name' is a required attribute of <" + child.getName() + "> and must be a valid identifier", child);
+                    String attrName = child.getAttributeValue("name");
+                    if (schema.enforceValidIdentifier) {
+                        try {
+                            attrName = requireIdentifierAttributeValue(child, "name");
+                        } catch (MissingAttributeException e) {
+                            throw new CompilationError(
+                                "'name' is a required attribute of <" + child.getName() + "> and must be a valid identifier", child);
+                        }
                     }
                     
                     ViewSchema.Type attrType = ViewSchema.EVENT_HANDLER_TYPE;
@@ -195,7 +203,7 @@
                     attributeDefs.add(attrSpec);
                 } else if (child.getName().equals("doc")) {
                     // Ignore documentation nodes
-                }
+                } 
             }
         }
         
@@ -204,21 +212,24 @@
     }
     
     public void compile(Element elt) {
-        String className;
-        try {
-            className = requireIdentifierAttributeValue(elt, "name");
-        } catch (MissingAttributeException e) {
-            throw new CompilationError(
-/* (non-Javadoc)
- * @i18n.test
- * @org-mes="'name' is a required attribute of <" + p[0] + "> and must be a valid identifier"
- */
-            org.openlaszlo.i18n.LaszloMessages.getMessage(
-                ClassCompiler.class.getName(),"051018-193", new Object[] {elt.getName()})
-, elt);
+        String className = elt.getAttributeValue("name");
+        ViewSchema schema = mEnv.getSchema();
+        if (schema.enforceValidIdentifier) {
+            try {
+                className = requireIdentifierAttributeValue(elt, "name");
+            } catch (MissingAttributeException e) {
+                throw new CompilationError(
+                    /* (non-Javadoc)
+                     * @i18n.test
+                     * @org-mes="'name' is a required attribute of <" + p[0] + "> and must be a valid identifier"
+                     */
+                    org.openlaszlo.i18n.LaszloMessages.getMessage(
+                        ClassCompiler.class.getName(),"051018-193", new Object[] {elt.getName()})
+                    , elt);
+            }
         }
                 
-        ViewSchema schema = mEnv.getSchema();
+
         ClassModel classModel = schema.getClassModel(className);
         
         String linedir = CompilerUtils.sourceLocationDirective(elt, true);
@@ -237,9 +248,9 @@
         viewMap.put("name", ScriptCompiler.quote(className));
         
         // TODO: [2007-01-29 ptw]  Someday write out real Javascript classes
-//         String superclass = XMLUtils.getAttributeValue(elt, "extends", DEFAULT_SUPERCLASS_NAME);
-//         org.openlaszlo.sc.ScriptClass scriptClass =
-//           new org.openlaszlo.sc.ScriptClass(className, superclass, (Map)viewMap.get("attrs"));
+        //         String superclass = XMLUtils.getAttributeValue(elt, "extends", DEFAULT_SUPERCLASS_NAME);
+        //         org.openlaszlo.sc.ScriptClass scriptClass =
+        //           new org.openlaszlo.sc.ScriptClass(className, superclass, (Map)viewMap.get("attrs"));
         
         // Construct a Javascript statement from the initobj map
         String initobj;

Modified: openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ClassModel.java
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ClassModel.java	2007-10-04 20:08:12 UTC (rev 6725)
+++ openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ClassModel.java	2007-10-04 22:49:36 UTC (rev 6726)
@@ -17,6 +17,9 @@
     protected final Element definition;
     protected NodeModel nodeModel;
     
+    /** Set of tags that can legally be nested in this element */
+    protected Set mCanContainTags = new HashSet();
+
     /* If superclass is a predefined system class, just store its name. */
     protected String superclassName = null;
     protected boolean hasInputText = false;
@@ -110,8 +113,12 @@
     }
 
     ClassModel getSuperclassModel() {
-        return superclass;
+      return superclass;
     }
+
+    String getClassName () {
+     return this.className;
+    }
     
     String getSuperclassName() {
         if (superclassName != null) {
@@ -309,6 +316,17 @@
             setChildrenClassRootDepth(child, childDepth);
         }
     }
+
+
+      /** Add an entry to the table of legally containable tags for a
+     * given tag */
+    public void addContainsElement (String childtag) {
+      mCanContainTags.add(childtag);
+    }
+
+    public Set getContainsSet () {
+      return mCanContainTags;
+    }
 }
 
 /**

Modified: openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/CompilationEnvironment.java
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/CompilationEnvironment.java	2007-10-04 20:08:12 UTC (rev 6725)
+++ openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/CompilationEnvironment.java	2007-10-04 22:49:36 UTC (rev 6726)
@@ -36,9 +36,6 @@
 
     public static final String PROFILE_PROPERTY           = "profile";
     public static final String LINK_PROPERTY              = "link";
-    public static final String VALIDATE_PROPERTY          = "validate";
-    // e_validate is defined if a user explicitly defined validate attribute
-    public static final String VALIDATE_EXPLICIT_PROPERTY = "e_validate";
     public static final String CSSFILE_PROPERTY           = "cssfile";
     // Log all debug.write messages back to the server
     public static final String LOGDEBUG_PROPERTY      = "logdebug";
@@ -638,4 +635,28 @@
         throw new CompilationError(elt, e);
       }
     }
+
+    public boolean warnIfCannotContain(Element parentTag, Element childTag) {
+        if (!mSchema.canContainElement(parentTag.getName(), childTag.getName())) {
+            this.warn(
+                // TODO [2006-08-22 hqm] i18n this
+                "The tag '" + childTag.getName() +
+                "' cannot be used as a child of " + parentTag.getName(),
+                parentTag);
+            return false;
+        } else {
+            return true;
+        }
+        
+    }
+
+    /** Check if all children are allowed to be contained in this tags */
+    public void checkValidChildContainment(Element element) {
+        for (Iterator iter = element.getChildren().iterator();
+             iter.hasNext(); ) {
+            Element child = (Element) iter.next();
+            this.warnIfCannotContain(element, child);
+        }
+    }
+
 }

Modified: openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/Compiler.java
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/Compiler.java	2007-10-04 20:08:12 UTC (rev 6725)
+++ openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/Compiler.java	2007-10-04 22:49:36 UTC (rev 6726)
@@ -308,11 +308,6 @@
             env.setProperty(CompilationEnvironment.BACKTRACE_PROPERTY, backtrace);
         }
 
-        String validate = props.getProperty(CompilationEnvironment.VALIDATE_PROPERTY,
-                                            LPS.getProperty("compiler.validate", "true"));
-        if (validate != null) {
-            env.setProperty(CompilationEnvironment.VALIDATE_PROPERTY, validate);
-        }
 
         String profile = props.getProperty(CompilationEnvironment.PROFILE_PROPERTY);
         if (profile != null) {
@@ -364,9 +359,9 @@
 
             mLogger.debug("Making a writer...");
 
-            // Initialize the schema from the base RELAX file
+            // Initialize the schema from the base LFC interface file
             try {
-                env.getSchema().loadSchema();
+                env.getSchema().loadSchema(env);
             } catch (org.jdom.JDOMException e) {
                 throw new ChainedException(e);
             }
@@ -376,20 +371,6 @@
             // files to have already been imported.
             if (! linking) { externalLibraries = env.getImportedLibraryFiles(); }
             Compiler.updateRootSchema(root, env, schema, externalLibraries);
-            if (SchemaLogger.isDebugEnabled()) {
-                org.jdom.output.XMLOutputter xmloutputter =
-                    new org.jdom.output.XMLOutputter();
-                try {
-                    SchemaLogger.debug(xmloutputter.outputString(schema.getSchemaDOM()));
-                } catch (org.jdom.JDOMException e) {
-                    throw new ChainedException(e);
-                }
-            }
-            
-            if (env.getBooleanProperty(CompilationEnvironment.VALIDATE_PROPERTY)) {
-                Parser.validate(doc, file.getPath(), env);
-            } 
-            
             Properties nprops = (Properties) env.getProperties().clone();
             Map compileTimeConstants = new HashMap();
             compileTimeConstants.put("$debug", new Boolean(
@@ -653,8 +634,7 @@
 
     static void importLibrary(File file, CompilationEnvironment env) {
         Element root = LibraryCompiler.resolveLibraryElement(
-            file, env, env.getImportedLibraryFiles(),
-            env.getBooleanProperty(CompilationEnvironment.VALIDATE_PROPERTY));
+            file, env, env.getImportedLibraryFiles());
         if (root != null) {
             compileElement(root, env);
         }
@@ -664,7 +644,7 @@
                                         ViewSchema schema, Set visited)
     {
         Element root = LibraryCompiler.resolveLibraryElement(
-            file, env, visited, false);
+            file, env, visited);
         if (root != null) {
             Compiler.updateSchema(root, env, schema, visited);
         }

Modified: openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/FontCompiler.java
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/FontCompiler.java	2007-10-04 20:08:12 UTC (rev 6725)
+++ openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/FontCompiler.java	2007-10-04 22:49:36 UTC (rev 6726)
@@ -45,6 +45,9 @@
             if (src != null) {
                 compileFont(name, element);
             }
+            // Check if children are valid tags to be contained 
+            mEnv.checkValidChildContainment(element);
+
             for (Iterator iter = element.getChildren("face", element.getNamespace()).iterator();
                  iter.hasNext(); ) {
                 compileFont(name, (Element) iter.next());

Modified: openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ImportCompiler.java
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ImportCompiler.java	2007-10-04 20:08:12 UTC (rev 6725)
+++ openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ImportCompiler.java	2007-10-04 22:49:36 UTC (rev 6726)
@@ -51,8 +51,7 @@
         String stage = XMLUtils.requireAttributeValue(element, "stage");
 
         Element module = LibraryCompiler.resolveLibraryElement(
-            element, mEnv, mEnv.getImportedLibraryFiles(),
-            mEnv.getBooleanProperty(mEnv.VALIDATE_PROPERTY));
+            element, mEnv, mEnv.getImportedLibraryFiles());
         if (module != null) {
             // check for conflict in the value of the "proxied"
             // attribute declared on the <import> tag vs the
@@ -124,7 +123,7 @@
     }
 
     void updateSchema(Element element, ViewSchema schema, Set visited) {
-        element = LibraryCompiler.resolveLibraryElement(element, mEnv, visited, false);
+        element = LibraryCompiler.resolveLibraryElement(element, mEnv, visited);
         if (element != null) {
             super.updateSchema(element, schema, visited);
         }

Modified: openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/LibraryCompiler.java
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/LibraryCompiler.java	2007-10-04 20:08:12 UTC (rev 6725)
+++ openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/LibraryCompiler.java	2007-10-04 22:49:36 UTC (rev 6726)
@@ -39,8 +39,7 @@
      */
     static Element resolveLibraryElement(File file,
                                          CompilationEnvironment env,
-                                         Set visited,
-                                         boolean validate)
+                                         Set visited)
     {
         try {
             File key = file.getCanonicalFile();
@@ -72,8 +71,6 @@
                 }
 
                 Document doc = env.getParser().parse(file, env);
-                if (validate)
-                    Parser.validate(doc, file.getPath(), env);
                 Element root = doc.getRootElement();
                 mLogger.debug("" + file + ": " + root + " attributes: " + root.getAttributes());
                 // Look for and add any includes from a binary library
@@ -106,29 +103,27 @@
      */
     static Element resolveLibraryElement(Element element,
                                          CompilationEnvironment env,
-                                         Set visited,
-                                         boolean validate)
+                                         Set visited)
     {
         String href = element.getAttributeValue(HREF_ANAME);
         if (href == null) {
             return element;
         }
         File file = env.resolveReference(element, HREF_ANAME, true);
-        return resolveLibraryElement(file, env, visited, validate);
+        return resolveLibraryElement(file, env, visited);
     }
     
     public void compile(Element element) throws CompilationError
     {
         element = resolveLibraryElement(
-            element, mEnv, mEnv.getImportedLibraryFiles(),
-            mEnv.getBooleanProperty(mEnv.VALIDATE_PROPERTY));
+            element, mEnv, mEnv.getImportedLibraryFiles());
         if (element != null) {
             super.compile(element);
         }
     }
 
     void updateSchema(Element element, ViewSchema schema, Set visited) {
-        element = resolveLibraryElement(element, mEnv, visited, false);
+        element = resolveLibraryElement(element, mEnv, visited);
         if (element != null) {
             super.updateSchema(element, schema, visited);
             // TODO [hqm 2005-02-09] can we compare any 'proxied' attribute here

Modified: openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/LibraryWriter.java
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/LibraryWriter.java	2007-10-04 20:08:12 UTC (rev 6725)
+++ openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/LibraryWriter.java	2007-10-04 22:49:36 UTC (rev 6726)
@@ -98,17 +98,7 @@
     }
   }
 
-  private void exportAttributes() {
-      // Write out the validate attribute of the source library, but only if
-      // it was explicitly defined by the user
-      String property   = CompilationEnvironment.VALIDATE_PROPERTY;
-      String e_property = CompilationEnvironment.VALIDATE_EXPLICIT_PROPERTY;
-      String validate   = mEnv.getProperty(property, null);
-      String e_validate = mEnv.getProperty(e_property, null);
-      if (e_validate != null && validate != null) {
-        out.println("<attribute name='" + property + "' value='" + validate + "' />");
-      }
-  }
+  private void exportAttributes() {}
 
   private void exportResources() {
     for (Iterator i = resourceMap.entrySet().iterator(); i.hasNext(); ) {

Modified: openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/NodeModel.java
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/NodeModel.java	2007-10-04 20:08:12 UTC (rev 6725)
+++ openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/NodeModel.java	2007-10-04 22:49:36 UTC (rev 6726)
@@ -403,6 +403,14 @@
         this.parentClassModel = getParentClassModel();
     }
 
+    ViewSchema.Type getAttributeTypeInfoFromParent(
+        Element elt, String attrname)
+        throws UnknownAttributeException
+    {
+        Element parent = elt.getParentElement();
+        return schema.getAttributeType(parent, attrname);
+    }
+
     // Should only be called on a <class> definition element.
     ViewSchema.Type getAttributeTypeInfoFromSuperclass(
         Element classDefElement, String attrname)
@@ -614,14 +622,23 @@
                 }
             }
 
-            // Special case, if we are compiling a "class" tag,
-            // then get the type of attributes from the
-            // superclass.
+
             Schema.Type type;
             try {
                 if (className.equals("class")) {
+                    // Special case, if we are compiling a "class"
+                    // tag, then get the type of attributes from the
+                    // superclass.
                     type = getAttributeTypeInfoFromSuperclass(element, name);
-                }  else {
+                } else if (className.equals("state")) {
+                    // Special case for "state", it can have any attribute
+                    // which belongs to the parent. 
+                    try {
+                        type = schema.getAttributeType(element, name);
+                    } catch (UnknownAttributeException e) {
+                        type = getAttributeTypeInfoFromParent(element, name);
+                    }
+                } else {
                     // NOTE [2007-06-14 ptw]: Querying the classModel
                     // directly will NOT work, because the schema
                     // method has some special kludges in it for canvas
@@ -707,10 +724,7 @@
                       ComparisonMap references, ComparisonMap paths,
                       ComparisonMap styles) {
         if (cattr.type == cattr.ATTRIBUTE) {
-            // Ignore warnings for 'validate'
-            // FIXME [2007-08-31 pbr]: LPP-4620.
-            if (attrs.containsKey(name, caseSensitive) && 
-                !"validate".equalsIgnoreCase(name)) {
+            if (attrs.containsKey(name, caseSensitive)) {
                 env.warn(
 /* (non-Javadoc)
  * @i18n.test
@@ -866,12 +880,44 @@
         return (child.getName().equals("datapath"));
     }
 
+    void checkChildNameConflict(Element child, CompilationEnvironment env) {
+        String attrName = child.getAttributeValue("name");
+        if (attrName != null) {
+            ViewSchema.Type attrType = null;
+            try {
+                attrType = schema.getAttributeType(element,  attrName);
+            } catch (UnknownAttributeException e) {
+                    
+            }
+            if (attrType != null) {
+                // TODO [2007-09-26 hqm] i18n this
+                env.warn(
+                    "Child tag '" + child.getName() +
+                    "' with attribute '"+attrName +
+                    "' conflicts with attribute named '"+attrName+"' of type '" + attrType +
+                    "' on parent tag '"+element.getName()+"'.",
+                    element);
+            }
+        }
+    }
+
+
+
     void addChildren(CompilationEnvironment env) {
         // Encode the children
         for (Iterator iter = element.getChildren().iterator(); iter.hasNext(); ) {
             ElementWithLocationInfo child = (ElementWithLocationInfo) iter.next();
+            if (!schema.canContainElement(element.getName(), child.getName())) {
+                env.warn(
+                    // TODO [2007-09-26 hqm] i18n this
+                    "The tag '" + child.getName() +
+                    "' cannot be used as a child of " + element.getName(),
+                    element);
+            }
+
             try {
                 if (child.getName().equals("data")) {
+                    checkChildNameConflict(child, env);
                     // literal data
                     addLiteralDataElement(child);
                 } else if (isPropertyElement(child)) {
@@ -881,9 +927,11 @@
                 } else if (schema.isDocElement(child)) {
                     ; // ignore doc nodes.
                 } else if (isDatapathElement(child)) {
+                    checkChildNameConflict(child, env);
                     NodeModel dpnode = elementAsModel(child, schema, env);
                     this.datapath = dpnode;
                 } else {
+                    checkChildNameConflict(child, env);
                     NodeModel childModel = elementAsModel(child, schema, env);
                     children.add(childModel);
                     totalSubnodes += childModel.totalSubnodes();
@@ -1250,7 +1298,7 @@
                 if (when.equals(WHEN_IMMEDIATELY)) {
                     value = ScriptCompiler.quote(value);
                 }
-            } else if (type == ViewSchema.EXPRESSION_TYPE) {
+            } else if ((type == ViewSchema.EXPRESSION_TYPE) || (type == ViewSchema.BOOLEAN_TYPE)) {
                 // No change currently, possibly analyze expressions
                 // and default non-constant to when="once" in the
                 // future
@@ -1258,6 +1306,14 @@
                 // change "inherit" to null and pass true/false through as expression
                 if ("inherit".equals(value)) {
                     value = "null";
+                } else if ("true".equals(value)) {
+                    value = "true";
+                } else if ("false".equals(value)) {
+                    value = "false";
+                } else {
+                    // TODO [hqm 2007-0] i8nalize this message
+                    env.warn("attribute '"+name+"' must have the value 'true', 'false', or 'inherit'",
+                             element);
                 }
             } else if (type == ViewSchema.NUMBER_TYPE) {
                 // No change currently, possibly analyze expressions

Modified: openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/Parser.java
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/Parser.java	2007-10-04 20:08:12 UTC (rev 6725)
+++ openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/Parser.java	2007-10-04 22:49:36 UTC (rev 6726)
@@ -159,7 +159,7 @@
     
     /** Reads an XML document and adds source location information to
      * the elements. */
-    protected Document read(File file)
+    public Document read(File file)
         throws JDOMException, IOException
     {
         // See if we've already read the file.  This is an
@@ -616,142 +616,6 @@
      * serialization of the schema.  */
     private static LRUMap mSchemaCache = new LRUMap(1);
     
-    /** Validates an XML file against the Laszlo schema. Errors are
-     * thrown as the text of a CompilationError.
-     *
-     * @param doc DOM of the source code to be validated
-     * @param pathname pathname of the source file, for error reporting
-     * @param env the compilation environment
-     * @throws CompilationError if a validation error occurs
-     */
-    public static void validate(Document doc, String pathname,
-                                final CompilationEnvironment env) 
-    {
-        final CompilationErrorHandler errorHandler = env.getErrorHandler();
-        final ViewSchema viewschema = env.getSchema();
-
-        if (mPreValidationLogger.isDebugEnabled()) {
-            org.jdom.output.XMLOutputter debugOutputter =
-                new org.jdom.output.XMLOutputter();
-            mPreValidationLogger.debug("Pathname: " + pathname);
-            mPreValidationLogger.debug(debugOutputter.outputString(doc));
-        }
-        try {
-            org.iso_relax.verifier.Schema schema;
-
-            // Look up a cached version of the compiled verifier for this env
-            Verifier verifier = env.getCachedVerifier();
-
-            if (verifier == null) {
-                // System.err.println("env verifier cache miss: " + pathname);
-
-                // Look up schema XML signature in common pool of compiled verifiers
-                Object value;
-                String schemaXMLstring = new XMLOutputter().outputString(viewschema.getSchemaDOM());
-                String key = schemaXMLstring;
-
-                synchronized (mSchemaCache) {
-                    schema = (org.iso_relax.verifier.Schema) mSchemaCache.get(key);
-                }
-                
-                if (schema == null) {
-                    StringReader schemaXMLSource = new StringReader(schemaXMLstring);
-                    InputSource schemaInputSource = new InputSource(schemaXMLSource);
-
-                    // System.err.println("validator pool cache miss: " + pathname + " " + key.length());
-                    long st = System.currentTimeMillis();
-                    
-                    VerifierFactory factory = VerifierFactory.newInstance(
-                        "http://relaxng.org/ns/structure/1.0");
-                    schema = factory.compileSchema(schemaInputSource);
-                    long elapsed = System.currentTimeMillis() - st; 
-                    mLogger.debug("compileSchema took "+elapsed+"ms");
-
-
-                    synchronized (mSchemaCache) {
-                        mSchemaCache.put(key, schema);
-                    }
-                } else {
-                    // System.err.println("validator pool cache hit: " + pathname + " " + key.length());
-                }
-                
-                // Cache this in CompilationEnvironment
-                verifier = schema.newVerifier();
-                env.setCachedVerifier(verifier);
-            } else {
-                // System.err.println("env verifier cache hit: " + pathname);
-            }
-            
-            VerifierHandler handler = verifier.getVerifierHandler();
-
-            verifier.setErrorHandler(
-                new org.xml.sax.ErrorHandler() {
-                        protected void reportError(org.xml.sax.SAXParseException e)
-                        {
-                            String msg = e.getMessage();
-                            msg = StringUtils.replace(msg, " from namespace \"" + sNamespace.getURI() + "\"", "");
-                            CompilationError cerr = new CompilationError(msg);
-                            cerr.initPathname(e.getPublicId());
-                            cerr.setLineNumber(e.getLineNumber());
-                            cerr.setColumnNumber(e.getColumnNumber());
-                            if (msg.endsWith("not allowed in this context"))
-                                cerr.setSolution("Check whether it is spelled correctly, and whether a class with this name exists.");
-                            // TODO [2003-3-17 hqm]: find and add more
-                            // solution message here]
-                            env.warn(cerr);
-                        }
-                        public void fatalError(org.xml.sax.SAXParseException e) {
-                            reportError(e);
-                        }
-                        public void error(org.xml.sax.SAXParseException e) {
-                            reportError(e);
-                        }
-                        public void warning(org.xml.sax.SAXParseException e) {
-                            reportError(e);
-                        }
-                    }
-                );
-            
-            /* Walk the DOM tree out as SAX events, as best we can. We
-             * can't just use org.jdom.output.SAXOutputter because it
-             * doesn't know how to convert the source location info from
-             * our custom Elements into SAX Events. 
-             */
-
-            SourceLocatorSAXOutputter outputter =
-                new SourceLocatorSAXOutputter();
-
-            /* Sets our validator (event handler) to be the handler
-             * for the SAX Outputter  */
-            outputter.setContentHandler(handler);
-            /* Feed the the source file DOM, via the SAX event
-             * generator, to the validator. */
-            outputter.output(doc);
-
-        } catch (VerifierConfigurationException e) {
-            throw new ChainedException(e);
-        } catch (JDOMException e) {
-            throw new ChainedException(e);
-        } catch (StackOverflowError e) {
-            env.warn(
-/* (non-Javadoc)
- * @i18n.test
- * @org-mes="The validator had a fatal error, but proceeding with compilation"
- */
-            org.openlaszlo.i18n.LaszloMessages.getMessage(
-                Parser.class.getName(),"051018-648")
-, doc.getRootElement());
-        } catch (SAXException e) {
-            String solution = SolutionMessages.findSolution(e.getMessage(), SolutionMessages.PARSER);
-            CompilationError err = new CompilationError(e, solution);
-            err.setFileBase(errorHandler.fileBase);
-            err.initPathname(pathname);
-            throw err;
-        } catch (IOException e) {
-            throw new ChainedException(e);
-        }
-    }
-
     void saveStartLocation (Element elt,
                             String pathname,
                             String messagePathname,

Modified: openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ResourceCompiler.java
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ResourceCompiler.java	2007-10-04 20:08:12 UTC (rev 6725)
+++ openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ResourceCompiler.java	2007-10-04 22:49:36 UTC (rev 6726)
@@ -128,6 +128,9 @@
                 }
                 resourceNames.add(name);
 
+                // Check if children are valid tags to be contained 
+                mEnv.checkValidChildContainment(element);
+
                 // N.B.: Resources are always imported into the main
                 // program for the Flash target, hence the use of
                 // getResourceGenerator below

Modified: openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/SWFWriter.java
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/SWFWriter.java	2007-10-04 20:08:12 UTC (rev 6725)
+++ openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/SWFWriter.java	2007-10-04 22:49:36 UTC (rev 6726)
@@ -101,13 +101,6 @@
     public static final int DEFAULT_SIZE = 8;
 
 
-    /** Width of the "root" text output object. Defaults to canvas width. */
-    private int mMaxTextWidth = 0;
-
-    /** Height of the "root" text output object. Defaults to canvas height. */
-    private int mMaxTextHeight = 0;
-
-
     /** Logger for jgenerator */
     /**
      * Initializes a SWFWriter with an OutputStream to which a new SWF
@@ -281,18 +274,6 @@
         mWidth = canvas.getWidth();
         mHeight = canvas.getHeight();
 
-        mMaxTextWidth = canvas.getMaxTextWidth();
-        // If zero, default to canvas width 
-        if (mMaxTextWidth == 0) {
-            mMaxTextWidth = mWidth;
-        }
-
-        mMaxTextHeight = canvas.getMaxTextHeight();
-        // If zero, default to canvas height 
-        if (mMaxTextHeight == 0) {
-            mMaxTextHeight = mHeight;
-        }
-
         // Get default font info 
         FontInfo fontInfo = canvas.getFontInfo();
 

Modified: openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ToplevelCompiler.java
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ToplevelCompiler.java	2007-10-04 20:08:12 UTC (rev 6725)
+++ openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ToplevelCompiler.java	2007-10-04 22:49:36 UTC (rev 6726)
@@ -38,6 +38,9 @@
     }
     
     public void compile(Element element) {
+        // Check if children are valid tags to be contained 
+        mEnv.checkValidChildContainment(element);
+
         for (Iterator iter = element.getChildren().iterator();
              iter.hasNext(); ) {
             Element child = (Element) iter.next();
@@ -54,15 +57,12 @@
      * look for elements named "class", find the "name" and "extends"
      * attributes, and enter them in the ViewSchema.
      *
-     * Also check for the "validate" attribute, to optionally disable validator.
-     *
      * @param visited {canonical filenames} for libraries whose
      * schemas have been visited; used to prevent recursive
      * processing.
      * 
      */
     void updateSchema(Element element, ViewSchema schema, Set visited) {
-        setValidateProperty(element, mEnv);
         Iterator iterator = element.getChildren().iterator();
         while (iterator.hasNext()) {
             Element child = (Element) iterator.next();
@@ -72,46 +72,6 @@
         }
     }
 
-
-    /**
-     * Look for the "validate" attribute on canvas or at top level of imported libraries
-     *
-     * We look these places for the validate attribute:
-     *   <li>  canvas (root) element
-     *   <li>  direct child atttribute of canvas
-     * @param root source code document root
-     * @param env the CompilationEnvironment
-     */
-    void setValidateProperty(Element root , CompilationEnvironment env) {
-        String validate = CompilationEnvironment.VALIDATE_PROPERTY;
-        String e_validate = CompilationEnvironment.VALIDATE_EXPLICIT_PROPERTY;
-        // Look for canvas attribute
-        if (root.getAttributeValue(validate) != null) {
-            // Record that the user explicitly defined validate
-            env.setProperty(e_validate, true);
-            if ("false".equals(root.getAttributeValue("validate"))) {
-                env.setProperty(validate, false);
-            } else {
-                env.setProperty(validate, true);
-            }
-        }
-
-        // Look for direct canvas children <attribute name="validate" value="false">
-        for (Iterator iter = root.getChildren().iterator();
-             iter.hasNext(); ) {
-            Element child = (Element) iter.next();
-            if (child.getName().equals("attribute")
-                && validate.equals(child.getAttributeValue("name"))) {
-                // Record that the user explicitly defined validate
-                env.setProperty(e_validate, true);
-                if ("false".equals(child.getAttributeValue("value"))) {
-                    env.setProperty(validate, false);
-                }
-            }
-        }
-    }
-
-
     /** This also collects "attribute", "method", and HTML element
      * names, but that's okay since none of them has an autoinclude
      * entry.
@@ -129,7 +89,7 @@
             if (compiler instanceof LibraryCompiler || compiler instanceof ImportCompiler) {
                 libStart = new LinkedHashSet(libsVisited.keySet());
                 libFound = new LinkedHashSet(libStart);
-                library = LibraryCompiler.resolveLibraryElement(element, env, libFound, false);
+                library = LibraryCompiler.resolveLibraryElement(element, env, libFound);
                 if (library == element) {
                     // Not an external library
                     library = null;

Modified: openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ViewSchema.java
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ViewSchema.java	2007-10-04 20:08:12 UTC (rev 6725)
+++ openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ViewSchema.java	2007-10-04 22:49:36 UTC (rev 6726)
@@ -28,11 +28,11 @@
     private static final Set sInputTextElements = new HashSet();
     private static final Set sHTMLContentElements = new HashSet();
 
-    /** The location of the base Laszlo RELAXNG schema */
+    /** The location of the Laszlo LFC bootstrap interface declarations file  */
     private final String SCHEMA_PATH = LPS.HOME() + File.separator +
         "WEB-INF" + File.separator + 
         "lps" + File.separator + 
-        "schema"  + File.separator + "lzx.rng";
+        "schema"  + File.separator + "lfc.lzx";
 
     private Document schemaDOM = null;
 
@@ -54,8 +54,19 @@
      */
     private final Map mClassMap = new HashMap();
 
+    /**
+     * If true, requires class names to be valid javascript identifiers.
+     * We disable this when defining LZX builtin tags such as "import"
+     * which are reserved javascript tokens.
+     */
+    public boolean enforceValidIdentifier = false;
+
     /** Type of script expressions. */
     public static final Type EXPRESSION_TYPE = newType("expression");
+
+    /** 'boolean' is compiled the same as an expression type */
+    public static final Type BOOLEAN_TYPE = newType("boolean");
+
     public static final Type REFERENCE_TYPE = newType("reference");
     /** Type of event handler bodies. */
     public static final Type EVENT_HANDLER_TYPE = newType("script");
@@ -76,34 +87,6 @@
         sHTMLContentElements.add("text");
         sInputTextElements.add("inputtext");
 
-        // Define mapping from RNG Schema types to LPS types
-        sRNGtoLPSTypeMap.put("ID",               ID_TYPE);
-        sRNGtoLPSTypeMap.put("anyURI",           STRING_TYPE);
-        sRNGtoLPSTypeMap.put("booleanOrNull",    EXPRESSION_TYPE);
-        sRNGtoLPSTypeMap.put("boolean",          EXPRESSION_TYPE);
-        sRNGtoLPSTypeMap.put("booleanLiteral",   EXPRESSION_TYPE);
-        sRNGtoLPSTypeMap.put("inheritableBooleanLiteral",   INHERITABLE_BOOLEAN_TYPE);
-        sRNGtoLPSTypeMap.put("color",            COLOR_TYPE);
-        sRNGtoLPSTypeMap.put("colorLiteral",     COLOR_TYPE);
-        sRNGtoLPSTypeMap.put("css",              CSS_TYPE);
-        sRNGtoLPSTypeMap.put("double",           NUMBER_TYPE);
-        sRNGtoLPSTypeMap.put("enumeration",      STRING_TYPE);
-        sRNGtoLPSTypeMap.put("expression",       EXPRESSION_TYPE);
-        sRNGtoLPSTypeMap.put("float",            NUMBER_TYPE);
-        sRNGtoLPSTypeMap.put("integer",          NUMBER_TYPE);
-        sRNGtoLPSTypeMap.put("number",           NUMBER_TYPE);
-        sRNGtoLPSTypeMap.put("numberLiteral",    NUMBER_TYPE);
-        sRNGtoLPSTypeMap.put("numberExpression", NUMBER_EXPRESSION_TYPE);
-        sRNGtoLPSTypeMap.put("propertyPath",     STRING_TYPE);
-        sRNGtoLPSTypeMap.put("reference",        REFERENCE_TYPE);
-        sRNGtoLPSTypeMap.put("script",           EVENT_HANDLER_TYPE);
-        sRNGtoLPSTypeMap.put("size",             SIZE_EXPRESSION_TYPE);
-        sRNGtoLPSTypeMap.put("sizeLiteral",      SIZE_EXPRESSION_TYPE);
-        sRNGtoLPSTypeMap.put("sizeExpression",   SIZE_EXPRESSION_TYPE);
-        sRNGtoLPSTypeMap.put("string",           STRING_TYPE);
-        sRNGtoLPSTypeMap.put("token",            TOKEN_TYPE);
-        sRNGtoLPSTypeMap.put("opacity",          NUMBER_TYPE);
-
         // from http://www.w3.org/TR/REC-html40/interact/scripts.html
         String[] mouseEventAttributes = {
             "onclick", "ondblclick", "onmousedown", "onmouseup", "onmouseover",
@@ -256,151 +239,8 @@
     }
 
     /**
-     * Add in the XML to the Schema class definition MYCLASS,
-     * to add this list of attribute declarations.
-     *
-     * @param sourceElement the user's LZX source file element that holds class LZX definition 
-     * @param classname the class we are defining
-     * @param classDef the RNG class declaration
-     * @param attributeDefs list of AttributeSpec attribute info to add to the Schema
-     *
-     * This is confusing because we are modifying the RNG XML tree,
-     * not the actual lzx source code tree.  So it is confusing to see
-     * JDOM Elements floating around and not be able to tell whether
-     * they pertain to the LZX source or the RNG tree. Only
-     * <i>sourceElement</i> is from the lzx source, we have it here so
-     * we can identify the source file and line # in case of an error.
-     */
-    void addAttributeDefs (Element sourceElement, String classname,
-                           Element classDef, List attributeDefs)
-    {
-        /*
-          <element>
-            CHILDREN
-          </element>
-
-          ==>
-
-          <element>
-            NEWATTRS
-            CHILDREN
-          </element>
-        */     
-        if (!attributeDefs.isEmpty()) {
-            Namespace ns = classDef.getNamespace();
-            List attrList = new ArrayList();
-            for (Iterator iter = attributeDefs.iterator(); iter.hasNext();) {
-                AttributeSpec attr = (AttributeSpec) iter.next();
-
-                // If this attribute does not already occur someplace
-                // in an ancestor, then let's add it to the schema, so
-                // that the validation phase will know about it.
-                //
-                // We don't want to splice this attribute into the
-                // schema if it already is present in an ancestor,
-                // because that causes a fatal error ("duplicate
-                // attribute") when parsing the schema.
-                
-                //System.out.println("getClassAttribute( "+ classname+", "+attr.name+ ") = "  + classInheritsAttribute(classname, attr.name));
-                if (getClassAttribute(classname, attr.name) == null) {
-                    // Splice some XML into the Schema element
-                    Element newAttr = new Element("attribute", ns);
-                    newAttr.setAttribute("name", attr.name);
-                    /* Datatype needs to be a ref to a laszlo type
-                       definition, so we generate this RELAX XML for
-                       the attribute:
-                       
-                       <optional>
-                         <attribute name="rotation" a:defaultValue="0">
-                           <ref name="numberExpression"/>
-                         </attribute>
-                       </optional>
-
-                       except for the base RELAX type 'string', for
-                       which there is no ref, we generate this:
-
-                       <optional>
-                         <attribute name="foo">
-                           <data type="string"/>
-                         </attribute>
-                       </optional>
-                    */
-                    String attrTypeName = attr.type.toString();
-                    Element datatype;
-                    if (attrTypeName.equals("string") || attrTypeName.equals("boolean")) {
-                        datatype = new Element("data", ns);
-                        datatype.setAttribute("type", attrTypeName);
-                    } else {
-                        datatype = new Element("ref", ns);
-                        datatype.setAttribute("name", attrTypeName);
-                    }
-                    // assemble the <attribute> node
-                    newAttr.addContent(datatype);
-                    // Wrap it in an <optional>
-                    Element optional = new Element("optional", ns);
-                    optional.addContent(newAttr);
-                    // If it's an <attribute name="text" type="text">, add this
-                    // instead:
-                    //   <ref name="textAttributes"/>
-                    if (attr.contentType != attr.NO_CONTENT) {
-                        optional = new Element("ref", ns);
-                        if (attr.contentType == attr.TEXT_CONTENT) {
-                            optional.setAttribute("name", "textContent");
-                        } else if (attr.contentType == attr.HTML_CONTENT) {
-                            optional.setAttribute("name", "htmlContent");
-                        } else {
-                            throw new RuntimeException("unknown content type");
-                        }
-                    }
-                    attrList.add(optional);
-                } else {
-                    // Check that the overriding type is the same as the superclass' type
-                    Type parentType = getAttributeType(classname, attr.name);
-
-                    if (parentType != attr.type) {
-throw new CompilationError(sourceElement, attr.name, new Throwable(
-/* (non-Javadoc)
- * @i18n.test
- * @org-mes="In class '" + p[0] + "' attribute '" + p[1] + "' with type '" + p[2] + "' is overriding superclass attribute with same name but different type: " + p[3]
- */
-            org.openlaszlo.i18n.LaszloMessages.getMessage(
-                ViewSchema.class.getName(),"051018-364", new Object[] {classname, attr.name, attr.type.toString(), parentType.toString()})
-                                ));
-                    }
-                }
-
-                // Update the in-memory attribute type table
-                setAttributeType(sourceElement, classname, attr.name, attr);
-            }
-
-            if (!attrList.isEmpty()) {
-                // Now splice the attribute list to the start of the class declaration node
-                // Remove the original children of the class node
-                List children = new ArrayList();
-                for (Iterator iter = classDef.getChildren().iterator(); iter.hasNext();) {
-                    Element child = (Element) iter.next();
-                    children.add(child);
-                    // The only way to detach the child from the
-                    // parent is to use the iterator.remove() method
-                    // otherwise you get a ConcurrentModificationException
-                    iter.remove(); 
-                }
-                // Add in attributes
-                classDef.setContent(attrList);
-                // Then add back the old children
-                for (Iterator iter = children.iterator(); iter.hasNext();) {
-                    Element child = (Element) iter.next();
-                    classDef.addContent(child);
-                }
-            }
-        }
-    }
-
-    /**
      * Add a new element to the attribute type map.
      *
-     * Modifies the in-core schema DOM tree as well, to clone the superclass node.
-     *
      * @param elt the element to add to the map
      * @param superclassName an element to inherit attribute to type info from. May be null.
      * @param attributeDefs list of attribute name/type defs
@@ -451,240 +291,83 @@
 
         info.supportsTextAttribute = superclass.supportsTextAttribute;
 
-
-        // Modify the RELAX schema DOM to add this element. We find the superclass and
-        // clone it, and modify its tag name.
-        
-        /*
-          Say we are defining a new class "myclass extends somesuperclass":
-
-          We look for some XML in the Schema which defines the
-          "somesuperclass" class, which will look like
-            <element name="somesuperclass"> .... </element>
-          or else
-            <element>
-              <choice>
-                <name>...</name>.
-                <name>somesuperclass</name>
-              </choice>
-            </element>
-
-          We then need to clone the superclass node, change its name
-          to "myclass", and replace the original superclass node with
-          a CHOICE of
-            <choice>
-              <..orginal superclass node..>
-              <..our new class node..>
-            </choice>
-
-          This involves detach()'ing the superclass node, cloning it,
-          and then making the new choice node and adding it back into
-          the parent.
-        */
-
-        // Find the superclass definition
-        Element superclassDef = findSchemaClassDef(superclassName, schemaDOM.getRootElement());
-        if (superclassDef == null) {
-            throw new CompilationError(
-/* (non-Javadoc)
- * @i18n.test
- * @org-mes="No definition for superclass " + p[0] + " found in the schema"
- */
-            org.openlaszlo.i18n.LaszloMessages.getMessage(
-                ViewSchema.class.getName(),"051018-491", new Object[] {superclassName})
-);
-        }
-
-        Namespace ns = superclassDef.getNamespace();
-        // Clone the superclass's schema definition
-        Element myclassDef  = (Element) superclassDef.clone();
-
-        // Update the map of classnames to defining Elements
-        classElementTable.put(className, myclassDef);
-
-        // Add in the attribute declarations
-        addAttributeDefs(elt, className, myclassDef, attributeDefs);
-        // Change "name" attritbute (if there is one) to className.
-        // If there's no "name" attribute, we look for the CHOICE
-        // child node that has NAME children and remove it.
-
-        // Change the name to our new classname
-        Attribute nameAttr = myclassDef.getAttribute("name");
-        if (nameAttr == null) {
-            // OK, it's not of the form <element name="classname">, so
-            // it is of the form <element>
-            // <choice><name>classname</name></choice>...</element>.
-            //
-            // We need to remove the "choice" child and add a "name"
-            // attribute
-
-            // +++ We don't necessarily want to remove the first
-            // 'choice' node, we want to remove the one which has
-            // 'name' children.
-
-            for (Iterator iter = myclassDef.getChildren("choice", ns).iterator(); iter.hasNext();) {
-                Element choice = (Element) iter.next();
-                List names = choice.getChildren("name", ns);
-                if (!names.isEmpty()) {
-                    // it contains one or more <name> elements, so
-                    // remove this whole 'choice' node from its parent
-                    iter.remove();
-                    break;
-                }
+        // Loop over containsElements tags, adding to containment table in classmodel
+        Iterator iterator = elt.getChildren().iterator();
+        while (iterator.hasNext()) {
+            Element child = (Element) iterator.next();
+            if (child.getName().equals("containsElements")) {
+                    // look for <element>tagname</element> 
+                Iterator iter1 = child.getChildren().iterator();
+                while (iter1.hasNext()) {
+                    Element etag = (Element) iter1.next();
+                    if (etag.getName().equals("element")) {
+                        String tagname = etag.getText();
+                        info.addContainsElement(tagname);
+                    } else {
+                        throw new CompilationError(
+                            "containsElement block must only contain <element> tags", etag);
+                    }
+                } 
             }
         }
 
-        myclassDef.setAttribute("name", className);
-
-        /* Now detach the superclass node and put in it's place
-             <choice>
-               <SUPERCLASSNODE>
-               <MYNEWCLASSNODE>
-             </choice>
-        */
-
-        Element parent = superclassDef.getParentElement();
-        if (parent.getName().equals("choice"))
-            parent.addContent(myclassDef);
-        else {
-            superclassDef.detach();
-            Element newChoice = new Element("choice", ns);
-            newChoice.addContent(superclassDef);
-            newChoice.addContent(myclassDef);
-            parent.addContent(newChoice);
-        }
-
-        /*
-          if (definition != null) {
-          // Look through the definition for children who are or
-          // have text elements, and set info.hasInputText
-          // accordingly
-          info.hasInputText = info.hasInputText || (new Object() {
-          boolean isOrHasChildren(Element elt) {
-          if (isInputText(elt.getName()) || hasInputText(elt.getName())) {
-          return true;
-          }
-          for (Iterator iter = elt.getChildren().iterator(); iter.hasNext(); ) {
-          Element child = (Element) iter.getNext();
-          return isOrHasChildren(child);
-          }
-          }
-          }).isOrHasChildren(definition);
-
-          }*/
-        /* <class ...>
-           <view>
-           <text/>
-           </view>
-           </class>
-        */
+        // Add in the attribute declarations
+        addAttributeDefs(elt, className, attributeDefs);
     }
 
     /**
-       Walk the Schema DOM looking for an element which defines CLASSNAME.
-       <p>
-       This
-       can actually occur in the schema as either
-       <pre>
-       &lt;element name="classname"&gt;
-       or
-       &lt;element&gt; &lt;choice&gt; ... ...  &lt;name&gt;classname&lt;/name&gt; &lt;/choice&gt;
-       </pre>
+     * Add this list of attribute name/type info to the in-core model of the class definitions.
+     *
+     * @param sourceElement the user's LZX source file element that holds class LZX definition 
+     * @param classname the class we are defining
+     * @param attributeDefs list of AttributeSpec attribute info to add to the Schema
+     *
+     */
+    void addAttributeDefs (Element sourceElement, String classname, List attributeDefs)
+    {
+        if (!attributeDefs.isEmpty()) {
+            for (Iterator iter = attributeDefs.iterator(); iter.hasNext();) {
+                AttributeSpec attr = (AttributeSpec) iter.next();
 
-       <p>
-       Uses the classElementTable to speed up the lookup.
-    */
-    
-    Element findSchemaClassDef (String classname, Element elt) {
+                // If this attribute does not already occur someplace
+                // in an ancestor, then let's add it to the schema.
+                //
+                // While we're here, we need to check that we aren't
+                // redefining an attribute of a parent class with a
+                // different type.
 
-        // Check the index
-        Element classdef = (Element) classElementTable.get(classname);
-        if (classdef != null) {
-            return classdef;
-        }
+                if (getClassAttribute(classname, attr.name) == null) {
+                    // Splice some XML into the Schema element
+                    String attrTypeName = attr.type.toString();
+                } else {
+                    // Check that the overriding type is the same as the superclass' type
+                    Type parentType = getAttributeType(classname, attr.name);
 
-        if (elt.getName().equals("element")) {
-            Namespace ns = elt.getNamespace();
-            // Is this an element named "classname"?
-            String name = elt.getAttributeValue("name");
-            if (name != null && name.equals(classname)) {
-                // cache this
-                classElementTable.put(classname, elt);
-                return elt;
-            } else if (name == null) {
-                // This is a structure of the form
-                // <element><choice><name>xxxx</name>...?  Look for
-                // immediate "choice" child, and look in its "name"
-                // children
-                for (Iterator iter = elt.getChildren("choice", ns).iterator(); iter.hasNext();) {
-                    Element choice = (Element) iter.next();
-                    for (Iterator iter2 = choice.getChildren("name", ns).iterator(); iter2.hasNext();) {
-                        Element child = (Element) iter2.next();
-                        if (child.getTextTrim().equals(classname)) {
-                            classElementTable.put(classname, elt);
-                            return elt;
-                        }
+                    if (parentType != attr.type) {
+                        throw new CompilationError(sourceElement, attr.name, new Throwable(
+                                                       /* (non-Javadoc)
+                                                        * @i18n.test
+                                                        * @org-mes="In class '" + p[0] + "' attribute '" + p[1] + "' with type '" + p[2] + "' is overriding superclass attribute with same name but different type: " + p[3]
+                                                        */
+                                                       org.openlaszlo.i18n.LaszloMessages.getMessage(
+                                                           ViewSchema.class.getName(),"051018-364", new Object[] {classname, attr.name, attr.type.toString(), parentType.toString()})
+                                                                                           ));
                     }
                 }
-            }
-        } 
 
-        // class def not found here; descend the tree to search for it
-        for (Iterator iter = elt.getChildren().iterator(); iter.hasNext(); ) {
-            Element child = (Element) iter.next();
-            Element result =  findSchemaClassDef(classname, child);
-            if (result != null) {
-                return result;
+                // Update the in-memory attribute type table
+                setAttributeType(sourceElement, classname, attr.name, attr);
             }
         }
-
-        return (Element) null;
     }
 
     public Type getTypeForName(String name) {
         if (name.equals("text") ||
             name.equals("html"))
             name = "string";
-        if (sRNGtoLPSTypeMap.containsKey(name))
-            return (Type) sRNGtoLPSTypeMap.get(name);
         return super.getTypeForName(name);
     }
 
-    /** Maps definition name to list of DOM Elements in the parsed RNG schema DOM */
-    private final Map referenceTable = new HashMap();
-    /** List of all <ELEMENT> tags in the schema DOM. */
-    private final List schemaElementTable = new ArrayList();
-
-    /** Table which maps class names to their definitions in the
-     * schema DOM, used by findSchemaClassDef() */
-    private final Map classElementTable = new HashMap();
-
-
-    /** Construct a table of <definition> elements from the RNG schema, to make
-     * efficient lookup possible when following <ref> tags.
-     */
-    private void buildReferenceTable (Element elt) {
-        // If it's a <define name="xxx"> add an entry in the referenceTable
-        String eltname = elt.getName();
-        if (eltname.equals("define")) {        
-            String name = elt.getAttributeValue("name");
-            List elts = (List) referenceTable.get(name);
-            if (elts == null) {
-                elts = new ArrayList();
-                referenceTable.put(name, elts);
-            } 
-            elts.add(elt);
-            //System.err.println("[adding ref "+name+" " + elt.getAttribute("name")+"]");
-        } else if (eltname.equals("element")) {
-            schemaElementTable.add(elt);
-        }
-
-        for (Iterator iter = elt.getChildren().iterator(); iter.hasNext(); ) {
-            Element child = (Element) iter.next();
-            buildReferenceTable(child);
-        }
-    }
-
     /** Adds a ClassModel entry into the class table for CLASSNAME. */
     private void makeNewStaticClass (String classname) {
         ClassModel info = new ClassModel(classname, this);
@@ -695,280 +378,16 @@
         if (mClassMap.get(classname) == null) {
             mClassMap.put(classname, info);
         } else {
-            // <font> seems to come out twice when we parse the
-            // schema, so this check doesn't really work.
-            
-            // throw new CompilationError("makeNewStaticClass: duplicate definition for " + classname);
+            throw new CompilationError("makeNewStaticClass: duplicate definition for static class " + classname);
         }
-
     }
 
 
-    /**
-       Walks the schema DOM searching for all <element> tags. For each named <element>, parse out the
-       attribute declarations for it and add them to the in-core attribute-type table. 
-       <p>
-       Definitions of elements can actually occur in the schema as either
-       <pre>
-       &lt;element name="classname"&gt;
-       or
-       &lt;element&gt; &lt;choice&gt; ... ...  &lt;name&gt;classname&lt;/name&gt; &lt;/choice&gt;
-       </pre>
-       <p>
-
-       In the second case above, where a set of element names is declared, we
-       set the attribute types once for each element (class) name.
-
-       <p>
-
-       The reason we need this method is that when a user defines a new class
-       which has one or more attributes, we need to learn if each attribute has
-       been declared by a superclass. That info is available for user-defined
-       classes, in the mClassMap table, but it's not present for 'primitive'
-       system types that are implicitly built into the base schema RNG file. So
-       here's where we parse that info from the base schema.
-
-       <p>
-
-       The algorithm is as follows: buildReferenceTable() is called once at
-       schema load time to initialize a table of <definition> elements by name,
-       for efficient following of <ref> tags.
-
-       <p>
-
-       Make a pass descending from root:
-       <ul>
-       <li>When you get to an <element>, set that to the current class name, and keep adding attributes
-       as you find them, following references. When you hit a "element", change class name.
-       <p>
-       <li>Mark elements as having been visited to  avoid re-traversing them.
-       </ul>
-    */
-    
-    public void parseSchemaAttributes () {
-        for (Iterator eltIter = schemaElementTable.iterator(); eltIter.hasNext();) {
-            Element elt = (Element) eltIter.next();
-
-            // We are starting on a known element tag; what class names does it define?
-            List classnames = new ArrayList();
-            Namespace ns = elt.getNamespace();
-            String name = elt.getAttributeValue("name");
-            // Is this tag of the form <element name="foo"> or
-            // <element><choice><name>foo</name><name>bar</name>... ?
-            if (name != null) {
-                classnames.add(name);
-                //System.err.println("parseSchemaAttributes("+name+")");
-                makeNewStaticClass(name);
-            } else if (name == null) {
-                // This is a structure of the form
-                // <element><choice><name>xxxx</name>...?  Look for
-                // immediate "choice" child, and look in it's "name"
-                // children
-                for (Iterator iter = elt.getChildren("choice", ns).iterator(); iter.hasNext();) {
-                    Element choice = (Element) iter.next();
-                    for (Iterator iter2 = choice.getChildren("name", ns).iterator(); iter2.hasNext();) {
-                        Element child = (Element) iter2.next();
-                        name = child.getTextTrim();
-                        // Add this name to the list of classnames that this element defines
-                        classnames.add(name);
-                        //System.err.println("parseSchemaAttributes("+name+")");
-                        makeNewStaticClass(name);
-                    }
-                }
-            }
-            // OK we're defining some named element, lets follow the
-            // tree down to the next element
-            if (!classnames.isEmpty()) {
-                //System.out.println("calling parseSchemaAttributes:: "+classnames);
-                // Now descend the tree looking for <attribute> tags, and following <refs>
-                for (Iterator iter = elt.getChildren().iterator(); iter.hasNext(); ) {
-                    Element child = (Element) iter.next();
-                    parseSchemaAttributes(child, classnames);
-                }
-            }
-        }
-    }
-
-    /**
-       This descends the schema DOM collecting <attribute> declaration
-       info, but stops the descent wherever another <element> tag is
-       found.
-
-       <ref> tags are followed via the referenceTable map.
-    */
-
-    public void parseSchemaAttributes (Element elt, List classnames) {
-        // Stop if we get to an <element>
-        if (elt.getName().equals("element")) {
-            return;
-        } else if (elt.getName().equals("attribute")) {
-            String attrName = elt.getAttributeValue("name");
-            if (attrName == null) {
-                //throw new RuntimeException("parsing choice attribute names in the schema is unimplemented");
-                // There is actually one unnamed attribute, the "anyName" attribute for datacontent.
-            } else {
-                //System.err.print("parsing attribute "+classnames+"."+attrName);
-
-                String rngTypeName;
-
-                /*
-                  We will see one of these three types of attribute elements:
-
-                  <attribute name="width" a:defaultValue="800">
-                    <ref name="size"/>
-                  </attribute>
-
-                  <attribute name="title" a:defaultValue="Laszlo Presentation Server">
-                    <a:documentation>The string that is used in the browser window.</a:documentation>
-                    <data type="string" datatypeLibrary=""/>
-                  </attribute>
-
-                  <attribute name="fontstyle" a:defaultValue="">
-                    <a:documentation>The default font style for views in this application.</a:documentation>
-                    <choice>
-                      <value>bold</value>
-                      <value>italic</value>
-                      <value>bold italic</value>
-                      <value>plain</value>
-                      <value/>
-                    </choice>
-                  </attribute>
-
-                  // or this degenerate case from menuitem
-                  <attribute name="type">
-                     <value>separator</value>
-                  </attribute>
-                */
-                Namespace ns = elt.getNamespace();
-
-                Element ref = elt.getChild("ref", ns);
-                if (ref != null) {
-                    rngTypeName = ref.getAttributeValue("name");
-                } else {
-                    Element data = elt.getChild("data", ns);
-                    if (data != null) {
-                        rngTypeName = data.getAttributeValue("type");
-                    } else {
-                        // If it's a <choice> or <value>, then it's a token
-                        rngTypeName = "token";
-                    }
-                }
-
-                // Set the attribute type 
-                Type attrType = (Type) sRNGtoLPSTypeMap.get(rngTypeName);
-
-                if (attrType == null) {
-                    throw new RuntimeException(
-/* (non-Javadoc)
- * @i18n.test
- * @org-mes="error parsing RNG schema: unknown attribute type name " + p[0] + "  for attribute " + p[1]
- */
-            org.openlaszlo.i18n.LaszloMessages.getMessage(
-                ViewSchema.class.getName(),"051018-864", new Object[] {rngTypeName, attrName})
-                            );
-                }
-
-                AttributeSpec attrspec = new AttributeSpec(attrName, attrType, null, null);
-                //System.err.println(" ==> "+attrType);
-
-                // Define this attribute on all classnames it applies to
-                Iterator citer = classnames.iterator();
-                while (citer.hasNext()) {
-                    String cname = (String) citer.next();
-                    //System.err.println("adding attribute type from schema: elt(class) "+cname+": "+attrName); 
-
-                    // TODO: [2003-02-04 hqm] There is a special case
-                    // for <splash> elements; the schema contains a
-                    // special <view> declaration which differs from
-                    // the normal one, in that "x" and "y" attributes
-                    // are numeric constants rather than expressions.
-
-                    // To deal with this, we check if this element has
-                    // a parent of <splash> and if so we just discard
-                    // the attribute info. SplashCompiler will have a
-                    // special case to quote values for x and y
-                    // attributes.
-
-                    boolean ignore = false;
-                    // search up the parents for a "splash" element
-                    if (cname.equals("view")) {
-                        Element p = elt;
-                        while (p != null) {
-                            p = p.getParentElement();
-                            if (p == null) {
-                                break;
-                            }
-                            if ((p.getName().equals("element")) && ("splash".equals(p.getAttributeValue("name")))) {
-                                ignore = true;
-                                break;
-                            }
-                        }
-                    }
-
-                    // Look up the ClassModel in the class info table
-                    ClassModel classModel = getClassModel(cname);
-                    if (classModel == null) {
-                        throw new RuntimeException(
-/* (non-Javadoc)
- * @i18n.test
- * @org-mes="parseSchemaAttributes: undefined class: " + p[0]
- */
-            org.openlaszlo.i18n.LaszloMessages.getMessage(
-                ViewSchema.class.getName(),"051018-914", new Object[] {cname})
-);
-                    }
-                    if (ignore) {
-                        //System.err.println("ignoring splash child attribute "+attrName+" "+attrType);
-                    } else {
-                        classModel.attributeSpecs.put(attrName, attrspec);
-                    }
-                }
-            }
-        } else if (elt.getName().equals("ref")) {
-            // follow references
-            String refName = elt.getAttributeValue("name");
-            // The list of all elements that define this reference. A
-            // reference can be split over several different elements
-            // in the schema. See "viewContentElements" for example.
-            List refElements = (List) referenceTable.get(refName);
-            if (refElements == null || refElements.isEmpty()) {
-                throw new RuntimeException(
-/* (non-Javadoc)
- * @i18n.test
- * @org-mes="error parsing schema: could not find definition for reference " + p[0] + " on elt" + p[1]
- */
-            org.openlaszlo.i18n.LaszloMessages.getMessage(
-                ViewSchema.class.getName(),"051018-938", new Object[] {refName, elt})
-);
-            }
-            Iterator riter = refElements.iterator();
-            while (riter.hasNext()) {
-                Element ref = (Element) riter.next();
-                if (ref == null) {
-                    throw new RuntimeException(
-/* (non-Javadoc)
- * @i18n.test
- * @org-mes="error parsing schema: could not find definition for reference " + p[0] + " on elt" + p[1]
- */
-            org.openlaszlo.i18n.LaszloMessages.getMessage(
-                ViewSchema.class.getName(),"051018-938", new Object[] {refName, elt})
-);
-                }
-                parseSchemaAttributes(ref, classnames);
-            }
-        }
-
-        // Descend the tree
-        for (Iterator iter = elt.getChildren().iterator(); iter.hasNext(); ) {
-            Element child = (Element) iter.next();
-            parseSchemaAttributes(child, classnames);
-        }
-    }
-
     static Type getAttributeType(String attrName) {
         return (Type) sAttributeTypes.get(attrName);
     }
-    
+
+
     /**
      * Returns a value representing the type of an attribute within an
      * XML element. Unknown attributes have Expression type.
@@ -1051,7 +470,7 @@
       return lzx;
     }
 
-    public void loadSchema() throws JDOMException, IOException {
+    public void loadSchema(CompilationEnvironment env) throws JDOMException, IOException {
         String schemaPath = SCHEMA_PATH;
         // Load the schema if it hasn't been.
         // Reload it if it's been touched, to make it easier for developers.
@@ -1061,24 +480,70 @@
             // race condition --- although since this doesn't happen in
             // production code, this isn't critical
             sCachedSchemaLastModified = new File(schemaPath).lastModified();
-            // Without this, parsing fails when LPS is installed
-            // in a directory with a space in the name.
-            String schemaURI = "file:///" + schemaPath;
-            sCachedSchemaDOM = new SAXBuilder().build(schemaURI);
+            sCachedSchemaDOM = new Parser().read(new File(schemaPath));
         }
+
+        // This is the base class from which all classes derive unless otherwise
+        // specified. It has no attributes.
+        makeNewStaticClass("Instance");
+
         schemaDOM = (Document) sCachedSchemaDOM.clone();
-        buildReferenceTable(schemaDOM.getRootElement());
-        // Parse out the attribute types of built-in defs
-        parseSchemaAttributes();
+        Element docroot = schemaDOM.getRootElement();
+        ToplevelCompiler ec = (ToplevelCompiler) Compiler.getElementCompiler(docroot, env);
+        Set visited = new HashSet();
+        ec.updateSchema(docroot, this, visited);
+        /** From here on, user-defined classes must not use reserved javascript identifiers */
+        this.enforceValidIdentifier = true;
     }
     
-    public Document getSchemaDOM() throws JDOMException, IOException {
-        if (schemaDOM == null) {
-            loadSchema();
+
+
+    /** Check if a child element can legally be contained in a parent element.
+        This works with the class hierarchy as follows:
+
+        + Look up the ClassModel corresponding to the parentTag
+
+        + Check the containsElements table to see if child tag is in there
+
+        + If not, look up the ClassModel of the child tag, and follow up the chain
+          checking if that name is present in the table
+
+
+           + If not, ascend up the parent classmodel, and call canContainElement recursively
+          
+     */
+    public boolean canContainElement (String parentTag, String childTag) {
+        // Get list of legally nestable tags
+        ClassModel parent = getClassModel(parentTag);
+
+        // TODO [hqm 2007-09]: CHECK FOR NULL HERE 
+
+        Set tagset = parent.getContainsSet();
+        if (tagset.contains(childTag)) {
+            return true;
         }
-        return schemaDOM;
+        // check all superclasses of the childTag
+        ClassModel childclass = getClassModel(childTag);
+
+        // TODO [hqm 2007-09]: CHECK FOR NULL HERE         
+
+        while (childclass != null) {
+            String superclassname = childclass.getSuperclassName();
+            if (tagset.contains(superclassname)) {
+                return true;
+            }
+            childclass = childclass.getSuperclassModel();
+        }
+
+        String parentSuperclassname = parent.getSuperclassName();
+        if (parentSuperclassname != null) {
+            return canContainElement(parentSuperclassname, childTag);
+        }
+
+        return false;
     }
 
+    
     /** @return true if this element is an input text field */
     boolean isInputTextElement(Element e) {
         String classname = e.getName();

Modified: openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ViewSchema_Test.java
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ViewSchema_Test.java	2007-10-04 20:08:12 UTC (rev 6725)
+++ openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/compiler/ViewSchema_Test.java	2007-10-04 22:49:36 UTC (rev 6726)
@@ -3,7 +3,7 @@
  * ****************************************************************************/
 
 /* J_LZ_COPYRIGHT_BEGIN *******************************************************
-* Copyright 2001-2006 Laszlo Systems, Inc.  All Rights Reserved.              *
+* Copyright 2001-2007 Laszlo Systems, Inc.  All Rights Reserved.              *
 * Use is subject to license terms.                                            *
 * J_LZ_COPYRIGHT_END *********************************************************/
 
@@ -81,7 +81,7 @@
 
         ViewSchema schema = new ViewSchema();
         try {
-            schema.loadSchema();
+            schema.loadSchema(new CompilationEnvironment());
         } catch (JDOMException e) {
             throw new RuntimeException(e.getMessage());
         } catch (IOException e) {

Modified: openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/i18n/laszlomessages.properties
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/i18n/laszlomessages.properties	2007-10-04 20:08:12 UTC (rev 6725)
+++ openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/i18n/laszlomessages.properties	2007-10-04 22:49:36 UTC (rev 6726)
@@ -66,9 +66,9 @@
 org.openlaszlo.compiler.ClassCompiler.051018-77=The classname attribute, \"name\" must be a valid identifier for a class definition
 org.openlaszlo.compiler.ClassCompiler.051018-89=The value for the 'extends' attribute on a class definition must be a valid identifier
 org.openlaszlo.compiler.ClassCompiler.051018-106=undefined superclass {0} for class {1}
-org.openlaszlo.compiler.ClassCompiler.051018-131='name'' is a required attribute of <{0}> and must be a valid identifier
+org.openlaszlo.compiler.ClassCompiler.051018-131='name' is a required attribute of <{0}> and must be a valid identifier
 org.openlaszlo.compiler.ClassCompiler.051018-160=In class {0} type ''{1}'', declared for attribute ''{2}'' is not a known data type.
-org.openlaszlo.compiler.ClassCompiler.051018-193='name'' is a required attribute of <{0}> and must be a valid identifier
+org.openlaszlo.compiler.ClassCompiler.051018-193='name' is a required attribute of <{0}> and must be a valid identifier
 org.openlaszlo.compiler.ClassModel.051018-196=The class has a {0} attribute
 org.openlaszlo.compiler.ClassModel.051018-205=The instance has a {0} attribute
 org.openlaszlo.compiler.ClassModel.051018-214=An element within the instance has a {0} attribute
@@ -123,7 +123,7 @@
 org.openlaszlo.compiler.NodeModel.051018-846={0} is deprecated.  This method will be compiled as <method name=''{1}'' instead.  Please update your sources.
 org.openlaszlo.compiler.NodeModel.051018-922=an attribute or method named ''{0}'' already is defined on {1}
 org.openlaszlo.compiler.NodeModel.051018-956=value is null in {0}
-org.openlaszlo.compiler.NodeModel.051018-1157='name'' is a required attribute of <{0}> and must be a valid identifier
+org.openlaszlo.compiler.NodeModel.051018-1157='name' is a required attribute of <{0}> and must be a valid identifier
 org.openlaszlo.compiler.NodeModel.051018-1211=unknown attribute type: {0}
 org.openlaszlo.compiler.NodeModel.051018-1227=In element ''{0}'' attribute ''{1}'' with type ''{2}'' is overriding parent class attribute with same name but different type: {3}
 org.openlaszlo.compiler.NodeModel.051018-1388=Both the class and the instance or subclass define the {0}{1}

Modified: openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/servlets/responders/ResponderCompile.java
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/servlets/responders/ResponderCompile.java	2007-10-04 20:08:12 UTC (rev 6725)
+++ openlaszlo/trunk/WEB-INF/lps/server/src/org/openlaszlo/servlets/responders/ResponderCompile.java	2007-10-04 22:49:36 UTC (rev 6726)
@@ -408,7 +408,6 @@
      * <li> "logdebug"
      * <li> "lzbacktrace"
      * <li> "profile"
-     * <li> "validate"
      * <li> "sourcelocators"
      * <li> "lzr" (swf version := swf5 | swf6)
      * <li> "lzproxied" true|false
@@ -438,14 +437,6 @@
                 props.setProperty(CompilationEnvironment.LOGDEBUG_PROPERTY, logdebug);
             }
 
-            // Look for "validate=boolean" flag, default to true
-            props.setProperty(CompilationEnvironment.VALIDATE_PROPERTY,
-                              LPS.getProperty("compiler.validate", "true"));
-            String validate = req.getParameter(CompilationEnvironment.VALIDATE_PROPERTY);
-            if (validate != null) {
-                props.setProperty(CompilationEnvironment.VALIDATE_PROPERTY, validate);
-            }
-
             // Look for "debug=true" flag
             props.setProperty(CompilationEnvironment.DEBUG_PROPERTY, "false");
             String debug = req.getParameter(CompilationEnvironment.DEBUG_PROPERTY);

Modified: openlaszlo/trunk/lps/components/incubator/textstyle.lzx
===================================================================
--- openlaszlo/trunk/lps/components/incubator/textstyle.lzx	2007-10-04 20:08:12 UTC (rev 6725)
+++ openlaszlo/trunk/lps/components/incubator/textstyle.lzx	2007-10-04 22:49:36 UTC (rev 6726)
@@ -10,7 +10,7 @@
     -->
     <class name="textstyle" extends="style">
         <attribute name="font" value="arial" type="string" />
-        <attribute name="fontsize" value="11" type="number" />
+        <attribute name="fontsize" value="11" />
         <attribute name="fontstyle" value="plain" type="string" />
     </class>    
 </library>

Modified: openlaszlo/trunk/test/compiler_errors/bogus-attribute-error.lzx
===================================================================
--- openlaszlo/trunk/test/compiler_errors/bogus-attribute-error.lzx	2007-10-04 20:08:12 UTC (rev 6725)
+++ openlaszlo/trunk/test/compiler_errors/bogus-attribute-error.lzx	2007-10-04 22:49:36 UTC (rev 6726)
@@ -3,7 +3,7 @@
 <canvas width="300" height="200" bgcolor="red"> 
     <window title="Window 1" x="10" y="10" width="200" height="200" >
         <view>
-	<text>This is some
+    <text>This is some
 text with a couple
 of linebreaks in it.
 </text>
@@ -20,8 +20,11 @@
    <mywindow bgcolor="yellow" boogaboogah="'bogus_attribute'" fluffy="parrot food">
    </mywindow>
 
+   <view blah="17"/>
+          <method event="oninit" method="_doCheckConfig"/>
+
 </canvas>
 <!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
-* Copyright 2001-2004 Laszlo Systems, Inc.  All Rights Reserved.              *
+* Copyright 2001-2007 Laszlo Systems, Inc.  All Rights Reserved.              *
 * Use is subject to license terms.                                            *
 * X_LZ_COPYRIGHT_END ****************************************************** -->

Modified: openlaszlo/trunk/test/compiler_errors/redfine-builtin.lzx
===================================================================
--- openlaszlo/trunk/test/compiler_errors/redfine-builtin.lzx	2007-10-04 20:08:12 UTC (rev 6725)
+++ openlaszlo/trunk/test/compiler_errors/redfine-builtin.lzx	2007-10-04 22:49:36 UTC (rev 6726)
@@ -1,6 +1,6 @@
 
 <canvas layout="spacing:10">
-   <class name="textfield"/>
+   <class name="text"/>
 
    <edittext>
        <method event="onkeyup">
@@ -9,3 +9,7 @@
    </edittext>
 
 </canvas>
+<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
+* Copyright 2001-2007 Laszlo Systems, Inc.  All Rights Reserved.              *
+* Use is subject to license terms.                                            *
+* X_LZ_COPYRIGHT_END ****************************************************** -->

Modified: openlaszlo/trunk/test/lfc/data/testheaderresponse.lzx
===================================================================
--- openlaszlo/trunk/test/lfc/data/testheaderresponse.lzx	2007-10-04 20:08:12 UTC (rev 6725)
+++ openlaszlo/trunk/test/lfc/data/testheaderresponse.lzx	2007-10-04 22:49:36 UTC (rev 6726)
@@ -3,7 +3,7 @@
 
   <dataset name="dsheaders" timeout="400000"
     src="http:testdata.xml"
-    proxied="true"
+    proxied="xlxinherit"
     getresponseheaders="true"
            onerror="Debug.write('testheaderresponse: dsheaders got onerror')" 
            ontimeout="Debug.write('testheaderresponse: dsheaders got ontimeout')" 



More information about the Laszlo-checkins mailing list