Source Code Cross Referenced for ViewCompiler.java in  » Ajax » Laszlo-4.0.10 » org » openlaszlo » compiler » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Ajax » Laszlo 4.0.10 » org.openlaszlo.compiler 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /* -*- mode: Java; c-basic-offset: 2; -*- */
002:
003:        /**
004:         * LZX View Compiler
005:         */package org.openlaszlo.compiler;
006:
007:        import java.io.*;
008:        import java.text.DecimalFormat;
009:        import java.text.FieldPosition;
010:        import java.util.*;
011:
012:        import org.openlaszlo.css.CSSParser;
013:        import org.openlaszlo.sc.ScriptCompiler;
014:        import org.openlaszlo.server.LPS;
015:        import org.openlaszlo.xml.internal.Schema;
016:        import org.openlaszlo.xml.internal.MissingAttributeException;
017:        import org.openlaszlo.utils.ChainedException;
018:        import org.openlaszlo.xml.internal.XMLUtils;
019:        import org.apache.log4j.*;
020:        import java.util.regex.*;
021:        import org.openlaszlo.compiler.ViewSchema.ColorFormatException;
022:        import org.openlaszlo.utils.FileUtils;
023:
024:        import java.io.*;
025:        import java.util.*;
026:        import org.jdom.Attribute;
027:        import org.jdom.Element;
028:
029:        /** Responsible for compiling elements that compile into instances of
030:         * LzNode.  This is called ViewCompiler for historical reasons; it
031:         * would more appropriately be called NodeCompiler.
032:         *
033:         * Node compilation consists of these steps:<ul>
034:         * <li> compute text metrics
035:         * <li> call the XML compiler to generate bytecodes that recreate the
036:         * view template subtree and pass it to a runtime view instantiation
037:         * library
038:         * </ul>
039:         */
040:        public class ViewCompiler extends ElementCompiler {
041:            // +=2 so you can see cursor at end of line
042:            private static final int INPUT_TEXTWIDTH_FUDGE_FACTOR = 2;
043:
044:            private static final String FONTSTYLE_ATTRIBUTE = "fontstyle";
045:            private static final String WHEN_IMMEDIATELY = "immediately";
046:            private static final String WHEN_ONCE = "once";
047:            private static final String WHEN_ALWAYS = "always";
048:            private static final String WHEN_PATH = "path";
049:
050:            private ViewSchema mSchema;
051:
052:            private static Logger mLogger = Logger
053:                    .getLogger(ViewCompiler.class);
054:            private static Logger mTraceLogger = Logger.getLogger("trace.xml");
055:
056:            public ViewCompiler(CompilationEnvironment env) {
057:                super (env);
058:                mSchema = env.getSchema();
059:                mTraceLogger.setLevel(Level.INFO);
060:            }
061:
062:            private static final String SERVERLESS_WARNINGS_PROPERTY_FILE = (LPS
063:                    .getMiscDirectory()
064:                    + File.separator + "lzx-server-only-apis.properties");
065:            private static final Properties sServerOnlyTags = new Properties();
066:
067:            static {
068:                try {
069:                    InputStream is = new FileInputStream(
070:                            SERVERLESS_WARNINGS_PROPERTY_FILE);
071:                    try {
072:                        sServerOnlyTags.load(is);
073:                    } finally {
074:                        is.close();
075:                    }
076:                } catch (java.io.IOException e) {
077:                    mLogger.warn("Can't find server-only APIs config file  "
078:                            + SERVERLESS_WARNINGS_PROPERTY_FILE);
079:                }
080:            }
081:
082:            public void compile(Element element) throws CompilationError {
083:                preprocess(element, mEnv);
084:                FontInfo fontInfo = null;
085:
086:                String name = element.getName();
087:                if (mEnv.isCanvas()) {
088:                    if (name != null && sServerOnlyTags.containsKey(name)
089:                            && !mEnv.getCanvas().isProxied()) {
090:                        mEnv.warn(
091:                        /* (non-Javadoc)
092:                         * @i18n.test
093:                         * @org-mes="The tag '" + p[0] + "' will not work as expected when used in a serverless application."
094:                         */
095:                        org.openlaszlo.i18n.LaszloMessages.getMessage(
096:                                ViewCompiler.class.getName(), "051018-99",
097:                                new Object[] { name }));
098:                    }
099:
100:                    fontInfo = new FontInfo(mEnv.getCanvas().getFontInfo());
101:                    try {
102:                        fontInfo = new FontInfo(mEnv.getCanvas().getFontInfo());
103:                        mapTextMetricsCompilation(element, mEnv, fontInfo,
104:                                new HashSet());
105:                    } catch (NumberFormatException e) {
106:                        throw new CompilationError(e.getMessage());
107:                    }
108:                }
109:                compileXML(element, fontInfo);
110:            }
111:
112:            /** Returns true if this node applies to the element.  Anything
113:             * that the interface compiler doesn't recognize is considered a
114:             * view node, so this always returns true.
115:             * @param element an element
116:             * @return see doc
117:             */
118:            static boolean isElement(Element element) {
119:                return true;
120:            }
121:
122:            /** Collect the names of classes that are referenced. */
123:            static void collectElementNames(Element element, Set names) {
124:                names.add(element.getName());
125:                collectLayoutElement(element, names);
126:                for (Iterator iter = element.getChildren().iterator(); iter
127:                        .hasNext();) {
128:                    collectElementNames((Element) iter.next(), names);
129:                }
130:            }
131:
132:            static void collectLayoutElement(Element element, Set names) {
133:                if (element.getAttributeValue("layout") != null) {
134:                    try {
135:                        Map properties = new CSSParser(new AttributeStream(
136:                                element, "layout")).Parse();
137:                        String layoutClass = (String) properties.get("class");
138:                        if (layoutClass == null)
139:                            layoutClass = "simplelayout";
140:                        names.add(layoutClass);
141:                    } catch (org.openlaszlo.css.ParseException e) {
142:                    } catch (org.openlaszlo.css.TokenMgrError e) {
143:                        // The compilation phase will report the error.
144:                    }
145:                }
146:            }
147:
148:            /** Compile a XML element and generate code that binds it to a
149:             * runtime data structure named _lzViewTemplate.
150:             *
151:             * @param element an element
152:             * @param fontInfo font info inherited from canvas
153:             */
154:            void compileXML(Element element, FontInfo fontInfo) {
155:                // TODO: [2007-09-03 ptw] (LPP-4634) You should not be able to
156:                // get here.  This appears to happen when a binary file has
157:                // already included a sub-library and that same sub-library is
158:                // included by a source file.  Since the include is already
159:                // loaded, it is not expanded in expandIncludes, but because
160:                // ViewCompiler.isElement returns true for everything, we end up
161:                // here.  For now, just don't do anything.
162:                if ("include".equals(element.getName()))
163:                    return;
164:
165:                // TODO: [12-27-2002 ows] use the log4j API instead of this property
166:                boolean tracexml = mEnv.getBooleanProperty("trace.xml");
167:                if (tracexml) {
168:                    mTraceLogger.info("compiling XML:");
169:                    org.jdom.output.XMLOutputter outputter = new org.jdom.output.XMLOutputter();
170:                    mTraceLogger.info(outputter.outputString(element));
171:                }
172:
173:                NodeModel model = NodeModel.elementAsModel(element, mSchema,
174:                        mEnv);
175:                model = model.expandClassDefinitions();
176:                String script = VIEW_INSTANTIATION_FNAME + "("
177:                        + model.asJavascript() + ", " + model.totalSubnodes()
178:                        + ");";
179:
180:                // Don't keep non-class models around
181:                if (!element.getName().equals("class")) {
182:                    ((ElementWithLocationInfo) element).model = null;
183:                }
184:
185:                if (tracexml) {
186:                    mLogger.debug(
187:                    /* (non-Javadoc)
188:                     * @i18n.test
189:                     * @org-mes="compiled to:\n" + p[0] + "\n"
190:                     */
191:                    org.openlaszlo.i18n.LaszloMessages.getMessage(
192:                            ViewCompiler.class.getName(), "051018-186",
193:                            new Object[] { script }));
194:                }
195:                try {
196:                    mEnv.compileScript(script, element);
197:                } catch (CompilationError e) {
198:                    String solution = SolutionMessages.findSolution(e
199:                            .getMessage());
200:                    e.setSolution(solution);
201:                    throw e;
202:                }
203:            }
204:
205:            /**
206:             * Modify the DOM in place, to what the runtime expects.  This
207:             * function encapsulates the behavior that is common to root
208:             * views, and class definitions.
209:             *
210:             * Preprocessing consists of compiling resources, and turning
211:             * view-specific source-format attributes into runtime format
212:             *
213:             * @param elt an <code>Element</code> value
214:             * @param env a <code>CompilationEnvironment</code> value
215:             */
216:            static void preprocess(Element elt, CompilationEnvironment env) {
217:                compileResources(elt, env);
218:                compileClickResources(elt, env);
219:                compileAttributes(elt, env);
220:            }
221:
222:            /**
223:             * Modify elt and its children to replace source attribute values
224:             * by runtime values.
225:             */
226:            static void compileAttributes(Element elt,
227:                    CompilationEnvironment env) {
228:                if (elt.getName().equals("dataset")) {
229:                    String src = elt.getAttributeValue("src");
230:                    if (src == null) {
231:                        // This is a local dataset.  DataCompiler has already
232:                        // processed it.  TBD: move this check to isElement,
233:                        // and make it an assert since DataCompiler should
234:                        // have already processed it.
235:                        return;
236:                    }
237:                    src = env.adjustRelativeURL(src, elt);
238:                    elt.setAttribute("src", src);
239:                }
240:                Iterator iter;
241:                for (iter = elt.getChildren().iterator(); iter.hasNext();) {
242:                    compileAttributes((Element) iter.next(), env);
243:                }
244:            }
245:
246:            static HashMap sUnsupportedServerlessFiletypes = new HashMap();
247:            static HashMap sUnsupportedServerlessFiletypesSWF7 = new HashMap();
248:            {
249:                sUnsupportedServerlessFiletypes.put("bmp", "true");
250:                sUnsupportedServerlessFiletypes.put("tiff", "true");
251:                sUnsupportedServerlessFiletypes.put("tif", "true");
252:                sUnsupportedServerlessFiletypes.put("wmf", "true");
253:                sUnsupportedServerlessFiletypes.put("wmv", "true");
254:
255:                sUnsupportedServerlessFiletypesSWF7.put("png", "true");
256:                sUnsupportedServerlessFiletypesSWF7.put("gif", "true");
257:
258:            }
259:
260:            static void checkUnsupportedMediaTypes(CompilationEnvironment env,
261:                    Element elt, String url) {
262:                String suffix = FileUtils.getExtension(url);
263:                if (env.isSWF()) {
264:                    if ((sUnsupportedServerlessFiletypes.containsKey(suffix
265:                            .toLowerCase()))
266:                            || (env.getSWFVersionInt() < 8 && sUnsupportedServerlessFiletypesSWF7
267:                                    .containsKey(suffix.toLowerCase()))) {
268:                        env.warn(
269:                        /* (non-Javadoc)
270:                         * @i18n.test
271:                         * @org-mes="The runtime loadable resource type '" + p[0] + " is not supported by the Flash runtime. Supported resource types are JPEG (non-interlaced), SWF, and MP3"
272:                         */
273:                        org.openlaszlo.i18n.LaszloMessages.getMessage(
274:                                ViewCompiler.class.getName(), "051018-258",
275:                                new Object[] { url }), elt);
276:                    }
277:                } else {
278:                    // TODO: [2006-06-19 ptw] Handle media types for DHTML, etc.
279:                }
280:            }
281:
282:            /**
283:             * Compiles all resources under the current element
284:             *
285:             * @param env
286:             * @param elt
287:             */
288:            static void compileResources(Element elt, CompilationEnvironment env) {
289:                final String RESOURCE_ATTR_NAME = "resource";
290:
291:                // check for immediate <attribute name="resource" .../> children
292:                for (Iterator iter = elt.getChildren().iterator(); iter
293:                        .hasNext();) {
294:                    Element child = (Element) iter.next();
295:                    if (child.getName().equals("attribute")
296:                            && RESOURCE_ATTR_NAME.equals(child
297:                                    .getAttributeValue("name"))) {
298:                        String val = child.getAttributeValue("value");
299:                        // You are not allowed declare a resource attribute value twice
300:                        if (val == null) {
301:                            continue;
302:                        } else {
303:                            String val2 = elt
304:                                    .getAttributeValue(RESOURCE_ATTR_NAME);
305:                            if (val2 != null) {
306:                                env.warn(
307:                                /* (non-Javadoc)
308:                                 * @i18n.test
309:                                 * @org-mes="The resource attribute on this view was declared more than once, as '" + p[0] + "', and as '" + p[1] + "'"
310:                                 */
311:                                org.openlaszlo.i18n.LaszloMessages.getMessage(
312:                                        ViewCompiler.class.getName(),
313:                                        "051018-292",
314:                                        new Object[] { val2, val }), elt);
315:                            }
316:
317:                            // This is needed for backward compatibility with
318:                            // the deprecated "when='...'" syntax
319:                            String when = child.getAttributeValue("when");
320:                            if (when != null) {
321:                                val = "$" + when + "{" + val + "}";
322:                            }
323:
324:                            elt.setAttribute(RESOURCE_ATTR_NAME, val);
325:                            // remove this <attribute name="resource" .../>
326:                            // child because we just copied the value to the
327:                            // parent elt.
328:                            iter.remove();
329:                        }
330:                    }
331:                }
332:
333:                String value = elt.getAttributeValue(RESOURCE_ATTR_NAME);
334:
335:                if (value != null) {
336:                    if (value.matches("\\s*\\$\\s*\\(")) {
337:                        env
338:                                .warn(
339:                                        "The syntax '$(...)' is not valid, "
340:                                                + "you probably meant to use curly-braces instead '${...}'",
341:                                        elt);
342:                        //} else if (value.startsWith("$") && value.endsWith("}")) {
343:                    } else if (value.matches(sConstraintPatStr)) {
344:                        // It's a $xxx{...} attribute initializer, let's not
345:                        // do anything at all, and let the viewsystem takes
346:                        // care of finding the resource by id.
347:                    } else if (ScriptCompiler.isIdentifier(value)) {
348:                        // id: leave intact: nothing to do
349:                        Set resourceNames = env.getResourceNames();
350:                        if (!resourceNames.contains(value)) {
351:                            // Add this reference to be checked again after
352:                            // we've fully parsed the whole app.
353:                            env.addResourceReference(value, elt);
354:                        }
355:                    } else if (XMLUtils.isURL(value)) {
356:                        if (env.isCanvas() && !env.getCanvas().isProxied()) {
357:                            checkUnsupportedMediaTypes(env, elt, value);
358:                        }
359:                        // URL: relativize, and rename to "source" for runtime
360:                        value = env.adjustRelativeURL(value, elt);
361:                        // If it's a relative pathname with no hostname
362:                        // (e.g. "http:resource"), the runtime expects a
363:                        // bare name (e.g. "resource")
364:                        try {
365:                            java.net.URL url = new java.net.URL(value);
366:                            if (url.getHost().equals("")
367:                                    && !url.getPath().startsWith("/")) {
368:                                value = url.getPath();
369:                                if (url.getQuery() != null
370:                                        && url.getQuery().length() > 0) {
371:                                    value += "?" + url.getQuery();
372:                                }
373:                            }
374:                        } catch (java.net.MalformedURLException e) {
375:                            throw new ChainedException(e);
376:                        }
377:                        elt.removeAttribute(RESOURCE_ATTR_NAME);
378:                        elt.setAttribute("source", ScriptCompiler.quote(value));
379:
380:                    } else {
381:                        // pathname: turn into an id
382:                        File file = env.resolveReference(elt,
383:                                RESOURCE_ATTR_NAME);
384:                        // N.B.: Resources are always imported into the main
385:                        // program for the Flash target, hence the use of
386:                        // getResourceGenerator below
387:                        try {
388:                            value = env.getResourceGenerator().importResource(
389:                                    file);
390:                        } catch (ObjectWriter.ImportResourceError e) {
391:                            env.warn(e, elt);
392:                        }
393:                        elt.setAttribute(RESOURCE_ATTR_NAME, value);
394:
395:                        if (env.isCanvas()) {
396:                            Element info = new Element("resolve");
397:                            info.setAttribute("src", elt
398:                                    .getAttributeValue(RESOURCE_ATTR_NAME));
399:                            try {
400:                                info.setAttribute("pathname", file
401:                                        .getCanonicalPath());
402:                            } catch (java.io.IOException ioe) {
403:                                mLogger.warn(
404:                                /* (non-Javadoc)
405:                                 * @i18n.test
406:                                 * @org-mes="Can't canonicalize " + p[0]
407:                                 */
408:                                org.openlaszlo.i18n.LaszloMessages.getMessage(
409:                                        ViewCompiler.class.getName(),
410:                                        "051018-384", new Object[] { file
411:                                                .toString() }));
412:                            }
413:                            env.getCanvas().addInfo(info);
414:                        }
415:                    }
416:                }
417:
418:                // Recurse
419:                Iterator iter;
420:                for (iter = elt.getChildren().iterator(); iter.hasNext();) {
421:                    compileResources((Element) iter.next(), env);
422:                }
423:            }
424:
425:            static void compileClickResources(Element elt,
426:                    CompilationEnvironment env) {
427:                final String ATTR_NAME = "clickregion";
428:                String value = elt.getAttributeValue(ATTR_NAME);
429:
430:                if (value != null) {
431:                    if (value.matches(sConstraintPatStr)
432:                            || ScriptCompiler.isIdentifier(value)
433:                            || XMLUtils.isURL(value)) {
434:                        env.warn(
435:                        /* (non-Javadoc)
436:                         * @i18n.test
437:                         * @org-mes="The value of the " + p[0] + "attribute" + "must be a file name."
438:                         */
439:                        org.openlaszlo.i18n.LaszloMessages.getMessage(
440:                                ViewCompiler.class.getName(), "051018-414",
441:                                new Object[] { ATTR_NAME }), elt);
442:                    } else {
443:                        // pathname: turn into an id
444:                        File file = env.resolveReference(elt, ATTR_NAME);
445:                        try {
446:                            value = env.getResourceGenerator()
447:                                    .importClickResource(file);
448:                        } catch (ObjectWriter.ImportResourceError e) {
449:                            env.warn(e, elt);
450:                        }
451:                        elt.setAttribute(ATTR_NAME, value);
452:                    }
453:                }
454:
455:                // Recurse
456:                Iterator iter;
457:                for (iter = elt.getChildren().iterator(); iter.hasNext();) {
458:                    compileClickResources((Element) iter.next(), env);
459:                }
460:            }
461:
462:            static void checkUnresolvedResourceReferences(
463:                    CompilationEnvironment env) {
464:                Map refs = env.resourceReferences();
465:                Set resourceNames = env.getResourceNames();
466:                for (Iterator iter = refs.keySet().iterator(); iter.hasNext();) {
467:                    String resourceId = (String) iter.next();
468:                    Element elt = (Element) refs.get(resourceId);
469:                    if (!resourceNames.contains(resourceId)) {
470:                        env.warn(
471:                        /* (non-Javadoc)
472:                         * @i18n.test
473:                         * @org-mes="The resource named '" + p[0] + "' has not been declared"
474:                         */
475:                        org.openlaszlo.i18n.LaszloMessages.getMessage(
476:                                ViewCompiler.class.getName(), "051018-450",
477:                                new Object[] { resourceId }), elt);
478:                    }
479:                }
480:            }
481:
482:            /**
483:             * Walk the whole superclass chain, starting at the root, merging fontInfo.
484:             */
485:            protected static void mergeClassFontInfo(Element elt,
486:                    FontInfo fontInfo, CompilationEnvironment env) {
487:                String classname = elt.getName();
488:                // check for a cached fontInfo on the class
489:                FontInfo cachedInfo = env.getClassFontInfo(classname);
490:                if (cachedInfo != null) {
491:                    fontInfo.mergeFontInfoFrom(cachedInfo);
492:                    return;
493:                }
494:
495:                ViewSchema schema = env.getSchema();
496:                ClassModel classinfo = schema.getClassModel(classname);
497:                if (classinfo == null || classinfo.definition == null) {
498:                    return;
499:                }
500:
501:                // Build a list of superclasses 
502:                Vector parents = new Vector();
503:                ClassModel lzxclass = classinfo;
504:                // walk 
505:                while (lzxclass != null) {
506:                    parents.insertElementAt(lzxclass, 0);
507:                    lzxclass = lzxclass.super class;
508:                }
509:
510:                // A blank FontInfo with all empty slots
511:                FontInfo cinfo = FontInfo.blankFontInfo();
512:
513:                // Pop off elements starting at base class
514:                while (parents.size() > 0) {
515:                    lzxclass = (ClassModel) parents.firstElement();
516:                    parents.removeElementAt(0); // pop
517:                    mergeClassFontInfo(lzxclass, cinfo);
518:                }
519:
520:                env.addClassFontInfo(classname, cinfo);
521:                // apply the class' style changes, if any, to our fontInfo arg
522:                fontInfo.mergeFontInfoFrom(cinfo);
523:            }
524:
525:            /**
526:             * Merge FontInfo from a class definition.
527:             */
528:            protected static void mergeClassFontInfo(ClassModel classinfo,
529:                    FontInfo fontInfo) {
530:                if (classinfo != null && classinfo.definition != null) {
531:                    Element celt = classinfo.definition;
532:                    mergeFontInfo(celt, fontInfo);
533:                }
534:            }
535:
536:            /**
537:             * Adds in text widths for all text views below this element that
538:             * need them.  This walks down into class definitions, merging
539:             * font info as it goes.  We don't need to walk into class defs
540:             * for measuring text, since we have no way to pass those text
541:             * widths to the runtime, but we do need this to check if we need
542:             * to import the default bold or italic fonts.
543:             * 
544:             * 
545:             *
546:             * @param env
547:             * @param elt
548:             * @param fontInfo the current font name/style/size
549:             */
550:            protected void mapTextMetricsCompilation(Element elt,
551:                    CompilationEnvironment env, FontInfo fontInfo, Set classList) {
552:
553:                classList = new HashSet(classList);
554:
555:                // Clone a copy of the font info
556:                fontInfo = new FontInfo(fontInfo);
557:
558:                // Check class defaults for font info
559:                mergeClassFontInfo(elt, fontInfo, env);
560:                // Now override with any directly declared attributes
561:                mergeFontInfo(elt, fontInfo);
562:
563:                String fontName = fontInfo.getName();
564:
565:                // If it inherits from text or inputttext, annotate it with font info
566:                if ("text".equals(elt.getName())
567:                        || "text".equals(mSchema
568:                                .getBaseClassname(elt.getName()))
569:                        || "inputtext".equals(elt.getName())
570:                        || "inputtext".equals(mSchema.getBaseClassname(elt
571:                                .getName()))) {
572:                    compileTextMetrics(elt, env, fontInfo);
573:                }
574:                ClassModel classinfo = env.getSchema().getClassModel(
575:                        elt.getName());
576:
577:                // If this invokes a 'user-defined' class, let's walk that
578:                // class's source tree now
579:                if (classinfo != null && classinfo.definition != null) {
580:                    // check if we are in an instance of a class that we are
581:                    // already descended into (loop detection)
582:                    if (classList.contains(elt.getName().intern())) {
583:                        return;
584:                    }
585:                    for (Iterator iter = classinfo.definition.getChildren()
586:                            .iterator(); iter.hasNext();) {
587:                        Element e = (Element) iter.next();
588:                        String ename = e.getName();
589:                        if (!(ename.equals("method") || ename
590:                                .equals("attribute"))) {
591:                            // Avoid recursively traversing class definitions.
592:                            // Mark this class as having been traversed, to
593:                            // avoid loops.
594:                            classList.add(classinfo.className.intern());
595:                            mapTextMetricsCompilation(e, env, fontInfo,
596:                                    classList);
597:                        }
598:                    }
599:                }
600:
601:                // Now do immediate children
602:                for (Iterator iter = elt.getChildren().iterator(); iter
603:                        .hasNext();) {
604:                    Element e = (Element) iter.next();
605:                    mapTextMetricsCompilation(e, env, fontInfo, classList);
606:                }
607:            }
608:
609:            /** Merges font name/size/style from an element's direct
610:             * attributes into a FontInfo */
611:            protected static void mergeFontAttributes(Element elt,
612:                    FontInfo fontInfo) {
613:                String myfont = getAttributeValue(elt, "font");
614:                if (myfont != null) {
615:                    if (myfont.matches("\\s*[^${}]*\\s*")) {
616:                        fontInfo.setName(myfont);
617:                    } else {
618:                        // we don't know what font value is, so set back to the 'unknown' value
619:                        fontInfo.setName(FontInfo.NULL_FONT);
620:                    }
621:                }
622:
623:                String mysize = getAttributeValue(elt, "fontsize");
624:                if (mysize != null) {
625:                    if (mysize.matches(sFontSizePatStr)) {
626:                        fontInfo.setSize(mysize);
627:                    } else {
628:                        // we don't know what font size is, so set back to the
629:                        // 'unknown' value
630:                        fontInfo.setSize(FontInfo.NULL_SIZE);
631:                    }
632:                }
633:
634:                String mystyle = getAttributeValue(elt,
635:                        NodeModel.FONTSTYLE_ATTRIBUTE);
636:                if (mystyle != null) {
637:                    if (mystyle.matches(sFontstylePatStr)) {
638:                        fontInfo.setStyle(mystyle);
639:                    } else {
640:                        // we don't know what font size is, so set back to the 'unknown' value
641:                        fontInfo.setStyleBits(FontInfo.NULL_STYLE);
642:                    }
643:                }
644:            }
645:
646:            /** Merge in font attribute info from an element into a FontInfo.
647:             *
648:             * @param elt the element to look for font attributes on
649:             * @param fontInfo  merge font attribute info into this struct
650:             */
651:            private static void mergeFontInfo(Element elt, FontInfo fontInfo) {
652:                mergeFontAttributes(elt, fontInfo);
653:
654:                // Static sized textfield optimization; need to cascade resizable
655:                String resizable = getAttributeValue(elt, "resizable");
656:                if ("true".equals(resizable)) {
657:                    fontInfo.resizable = FontInfo.FONTINFO_TRUE;
658:                } else if ("false".equals(resizable)) {
659:                    fontInfo.resizable = FontInfo.FONTINFO_FALSE;
660:                }
661:
662:                // Static sized textfield optimization; need to cascade multiline
663:                String multiline = getAttributeValue(elt, "multiline");
664:                if ("true".equals(multiline)) {
665:                    fontInfo.multiline = FontInfo.FONTINFO_TRUE;
666:                } else if ("false".equals(multiline)) {
667:                    fontInfo.multiline = FontInfo.FONTINFO_FALSE;
668:                }
669:            }
670:
671:            /** Pattern matcher for compile-time optimizations */
672:            static String sConstPatStr = "\\s*(\\d*)\\s*";
673:            static String sFontstylePatStr = "\\s*(bold italic|bold-italic|bold|plain|italic)\\s*";
674:            static String sFontSizePatStr = "\\s*\\d*\\s*";
675:            static String sFontNamePatStr = "\\s*[^${}]*\\s*";
676:            static String sConstraintPatStr = "^\\s*\\$(\\w*)\\{(.*)}\\s*";
677:            static final Pattern sConstraintPat;
678:
679:            static {
680:                // $once{parent +|- DDDDD}
681:                sConstraintPat = Pattern.compile(sConstraintPatStr);
682:            }
683:
684:            /** return true if element has an attribute named ATTRIBUTE in
685:             * it's attribute list, or has a child lzx element 
686:             * <attribute name="ATTRIBUTE"/>
687:             */
688:            protected static boolean hasAttribute(Element elt, String attrName) {
689:                if (elt.getAttributeValue(attrName) != null) {
690:                    return true;
691:                }
692:
693:                Iterator iter;
694:                for (iter = elt.getChildren().iterator(); iter.hasNext();) {
695:                    Element child = (Element) iter.next();
696:                    if ((child.getName().equals("attribute"))
697:                            && (child.getAttribute(attrName) != null)) {
698:                        return true;
699:                    }
700:                }
701:                return false;
702:            }
703:
704:            /** return value if element has an attribute named ATTRNAME in
705:             * it's attribute list, or has a child lzx element 
706:             * <attribute name="ATTRNAME" value="VAL"/>
707:             */
708:            protected static String getAttributeValue(Element elt,
709:                    String attrName) {
710:                String attrval = elt.getAttributeValue(attrName);
711:                if (attrval != null) {
712:                    return attrval;
713:                }
714:
715:                Iterator iter;
716:                for (iter = elt.getChildren().iterator(); iter.hasNext();) {
717:                    Element child = (Element) iter.next();
718:                    if ((child.getName().equals("attribute"))
719:                            && attrName.equals(child.getAttributeValue("name"))) {
720:                        return child.getAttributeValue("value");
721:                    }
722:                }
723:                return null;
724:            }
725:
726:            /**
727:             * Adds in text metrics for this element.
728:             *
729:             * @param env
730:             * @param elt
731:             * @param fontInfo font information for this element
732:             */
733:            private void compileTextMetrics(Element elt,
734:                    CompilationEnvironment env, FontInfo fontInfo) {
735:
736:                if (fontInfo.getName() != null) {
737:                    elt.setAttribute("font", fontInfo.getName());
738:                }
739:
740:                if (fontInfo.getSize() != -1) {
741:                    elt.setAttribute("fontsize", "" + fontInfo.getSize());
742:                }
743:
744:                if (fontInfo.getStyle() != null) {
745:                    elt.setAttribute("fontstyle", fontInfo.getStyle());
746:                }
747:
748:            }
749:
750:            static void setFontInfo(FontInfo info, Element elt) {
751:                String face = elt.getAttributeValue("face");
752:                String size = elt.getAttributeValue("size");
753:
754:                if (face != null) {
755:                    info.setName(face);
756:                }
757:                if (size != null) {
758:                    info.setSize(size);
759:                }
760:            }
761:        }
762:
763:        /**
764:         * @copyright Copyright 2001-2007 Laszlo Systems, Inc.  All Rights
765:         * Reserved.  Use is subject to license terms.
766:         */
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.