Source Code Cross Referenced for StringTemplateGroup.java in  » Template-Engine » stringtemplate » org » antlr » stringtemplate » 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 » Template Engine » stringtemplate » org.antlr.stringtemplate 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         [The "BSD licence"]
0003:         Copyright (c) 2003-2005 Terence Parr
0004:         All rights reserved.
0005:
0006:         Redistribution and use in source and binary forms, with or without
0007:         modification, are permitted provided that the following conditions
0008:         are met:
0009:         1. Redistributions of source code must retain the above copyright
0010:            notice, this list of conditions and the following disclaimer.
0011:         2. Redistributions in binary form must reproduce the above copyright
0012:            notice, this list of conditions and the following disclaimer in the
0013:            documentation and/or other materials provided with the distribution.
0014:         3. The name of the author may not be used to endorse or promote products
0015:            derived from this software without specific prior written permission.
0016:
0017:         THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
0018:         IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0019:         OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
0020:         IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
0021:         INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
0022:         NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0023:         DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0024:         THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0025:         (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
0026:         THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0027:         */
0028:        package org.antlr.stringtemplate;
0029:
0030:        import org.antlr.stringtemplate.language.DefaultTemplateLexer;
0031:        import org.antlr.stringtemplate.language.GroupLexer;
0032:        import org.antlr.stringtemplate.language.GroupParser;
0033:        import org.antlr.stringtemplate.language.AngleBracketTemplateLexer;
0034:
0035:        import java.util.*;
0036:        import java.io.*;
0037:        import java.lang.reflect.Constructor;
0038:
0039:        /** Manages a group of named mutually-referential StringTemplate objects.
0040:         *  Currently the templates must all live under a directory so that you
0041:         *  can reference them as foo.st or gutter/header.st.  To refresh a
0042:         *  group of templates, just create a new StringTemplateGroup and start
0043:         *  pulling templates from there.  Or, set the refresh interval.
0044:         *
0045:         *  Use getInstanceOf(template-name) to get a string template
0046:         *  to fill in.
0047:         *
0048:         *  The name of a template is the file name minus ".st" ending if present
0049:         *  unless you name it as you load it.
0050:         *
0051:         *  You can use the group file format also to define a group of templates
0052:         *  (this works better for code gen than for html page gen).  You must give
0053:         *  a Reader to the ctor for it to load the group; this is general and
0054:         *  distinguishes it from the ctors for the old-style "load template files
0055:         *  from the disk".
0056:         *
0057:         *  10/2005 I am adding a StringTemplateGroupLoader concept so people can define supergroups
0058:         *  within a group and have it load that group automatically.
0059:         */
0060:        public class StringTemplateGroup {
0061:            /** What is the group name */
0062:            protected String name;
0063:
0064:            /** Maps template name to StringTemplate object */
0065:            protected Map templates = new HashMap();
0066:
0067:            /** Maps map names to HashMap objects.  This is the list of maps
0068:             *  defined by the user like typeInitMap ::= ["int":"0"]
0069:             */
0070:            protected Map maps = new HashMap();
0071:
0072:            /** How to pull apart a template into chunks? */
0073:            protected Class templateLexerClass = null;
0074:
0075:            /** You can set the lexer once if you know all of your groups use the
0076:             *  same separator.  If the instance has templateLexerClass set
0077:             *  then it is used as an override.
0078:             */
0079:            protected static Class defaultTemplateLexerClass = DefaultTemplateLexer.class;
0080:
0081:            /** Under what directory should I look for templates?  If null,
0082:             *  to look into the CLASSPATH for templates as resources.
0083:             */
0084:            protected String rootDir = null;
0085:
0086:            /** Track all groups by name; maps name to StringTemplateGroup */
0087:            protected static Map nameToGroupMap = Collections
0088:                    .synchronizedMap(new HashMap());
0089:
0090:            /** Track all interfaces by name; maps name to StringTemplateGroupInterface */
0091:            protected static Map nameToInterfaceMap = Collections
0092:                    .synchronizedMap(new HashMap());
0093:
0094:            /** Are we derived from another group?  Templates not found in this group
0095:             *  will be searched for in the superGroup recursively.
0096:             */
0097:            protected StringTemplateGroup super Group = null;
0098:
0099:            /** Keep track of all interfaces implemented by this group. */
0100:            protected List interfaces = null;
0101:
0102:            /** When templates are files on the disk, the refresh interval is used
0103:             *  to know when to reload.  When a Reader is passed to the ctor,
0104:             *  it is a stream full of template definitions.  The former is used
0105:             *  for web development, but the latter is most likely used for source
0106:             *  code generation for translators; a refresh is unlikely.  Anyway,
0107:             *  I decided to track the source of templates in case such info is useful
0108:             *  in other situations than just turning off refresh interval.  I just
0109:             *  found another: don't ever look on the disk for individual templates
0110:             *  if this group is a group file...immediately look into any super group.
0111:             *  If not in the super group, report no such template.
0112:             */
0113:            protected boolean templatesDefinedInGroupFile = false;
0114:
0115:            /** Normally AutoIndentWriter is used to filter output, but user can
0116:             *  specify a new one.
0117:             */
0118:            protected Class userSpecifiedWriter;
0119:
0120:            protected boolean debugTemplateOutput = false;
0121:
0122:            /** The set of templates to ignore when dumping start/stop debug strings */
0123:            protected Set noDebugStartStopStrings;
0124:
0125:            /** A Map<Class,Object> that allows people to register a renderer for
0126:             *  a particular kind of object to be displayed for any template in this
0127:             *  group.  For example, a date should be formatted differently depending
0128:             *  on the locale.  You can set Date.class to an object whose
0129:             *  toString(Object) method properly formats a Date attribute
0130:             *  according to locale.  Or you can have a different renderer object
0131:             *  for each locale.
0132:             *
0133:             *  These render objects are used way down in the evaluation chain
0134:             *  right before an attribute's toString() method would normally be
0135:             *  called in ASTExpr.write().
0136:             *
0137:             *  Synchronized at creation time.
0138:             */
0139:            protected Map attributeRenderers;
0140:
0141:            /** Maps obj.prop to a value to avoid reflection costs; track one
0142:             *  set of all class.property -> Member mappings for all ST usage in VM.
0143:            protected static Map classPropertyCache = new HashMap();
0144:
0145:            public static class ClassPropCacheKey {
0146:            	Class c;
0147:            	String propertyName;
0148:            	public ClassPropCacheKey(Class c, String propertyName) {
0149:            		this.c=c;
0150:            		this.propertyName=propertyName;
0151:            	}
0152:
0153:            	public boolean equals(Object other) {
0154:            		ClassPropCacheKey otherKey = (ClassPropCacheKey)other;
0155:            		return c.equals(otherKey.c) &&
0156:            			propertyName.equals(otherKey.propertyName);
0157:            	}
0158:
0159:            	public int hashCode() {
0160:            		return c.hashCode()+propertyName.hashCode();
0161:            	}
0162:            }
0163:             */
0164:
0165:            /** If a group file indicates it derives from a supergroup, how do we
0166:             *  find it?  Shall we make it so the initial StringTemplateGroup file
0167:             *  can be loaded via this loader?  Right now we pass a Reader to ctor
0168:             *  to distinguish from the other variety.
0169:             */
0170:            private static StringTemplateGroupLoader groupLoader = null;
0171:
0172:            /** Where to report errors.  All string templates in this group
0173:             *  use this error handler by default.
0174:             */
0175:            protected StringTemplateErrorListener listener = DEFAULT_ERROR_LISTENER;
0176:
0177:            public static StringTemplateErrorListener DEFAULT_ERROR_LISTENER = new StringTemplateErrorListener() {
0178:                public void error(String s, Throwable e) {
0179:                    System.err.println(s);
0180:                    if (e != null) {
0181:                        e.printStackTrace(System.err);
0182:                    }
0183:                }
0184:
0185:                public void warning(String s) {
0186:                    System.out.println(s);
0187:                }
0188:            };
0189:
0190:            /** Used to indicate that the template doesn't exist.
0191:             *  We don't have to check disk for it; we know it's not there.
0192:             */
0193:            protected static final StringTemplate NOT_FOUND_ST = new StringTemplate();
0194:
0195:            /** How long before tossing out all templates in seconds. */
0196:            protected int refreshIntervalInSeconds = Integer.MAX_VALUE / 1000; // default: no refreshing from disk
0197:            protected long lastCheckedDisk = 0L;
0198:
0199:            /** How are the files encoded (ascii, UTF8, ...)?  You might want to read
0200:             *  UTF8 for example on an ascii machine.
0201:             */
0202:            String fileCharEncoding = System.getProperty("file.encoding");
0203:
0204:            /** Create a group manager for some templates, all of which are
0205:             *  at or below the indicated directory.
0206:             */
0207:            public StringTemplateGroup(String name, String rootDir) {
0208:                this (name, rootDir, DefaultTemplateLexer.class);
0209:            }
0210:
0211:            public StringTemplateGroup(String name, String rootDir, Class lexer) {
0212:                this .name = name;
0213:                this .rootDir = rootDir;
0214:                lastCheckedDisk = System.currentTimeMillis();
0215:                nameToGroupMap.put(name, this );
0216:                this .templateLexerClass = lexer;
0217:            }
0218:
0219:            /** Create a group manager for some templates, all of which are
0220:             *  loaded as resources via the classloader.
0221:             */
0222:            public StringTemplateGroup(String name) {
0223:                this (name, null, null);
0224:            }
0225:
0226:            public StringTemplateGroup(String name, Class lexer) {
0227:                this (name, null, lexer);
0228:            }
0229:
0230:            /** Create a group from the template group defined by a input stream.
0231:             *  The name is pulled from the file.  The format is
0232:             *
0233:             *  group name;
0234:             *
0235:             *  t1(args) ::= "..."
0236:             *  t2() ::= <<
0237:             *  >>
0238:             *  ...
0239:             */
0240:            public StringTemplateGroup(Reader r) {
0241:                this (r, AngleBracketTemplateLexer.class,
0242:                        DEFAULT_ERROR_LISTENER, (StringTemplateGroup) null);
0243:            }
0244:
0245:            public StringTemplateGroup(Reader r,
0246:                    StringTemplateErrorListener errors) {
0247:                this (r, AngleBracketTemplateLexer.class, errors,
0248:                        (StringTemplateGroup) null);
0249:            }
0250:
0251:            public StringTemplateGroup(Reader r, Class lexer) {
0252:                this (r, lexer, null, (StringTemplateGroup) null);
0253:            }
0254:
0255:            public StringTemplateGroup(Reader r, Class lexer,
0256:                    StringTemplateErrorListener errors) {
0257:                this (r, lexer, errors, (StringTemplateGroup) null);
0258:            }
0259:
0260:            /** Create a group from the input stream, but use a nondefault lexer
0261:             *  to break the templates up into chunks.  This is usefor changing
0262:             *  the delimiter from the default $...$ to <...>, for example.
0263:             */
0264:            public StringTemplateGroup(Reader r, Class lexer,
0265:                    StringTemplateErrorListener errors,
0266:                    StringTemplateGroup super Group) {
0267:                this .templatesDefinedInGroupFile = true;
0268:                // if no lexer specified, then assume <...> when loading from group file
0269:                if (lexer == null) {
0270:                    lexer = AngleBracketTemplateLexer.class;
0271:                }
0272:                this .templateLexerClass = lexer;
0273:                if (errors != null) { // always have to have a listener
0274:                    this .listener = errors;
0275:                }
0276:                setSuperGroup(super Group);
0277:                parseGroup(r);
0278:                nameToGroupMap.put(name, this );
0279:                verifyInterfaceImplementations();
0280:            }
0281:
0282:            /** What lexer class to use to break up templates.  If not lexer set
0283:             *  for this group, use static default.
0284:             */
0285:            public Class getTemplateLexerClass() {
0286:                if (templateLexerClass != null) {
0287:                    return templateLexerClass;
0288:                }
0289:                return defaultTemplateLexerClass;
0290:            }
0291:
0292:            public String getName() {
0293:                return name;
0294:            }
0295:
0296:            public void setName(String name) {
0297:                this .name = name;
0298:            }
0299:
0300:            public void setSuperGroup(StringTemplateGroup super Group) {
0301:                this .super Group = super Group;
0302:            }
0303:
0304:            /** Called by group parser when ": supergroupname" is found.
0305:             *  This method forces the supergroup's lexer to be same as lexer
0306:             *  for this (sub) group.
0307:             */
0308:            public void setSuperGroup(String super GroupName) {
0309:                StringTemplateGroup super Group = (StringTemplateGroup) nameToGroupMap
0310:                        .get(super GroupName);
0311:                if (super Group != null) { // we've seen before; just use it
0312:                    setSuperGroup(super Group);
0313:                    return;
0314:                }
0315:                // else load it using this group's template lexer
0316:                super Group = loadGroup(super GroupName, this .templateLexerClass,
0317:                        null);
0318:                if (super Group != null) {
0319:                    nameToGroupMap.put(super GroupName, super Group);
0320:                    setSuperGroup(super Group);
0321:                } else {
0322:                    if (groupLoader == null) {
0323:                        listener.error("no group loader registered", null);
0324:                    }
0325:                }
0326:            }
0327:
0328:            /** Just track the new interface; check later.  Allows dups, but no biggie. */
0329:            public void implementInterface(StringTemplateGroupInterface I) {
0330:                if (interfaces == null) {
0331:                    interfaces = new ArrayList();
0332:                }
0333:                interfaces.add(I);
0334:            }
0335:
0336:            /** Indicate that this group implements this interface; load if necessary
0337:             *  if not in the nameToInterfaceMap.
0338:             */
0339:            public void implementInterface(String interfaceName) {
0340:                StringTemplateGroupInterface I = (StringTemplateGroupInterface) nameToInterfaceMap
0341:                        .get(interfaceName);
0342:                if (I != null) { // we've seen before; just use it
0343:                    implementInterface(I);
0344:                    return;
0345:                }
0346:                I = loadInterface(interfaceName); // else load it
0347:                if (I != null) {
0348:                    nameToInterfaceMap.put(interfaceName, I);
0349:                    implementInterface(I);
0350:                } else {
0351:                    if (groupLoader == null) {
0352:                        listener.error("no group loader registered", null);
0353:                    }
0354:                }
0355:            }
0356:
0357:            public StringTemplateGroup getSuperGroup() {
0358:                return super Group;
0359:            }
0360:
0361:            /** Walk up group hierarchy and show top down to this group */
0362:            public String getGroupHierarchyStackString() {
0363:                List groupNames = new LinkedList();
0364:                StringTemplateGroup p = this ;
0365:                while (p != null) {
0366:                    groupNames.add(0, p.name);
0367:                    p = p.super Group;
0368:                }
0369:                return groupNames.toString().replaceAll(",", "");
0370:            }
0371:
0372:            public String getRootDir() {
0373:                return rootDir;
0374:            }
0375:
0376:            public void setRootDir(String rootDir) {
0377:                this .rootDir = rootDir;
0378:            }
0379:
0380:            /** StringTemplate object factory; each group can have its own. */
0381:            public StringTemplate createStringTemplate() {
0382:                StringTemplate st = new StringTemplate();
0383:                return st;
0384:            }
0385:
0386:            /** A support routine that gets an instance of name knowing which
0387:             *  ST encloses it for error messages.
0388:             */
0389:            protected StringTemplate getInstanceOf(
0390:                    StringTemplate enclosingInstance, String name)
0391:                    throws IllegalArgumentException {
0392:                //System.out.println("getInstanceOf("+getName()+"::"+name+")");
0393:                StringTemplate st = lookupTemplate(enclosingInstance, name);
0394:                if (st != null) {
0395:                    StringTemplate instanceST = st.getInstanceOf();
0396:                    return instanceST;
0397:                }
0398:                return null;
0399:            }
0400:
0401:            /** The primary means of getting an instance of a template from this
0402:             *  group.
0403:             */
0404:            public StringTemplate getInstanceOf(String name) {
0405:                return getInstanceOf(null, name);
0406:            }
0407:
0408:            /** The primary means of getting an instance of a template from this
0409:             *  group when you have a predefined set of attributes you want to
0410:             *  use.
0411:             */
0412:            public StringTemplate getInstanceOf(String name, Map attributes) {
0413:                StringTemplate st = getInstanceOf(name);
0414:                st.attributes = attributes;
0415:                return st;
0416:            }
0417:
0418:            public StringTemplate getEmbeddedInstanceOf(
0419:                    StringTemplate enclosingInstance, String name)
0420:                    throws IllegalArgumentException {
0421:                /*
0422:                System.out.println("surrounding group is "+
0423:                				   enclosingInstance.getGroup().getName()+
0424:                				   " with native group "+enclosingInstance.getNativeGroup().getName());
0425:                 */
0426:                StringTemplate st = null;
0427:                // TODO: seems like this should go into lookupTemplate
0428:                if (name.startsWith("super.")) {
0429:                    // for super.foo() refs, ensure that we look at the native
0430:                    // group for the embedded instance not the current evaluation
0431:                    // group (which is always pulled down to the original group
0432:                    // from which somebody did group.getInstanceOf("foo");
0433:                    st = enclosingInstance.getNativeGroup().getInstanceOf(
0434:                            enclosingInstance, name);
0435:                } else {
0436:                    st = getInstanceOf(enclosingInstance, name);
0437:                }
0438:                // make sure all embedded templates have the same group as enclosing
0439:                // so that polymorphic refs will start looking at the original group
0440:                st.setGroup(this );
0441:                st.setEnclosingInstance(enclosingInstance);
0442:                return st;
0443:            }
0444:
0445:            /** Get the template called 'name' from the group.  If not found,
0446:             *  attempt to load.  If not found on disk, then try the superGroup
0447:             *  if any.  If not even there, then record that it's
0448:             *  NOT_FOUND so we don't waste time looking again later.  If we've gone
0449:             *  past refresh interval, flush and look again.
0450:             *
0451:             *  If I find a template in a super group, copy an instance down here
0452:             */
0453:            public synchronized StringTemplate lookupTemplate(
0454:                    StringTemplate enclosingInstance, String name)
0455:                    throws IllegalArgumentException {
0456:                //System.out.println("look up "+getName()+"::"+name);
0457:                if (name.startsWith("super.")) {
0458:                    if (super Group != null) {
0459:                        int dot = name.indexOf('.');
0460:                        name = name.substring(dot + 1, name.length());
0461:                        StringTemplate super ScopeST = super Group
0462:                                .lookupTemplate(enclosingInstance, name);
0463:                        /*
0464:                        System.out.println("superScopeST is "+
0465:                        				   superScopeST.getGroup().getName()+"::"+name+
0466:                        				   " with native group "+superScopeST.getNativeGroup().getName());
0467:                         */
0468:                        return super ScopeST;
0469:                    }
0470:                    throw new IllegalArgumentException(getName()
0471:                            + " has no super group; invalid template: " + name);
0472:                }
0473:                checkRefreshInterval();
0474:                StringTemplate st = (StringTemplate) templates.get(name);
0475:                if (st == null) {
0476:                    // not there?  Attempt to load
0477:                    if (!templatesDefinedInGroupFile) {
0478:                        // only check the disk for individual template
0479:                        st = loadTemplateFromBeneathRootDirOrCLASSPATH(getFileNameFromTemplateName(name));
0480:                    }
0481:                    if (st == null && super Group != null) {
0482:                        // try to resolve in super group
0483:                        st = super Group.getInstanceOf(name);
0484:                        // make sure that when we inherit a template, that it's
0485:                        // group is reset; it's nativeGroup will remain where it was
0486:                        if (st != null) {
0487:                            st.setGroup(this );
0488:                        }
0489:                    }
0490:                    if (st != null) { // found in superGroup
0491:                        // insert into this group; refresh will allow super
0492:                        // to change it's def later or this group to add
0493:                        // an override.
0494:                        templates.put(name, st);
0495:                    } else {
0496:                        // not found; remember that this sucker doesn't exist
0497:                        templates.put(name, NOT_FOUND_ST);
0498:                        String context = "";
0499:                        if (enclosingInstance != null) {
0500:                            context = "; context is "
0501:                                    + enclosingInstance
0502:                                            .getEnclosingInstanceStackString();
0503:                        }
0504:                        String hier = getGroupHierarchyStackString();
0505:                        context += "; group hierarchy is " + hier;
0506:                        throw new IllegalArgumentException(
0507:                                "Can't find template "
0508:                                        + getFileNameFromTemplateName(name)
0509:                                        + context);
0510:                    }
0511:                } else if (st == NOT_FOUND_ST) {
0512:                    return null;
0513:                }
0514:                //System.out.println("lookup found "+st.getGroup().getName()+"::"+st.getName());
0515:                return st;
0516:            }
0517:
0518:            public StringTemplate lookupTemplate(String name) {
0519:                return lookupTemplate(null, name);
0520:            }
0521:
0522:            protected void checkRefreshInterval() {
0523:                if (templatesDefinedInGroupFile) {
0524:                    return;
0525:                }
0526:                boolean timeToFlush = refreshIntervalInSeconds == 0
0527:                        || (System.currentTimeMillis() - lastCheckedDisk) >= refreshIntervalInSeconds * 1000;
0528:                if (timeToFlush) {
0529:                    // throw away all pre-compiled references
0530:                    templates.clear();
0531:                    lastCheckedDisk = System.currentTimeMillis();
0532:                }
0533:            }
0534:
0535:            protected StringTemplate loadTemplate(String name, BufferedReader r)
0536:                    throws IOException {
0537:                String line;
0538:                String nl = System.getProperty("line.separator");
0539:                StringBuffer buf = new StringBuffer(300);
0540:                while ((line = r.readLine()) != null) {
0541:                    buf.append(line);
0542:                    buf.append(nl);
0543:                }
0544:                // strip newlines etc.. from front/back since filesystem
0545:                // may add newlines etc...
0546:                String pattern = buf.toString().trim();
0547:                if (pattern.length() == 0) {
0548:                    error("no text in template '" + name + "'");
0549:                    return null;
0550:                }
0551:                return defineTemplate(name, pattern);
0552:            }
0553:
0554:            /** Load a template whose name is derived from the template filename.
0555:             *  If there is no root directory, try to load the template from
0556:             *  the classpath.  If there is a rootDir, try to load the file
0557:             *  from there.
0558:             */
0559:            protected StringTemplate loadTemplateFromBeneathRootDirOrCLASSPATH(
0560:                    String fileName) {
0561:                StringTemplate template = null;
0562:                String name = getTemplateNameFromFileName(fileName);
0563:                // if no rootDir, try to load as a resource in CLASSPATH
0564:                if (rootDir == null) {
0565:                    ClassLoader cl = Thread.currentThread()
0566:                            .getContextClassLoader();
0567:                    InputStream is = cl.getResourceAsStream(fileName);
0568:                    if (is == null) {
0569:                        cl = this .getClass().getClassLoader();
0570:                        is = cl.getResourceAsStream(fileName);
0571:                    }
0572:                    if (is == null) {
0573:                        return null;
0574:                    }
0575:                    BufferedReader br = null;
0576:                    try {
0577:                        br = new BufferedReader(getInputStreamReader(is));
0578:                        template = loadTemplate(name, br);
0579:                    } catch (IOException ioe) {
0580:                        error("Problem reading template file: " + fileName, ioe);
0581:                    } finally {
0582:                        if (br != null) {
0583:                            try {
0584:                                br.close();
0585:                            } catch (IOException ioe2) {
0586:                                error(
0587:                                        "Cannot close template file: "
0588:                                                + fileName, ioe2);
0589:                            }
0590:                        }
0591:                    }
0592:                    return template;
0593:                }
0594:                // load via rootDir
0595:                template = loadTemplate(name, rootDir + "/" + fileName);
0596:                return template;
0597:            }
0598:
0599:            /** (public so that people can override behavior; not a general
0600:             *  purpose method)
0601:             */
0602:            public String getFileNameFromTemplateName(String templateName) {
0603:                return templateName + ".st";
0604:            }
0605:
0606:            /** Convert a filename relativePath/name.st to relativePath/name.
0607:             *  (public so that people can override behavior; not a general
0608:             *  purpose method)
0609:             */
0610:            public String getTemplateNameFromFileName(String fileName) {
0611:                String name = fileName;
0612:                int suffix = name.lastIndexOf(".st");
0613:                if (suffix >= 0) {
0614:                    name = name.substring(0, suffix);
0615:                }
0616:                return name;
0617:            }
0618:
0619:            protected StringTemplate loadTemplate(String name, String fileName) {
0620:                BufferedReader br = null;
0621:                StringTemplate template = null;
0622:                try {
0623:                    InputStream fin = new FileInputStream(fileName);
0624:                    InputStreamReader isr = getInputStreamReader(fin);
0625:                    br = new BufferedReader(isr);
0626:                    template = loadTemplate(name, br);
0627:                    br.close();
0628:                    br = null;
0629:                } catch (IOException ioe) {
0630:                    if (br != null) {
0631:                        try {
0632:                            br.close();
0633:                        } catch (IOException ioe2) {
0634:                            error("Cannot close template file: " + fileName);
0635:                        }
0636:                    }
0637:                }
0638:                return template;
0639:            }
0640:
0641:            protected InputStreamReader getInputStreamReader(InputStream in) {
0642:                InputStreamReader isr = null;
0643:                try {
0644:                    isr = new InputStreamReader(in, fileCharEncoding);
0645:                } catch (UnsupportedEncodingException uee) {
0646:                    error("Invalid file character encoding: "
0647:                            + fileCharEncoding);
0648:                }
0649:                return isr;
0650:            }
0651:
0652:            public String getFileCharEncoding() {
0653:                return fileCharEncoding;
0654:            }
0655:
0656:            public void setFileCharEncoding(String fileCharEncoding) {
0657:                this .fileCharEncoding = fileCharEncoding;
0658:            }
0659:
0660:            /** Define an examplar template; precompiled and stored
0661:             *  with no attributes.  Remove any previous definition.
0662:             */
0663:            public synchronized StringTemplate defineTemplate(String name,
0664:                    String template) {
0665:                //System.out.println("defineTemplate "+getName()+"::"+name);
0666:                if (name != null && name.indexOf('.') >= 0) {
0667:                    throw new IllegalArgumentException(
0668:                            "cannot have '.' in template names");
0669:                }
0670:                StringTemplate st = createStringTemplate();
0671:                st.setName(name);
0672:                st.setGroup(this );
0673:                st.setNativeGroup(this );
0674:                st.setTemplate(template);
0675:                st.setErrorListener(listener);
0676:                templates.put(name, st);
0677:                return st;
0678:            }
0679:
0680:            /** Track all references to regions <@foo>...<@end> or <@foo()>.  */
0681:            public StringTemplate defineRegionTemplate(
0682:                    String enclosingTemplateName, String regionName,
0683:                    String template, int type) {
0684:                String mangledName = getMangledRegionName(
0685:                        enclosingTemplateName, regionName);
0686:                StringTemplate regionST = defineTemplate(mangledName, template);
0687:                regionST.setIsRegion(true);
0688:                regionST.setRegionDefType(type);
0689:                return regionST;
0690:            }
0691:
0692:            /** Track all references to regions <@foo>...<@end> or <@foo()>.  */
0693:            public StringTemplate defineRegionTemplate(
0694:                    StringTemplate enclosingTemplate, String regionName,
0695:                    String template, int type) {
0696:                StringTemplate regionST = defineRegionTemplate(
0697:                        enclosingTemplate.getOutermostName(), regionName,
0698:                        template, type);
0699:                enclosingTemplate.getOutermostEnclosingInstance()
0700:                        .addRegionName(regionName);
0701:                return regionST;
0702:            }
0703:
0704:            /** Track all references to regions <@foo()>.  We automatically
0705:             *  define as
0706:             *
0707:             *     @enclosingtemplate.foo() ::= ""
0708:             *
0709:             *  You cannot set these manually in the same group; you have to subgroup
0710:             *  to override.
0711:             */
0712:            public StringTemplate defineImplicitRegionTemplate(
0713:                    StringTemplate enclosingTemplate, String name) {
0714:                return defineRegionTemplate(enclosingTemplate, name, "",
0715:                        StringTemplate.REGION_IMPLICIT);
0716:
0717:            }
0718:
0719:            /** The "foo" of t() ::= "<@foo()>" is mangled to "region#t#foo" */
0720:            public String getMangledRegionName(String enclosingTemplateName,
0721:                    String name) {
0722:                return "region__" + enclosingTemplateName + "__" + name;
0723:            }
0724:
0725:            /** Return "t" from "region__t__foo" */
0726:            public String getUnMangledTemplateName(String mangledName) {
0727:                return mangledName.substring("region__".length(), mangledName
0728:                        .lastIndexOf("__"));
0729:            }
0730:
0731:            /** Make name and alias for target.  Replace any previous def of name */
0732:            public synchronized StringTemplate defineTemplateAlias(String name,
0733:                    String target) {
0734:                StringTemplate targetST = getTemplateDefinition(target);
0735:                if (targetST == null) {
0736:                    error("cannot alias " + name + " to undefined template: "
0737:                            + target);
0738:                    return null;
0739:                }
0740:                templates.put(name, targetST);
0741:                return targetST;
0742:            }
0743:
0744:            public synchronized boolean isDefinedInThisGroup(String name) {
0745:                StringTemplate st = (StringTemplate) templates.get(name);
0746:                if (st != null) {
0747:                    if (st.isRegion()) {
0748:                        // don't allow redef of @t.r() ::= "..." or <@r>...<@end>
0749:                        if (st.getRegionDefType() == StringTemplate.REGION_IMPLICIT) {
0750:                            return false;
0751:                        }
0752:                    }
0753:                    return true;
0754:                }
0755:                return false;
0756:            }
0757:
0758:            /** Get the ST for 'name' in this group only */
0759:            public synchronized StringTemplate getTemplateDefinition(String name) {
0760:                return (StringTemplate) templates.get(name);
0761:            }
0762:
0763:            /** Is there *any* definition for template 'name' in this template
0764:             *  or above it in the group hierarchy?
0765:             */
0766:            public boolean isDefined(String name) {
0767:                try {
0768:                    return lookupTemplate(name) != null;
0769:                } catch (IllegalArgumentException iae) {
0770:                    return false;
0771:                }
0772:            }
0773:
0774:            protected void parseGroup(Reader r) {
0775:                try {
0776:                    GroupLexer lexer = new GroupLexer(r);
0777:                    GroupParser parser = new GroupParser(lexer);
0778:                    parser.group(this );
0779:                    //System.out.println("read group\n"+this.toString());
0780:                } catch (Exception e) {
0781:                    String name = "<unknown>";
0782:                    if (getName() != null) {
0783:                        name = getName();
0784:                    }
0785:                    error("problem parsing group " + name + ": " + e, e);
0786:                }
0787:            }
0788:
0789:            /** verify that this group satisfies its interfaces */
0790:            protected void verifyInterfaceImplementations() {
0791:                for (int i = 0; interfaces != null && i < interfaces.size(); i++) {
0792:                    StringTemplateGroupInterface I = (StringTemplateGroupInterface) interfaces
0793:                            .get(i);
0794:                    List missing = I.getMissingTemplates(this );
0795:                    List mismatched = I.getMismatchedTemplates(this );
0796:                    if (missing != null) {
0797:                        error("group " + getName()
0798:                                + " does not satisfy interface " + I.getName()
0799:                                + ": missing templates " + missing);
0800:                    }
0801:                    if (mismatched != null) {
0802:                        error("group " + getName()
0803:                                + " does not satisfy interface " + I.getName()
0804:                                + ": mismatched arguments on these templates "
0805:                                + mismatched);
0806:                    }
0807:                }
0808:            }
0809:
0810:            public int getRefreshInterval() {
0811:                return refreshIntervalInSeconds;
0812:            }
0813:
0814:            /** How often to refresh all templates from disk.  This is a crude
0815:             *  mechanism at the moment--just tosses everything out at this
0816:             *  frequency.  Set interval to 0 to refresh constantly (no caching).
0817:             *  Set interval to a huge number like MAX_INT to have no refreshing
0818:             *  at all (DEFAULT); it will cache stuff.
0819:             */
0820:            public void setRefreshInterval(int refreshInterval) {
0821:                this .refreshIntervalInSeconds = refreshInterval;
0822:            }
0823:
0824:            public void setErrorListener(StringTemplateErrorListener listener) {
0825:                this .listener = listener;
0826:            }
0827:
0828:            public StringTemplateErrorListener getErrorListener() {
0829:                return listener;
0830:            }
0831:
0832:            /** Specify a StringTemplateWriter implementing class to use for
0833:             *  filtering output
0834:             */
0835:            public void setStringTemplateWriter(Class c) {
0836:                userSpecifiedWriter = c;
0837:            }
0838:
0839:            /** return an instance of a StringTemplateWriter that spits output to w.
0840:             *  If a writer is specified, use it instead of the default.
0841:             */
0842:            public StringTemplateWriter getStringTemplateWriter(Writer w) {
0843:                StringTemplateWriter stw = null;
0844:                if (userSpecifiedWriter != null) {
0845:                    try {
0846:                        Constructor ctor = userSpecifiedWriter
0847:                                .getConstructor(new Class[] { Writer.class });
0848:                        stw = (StringTemplateWriter) ctor
0849:                                .newInstance(new Object[] { w });
0850:                    } catch (Exception e) {
0851:                        error("problems getting StringTemplateWriter", e);
0852:                    }
0853:                }
0854:                if (stw == null) {
0855:                    stw = new AutoIndentWriter(w);
0856:                }
0857:                return stw;
0858:            }
0859:
0860:            /** Specify a complete map of what object classes should map to which
0861:             *  renderer objects for every template in this group (that doesn't
0862:             *  override it per template).
0863:             */
0864:            public void setAttributeRenderers(Map renderers) {
0865:                this .attributeRenderers = renderers;
0866:            }
0867:
0868:            /** Register a renderer for all objects of a particular type for all
0869:             *  templates in this group.
0870:             */
0871:            public void registerRenderer(Class attributeClassType,
0872:                    Object renderer) {
0873:                if (attributeRenderers == null) {
0874:                    attributeRenderers = Collections
0875:                            .synchronizedMap(new HashMap());
0876:                }
0877:                attributeRenderers.put(attributeClassType, renderer);
0878:            }
0879:
0880:            /** What renderer is registered for this attributeClassType for
0881:             *  this group?  If not found, as superGroup if it has one.
0882:             */
0883:            public AttributeRenderer getAttributeRenderer(
0884:                    Class attributeClassType) {
0885:                if (attributeRenderers == null) {
0886:                    if (super Group == null) {
0887:                        return null; // no renderers and no parent?  Stop.
0888:                    }
0889:                    // no renderers; consult super group
0890:                    return super Group.getAttributeRenderer(attributeClassType);
0891:                }
0892:
0893:                AttributeRenderer renderer = (AttributeRenderer) attributeRenderers
0894:                        .get(attributeClassType);
0895:                if (renderer == null) {
0896:                    if (super Group != null) {
0897:                        // no renderer registered for this class, check super group
0898:                        renderer = super Group
0899:                                .getAttributeRenderer(attributeClassType);
0900:                    }
0901:                }
0902:                return renderer;
0903:            }
0904:
0905:            /*
0906:            public void cacheClassProperty(Class c, String propertyName, Member member) {
0907:            	Object key = new ClassPropCacheKey(c,propertyName);
0908:            	classPropertyCache.put(key,member);
0909:            }
0910:
0911:            public Member getCachedClassProperty(Class c, String propertyName) {
0912:            	Object key = new ClassPropCacheKey(c,propertyName);
0913:            	return (Member)classPropertyCache.get(key);
0914:            }
0915:             */
0916:
0917:            public Map getMap(String name) {
0918:                if (maps == null) {
0919:                    if (super Group == null) {
0920:                        return null;
0921:                    }
0922:                    return super Group.getMap(name);
0923:                }
0924:                Map m = (Map) maps.get(name);
0925:                if (m == null && super Group != null) {
0926:                    m = super Group.getMap(name);
0927:                }
0928:                return m;
0929:            }
0930:
0931:            /** Define a map for this group; not thread safe...do not keep adding
0932:             *  these while you reference them.
0933:             */
0934:            public void defineMap(String name, Map mapping) {
0935:                maps.put(name, mapping);
0936:            }
0937:
0938:            public static void registerDefaultLexer(Class lexerClass) {
0939:                defaultTemplateLexerClass = lexerClass;
0940:            }
0941:
0942:            public static void registerGroupLoader(
0943:                    StringTemplateGroupLoader loader) {
0944:                groupLoader = loader;
0945:            }
0946:
0947:            public static StringTemplateGroup loadGroup(String name) {
0948:                return loadGroup(name, null, null);
0949:            }
0950:
0951:            public static StringTemplateGroup loadGroup(String name,
0952:                    StringTemplateGroup super Group) {
0953:                return loadGroup(name, null, super Group);
0954:            }
0955:
0956:            public static StringTemplateGroup loadGroup(String name,
0957:                    Class lexer, StringTemplateGroup super Group) {
0958:                if (groupLoader != null) {
0959:                    return groupLoader.loadGroup(name, lexer, super Group);
0960:                }
0961:                return null;
0962:            }
0963:
0964:            public static StringTemplateGroupInterface loadInterface(String name) {
0965:                if (groupLoader != null) {
0966:                    return groupLoader.loadInterface(name);
0967:                }
0968:                return null;
0969:            }
0970:
0971:            public void error(String msg) {
0972:                error(msg, null);
0973:            }
0974:
0975:            public void error(String msg, Exception e) {
0976:                if (listener != null) {
0977:                    listener.error(msg, e);
0978:                } else {
0979:                    System.err.println("StringTemplate: " + msg);
0980:                    if (e != null) {
0981:                        e.printStackTrace();
0982:                    }
0983:                }
0984:            }
0985:
0986:            public synchronized Set getTemplateNames() {
0987:                return templates.keySet();
0988:            }
0989:
0990:            /** Indicate whether ST should emit <templatename>...</templatename>
0991:             *  strings for debugging around output for templates from this group.
0992:             */
0993:            public void emitDebugStartStopStrings(boolean emit) {
0994:                this .debugTemplateOutput = emit;
0995:            }
0996:
0997:            public void doNotEmitDebugStringsForTemplate(String templateName) {
0998:                if (noDebugStartStopStrings == null) {
0999:                    noDebugStartStopStrings = new HashSet();
1000:                }
1001:                noDebugStartStopStrings.add(templateName);
1002:            }
1003:
1004:            public void emitTemplateStartDebugString(StringTemplate st,
1005:                    StringTemplateWriter out) throws IOException {
1006:                if (noDebugStartStopStrings == null
1007:                        || !noDebugStartStopStrings.contains(st.getName())) {
1008:                    out.write("<" + st.getName() + ">");
1009:                }
1010:            }
1011:
1012:            public void emitTemplateStopDebugString(StringTemplate st,
1013:                    StringTemplateWriter out) throws IOException {
1014:                if (noDebugStartStopStrings == null
1015:                        || !noDebugStartStopStrings.contains(st.getName())) {
1016:                    out.write("</" + st.getName() + ">");
1017:                }
1018:            }
1019:
1020:            public String toString() {
1021:                return toString(true);
1022:            }
1023:
1024:            public String toString(boolean showTemplatePatterns) {
1025:                StringBuffer buf = new StringBuffer();
1026:                Set templateNameSet = templates.keySet();
1027:                List sortedNames = new ArrayList(templateNameSet);
1028:                Collections.sort(sortedNames);
1029:                Iterator iter = sortedNames.iterator();
1030:                buf.append("group " + getName() + ";\n");
1031:                StringTemplate formalArgs = new StringTemplate(
1032:                        "$args;separator=\",\"$");
1033:                while (iter.hasNext()) {
1034:                    String tname = (String) iter.next();
1035:                    StringTemplate st = (StringTemplate) templates.get(tname);
1036:                    if (st != NOT_FOUND_ST) {
1037:                        formalArgs = formalArgs.getInstanceOf();
1038:                        formalArgs
1039:                                .setAttribute("args", st.getFormalArguments());
1040:                        buf.append(tname + "(" + formalArgs + ")");
1041:                        if (showTemplatePatterns) {
1042:                            buf.append(" ::= <<");
1043:                            buf.append(st.getTemplate());
1044:                            buf.append(">>\n");
1045:                        } else {
1046:                            buf.append('\n');
1047:                        }
1048:                    }
1049:                }
1050:                return buf.toString();
1051:            }
1052:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.