KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openlaszlo > compiler > ClassCompiler


1 /* *****************************************************************************
2  * ClassNode.java
3  * ****************************************************************************/

4
5 /* J_LZ_COPYRIGHT_BEGIN *******************************************************
6 * Copyright 2001-2004 Laszlo Systems, Inc. All Rights Reserved. *
7 * Use is subject to license terms. *
8 * J_LZ_COPYRIGHT_END *********************************************************/

9
10 package org.openlaszlo.compiler;
11 import java.io.*;
12 import java.util.*;
13 import org.apache.log4j.*;
14 import org.jdom.Element;
15 import org.openlaszlo.xml.internal.XMLUtils;
16 import org.openlaszlo.xml.internal.MissingAttributeException;
17 import org.openlaszlo.xml.internal.Schema;
18 import org.openlaszlo.xml.internal.Schema.Type;
19 import org.openlaszlo.sc.ScriptCompiler;
20 import org.openlaszlo.utils.ChainedException;
21 import org.openlaszlo.css.CSSParser;
22
23 /** Compiler for <code>class</code> class elements.
24  */

25 class ClassCompiler extends ViewCompiler {
26     /**
27        For a declaration of a class named "foobar"
28        
29        <pre>&lt;class name="foobar" extends="view"&gt;</pre>
30
31        We are going to call
32
33        <pre>
34        LzInstantiateView(
35       {
36         name: 'userclass',
37         attrs: {
38                 parent: "view",
39                 initobj: {
40                              name: "foobar",
41                              attrs: {name: "foobar"},
42
43        </pre>
44      */

45     static final String JavaDoc DEFAULT_SUPERCLASS_NAME = "view";
46     
47     ClassCompiler(CompilationEnvironment env) {
48         super(env);
49     }
50     
51     /** Returns true iff this class applies to this element.
52      * @param element an element
53      * @return see doc
54      */

55     static boolean isElement(Element element) {
56         return element.getName().equals("class");
57     }
58
59     /** Parse out an XML class definition, add the superclass and
60      * attribute types to the schema.
61      *
62      * <p>
63      * For each CLASS element, find child ATTRIBUTE tags, and add them
64      * to the schema. */

65     void updateSchema(Element element, ViewSchema schema, Set visited) {
66         Element elt = element;
67         
68         String JavaDoc classname = elt.getAttributeValue("name");
69         String JavaDoc superclass = elt.getAttributeValue("extends");
70         
71         if (classname == null || !ScriptCompiler.isIdentifier(classname)) {
72             CompilationError cerr = new CompilationError("The classname attribute, \"name\" must be a valid identifier for a class definition", elt);
73             throw(cerr);
74         }
75         
76         if (superclass != null && !ScriptCompiler.isIdentifier(superclass)) {
77             mEnv.warn("The value for the 'extends' attribute on a class definition must be a valid identifier", elt);
78             superclass = null;
79         }
80         if (superclass == null) {
81             // Default to LzView
82
superclass = ClassCompiler.DEFAULT_SUPERCLASS_NAME;
83         }
84         
85         ClassModel superclassinfo = schema.getClassModel(superclass);
86         if (superclassinfo == null) {
87             throw new CompilationError("undefined superclass " + superclass + " for class "+classname, elt);
88         }
89         
90         // Collect up the attribute defs, if any, of this class
91
List attributeDefs = new ArrayList();
92         Iterator iterator = element.getContent().iterator();
93         
94         while (iterator.hasNext()) {
95             Object JavaDoc o = iterator.next();
96             if (o instanceof Element) {
97                 Element child = (Element) o;
98                 // Is this an element named ATTRIBUTE which is a
99
// direct child of a CLASS tag?
100
if (child.getName().equals("attribute")) {
101                     String JavaDoc attrName;
102                     try {
103                         attrName = requireIdentifierAttributeValue(child, "name");
104                     } catch (MissingAttributeException e) {
105                         throw new CompilationError(
106                             "'name' is a required attribute of <" + child.getName() + "> and must be a valid identifier", child);
107                     }
108                     
109                     String JavaDoc attrTypeName = child.getAttributeValue("type");
110                     String JavaDoc attrDefault = child.getAttributeValue("default");
111                     String JavaDoc attrSetter = child.getAttributeValue("setter");
112                     String JavaDoc attrRequired = child.getAttributeValue("required");
113                     
114                     ViewSchema.Type attrType;
115                     if (attrTypeName == null) {
116                         // Check if this attribute exists in ancestor classes,
117
// and if so, default to that type.
118
attrType = superclassinfo.getAttributeType(attrName);
119                         if (attrType == null) {
120                             // The default attribute type
121
attrType = ViewSchema.EXPRESSION_TYPE;
122                         }
123                     } else {
124                         attrType = schema.getTypeForName(attrTypeName);
125                     }
126                     
127                     if (attrType == null) {
128                         throw new CompilationError("In class "+classname+ " type '"+attrTypeName +"', declared for attribute '"+
129                                                    attrName + "' is not a known data type.", element);
130                     }
131                     
132                     AttributeSpec attrSpec =
133                         new AttributeSpec(attrName, attrType, attrDefault,
134                                           attrSetter, child);
135                     if (attrName.equals("text") && attrTypeName != null) {
136                         if ("text".equals(attrTypeName))
137                             attrSpec.contentType = attrSpec.TEXT_CONTENT;
138                         else if ("html".equals(attrTypeName))
139                             attrSpec.contentType = attrSpec.HTML_CONTENT;
140                     }
141                     attributeDefs.add(attrSpec);
142                 }
143             }
144         }
145         
146         // Add this class to the schema
147
schema.addElement(element, classname, superclass, attributeDefs);
148     }
149     
150     public void compile(Element elt) {
151         String JavaDoc className;
152         try {
153             className = requireIdentifierAttributeValue(elt, "name");
154         } catch (MissingAttributeException e) {
155             throw new CompilationError("'name' is a required attribute of <" + elt.getName() + "> and must be a valid identifier", elt);
156         }
157                 
158         String JavaDoc extendsName = XMLUtils.getAttributeValue(
159             elt, "extends", DEFAULT_SUPERCLASS_NAME);
160         
161         ViewSchema schema = mEnv.getSchema();
162         ClassModel classModel = schema.getClassModel(className);
163         
164         String JavaDoc linedir = CompilerUtils.sourceLocationDirective(elt, true);
165         ViewCompiler.preprocess(elt, mEnv);
166         
167         FontInfo fontInfo = new FontInfo(mEnv.getCanvas().getFontInfo());
168         if (mEnv.getSWFVersion().equals("swf5")) {
169             ViewCompiler.collectInputFonts(elt, mEnv, fontInfo, new HashSet());
170         }
171         
172         // We compile a class declaration just like a view, and then
173
// add attribute declarations and perhaps some other stuff that
174
// the runtime wants.
175
NodeModel model = NodeModel.elementAsModel(elt, schema, mEnv);
176         model = model.expandClassDefinitions();
177         model.removeAttribute("name");
178         classModel.setNodeModel(model);
179         Map viewMap = model.asMap();
180         
181         // Put in the class name, not "class"
182
viewMap.put("name", ScriptCompiler.quote(className));
183         
184         // Construct a Javascript statement from the initobj map
185
String JavaDoc initobj;
186         try {
187             java.io.Writer JavaDoc writer = new java.io.StringWriter JavaDoc();
188             ScriptCompiler.writeObject(viewMap, writer);
189             initobj = writer.toString();
190         } catch (java.io.IOException JavaDoc e) {
191             throw new ChainedException(e);
192         }
193         // Generate a call to queue instantiation
194
StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
195         buffer.append(VIEW_INSTANTIATION_FNAME +
196                       "({name: 'userclass', attrs: " +
197                       "{parent: " +
198                       ScriptCompiler.quote(extendsName) +
199                       ", initobj: " + initobj +
200                       "}}" +
201                       ", " + ((ElementWithLocationInfo)elt).model.totalSubnodes() +
202                       ");\n");
203         if (!classModel.getInline()) {
204             ClassModel superclassModel = classModel.getSuperclassModel();
205             mEnv.compileScript(buffer.toString(), elt);
206         }
207         
208         // TODO: [12-27-2002 ows] use the log4j API instead of this property
209
boolean tracexml =
210             mEnv.getProperties().getProperty("trace.xml", "false") == "true";
211         if (tracexml) {
212             Logger mXMLLogger = Logger.getLogger("trace.xml");
213             mXMLLogger.info("compiling class definition:");
214             org.jdom.output.XMLOutputter outputter =
215                 new org.jdom.output.XMLOutputter();
216             outputter.setTextNormalize(true);
217             mXMLLogger.info(outputter.outputString(elt));
218             mXMLLogger.info("compiled to:\n" + buffer.toString() + "\n");
219         }
220     }
221 }
222
Popular Tags