Source Code Cross Referenced for Template.java in  » Template-Engine » freemarker-2.3.10 » freemarker » template » 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 » freemarker 2.3.10 » freemarker.template 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright (c) 2003 The Visigoth Software Society. All rights
003:         * reserved.
004:         *
005:         * Redistribution and use in source and binary forms, with or without
006:         * modification, are permitted provided that the following conditions
007:         * are met:
008:         *
009:         * 1. Redistributions of source code must retain the above copyright
010:         *    notice, this list of conditions and the following disclaimer.
011:         *
012:         * 2. Redistributions in binary form must reproduce the above copyright
013:         *    notice, this list of conditions and the following disclaimer in
014:         *    the documentation and/or other materials provided with the
015:         *    distribution.
016:         *
017:         * 3. The end-user documentation included with the redistribution, if
018:         *    any, must include the following acknowledgement:
019:         *       "This product includes software developed by the
020:         *        Visigoth Software Society (http://www.visigoths.org/)."
021:         *    Alternately, this acknowledgement may appear in the software itself,
022:         *    if and wherever such third-party acknowledgements normally appear.
023:         *
024:         * 4. Neither the name "FreeMarker", "Visigoth", nor any of the names of the
025:         *    project contributors may be used to endorse or promote products derived
026:         *    from this software without prior written permission. For written
027:         *    permission, please contact visigoths@visigoths.org.
028:         *
029:         * 5. Products derived from this software may not be called "FreeMarker" or "Visigoth"
030:         *    nor may "FreeMarker" or "Visigoth" appear in their names
031:         *    without prior written permission of the Visigoth Software Society.
032:         *
033:         * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
034:         * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
035:         * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
036:         * DISCLAIMED.  IN NO EVENT SHALL THE VISIGOTH SOFTWARE SOCIETY OR
037:         * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
038:         * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
039:         * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
040:         * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
041:         * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
042:         * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
043:         * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
044:         * SUCH DAMAGE.
045:         * ====================================================================
046:         *
047:         * This software consists of voluntary contributions made by many
048:         * individuals on behalf of the Visigoth Software Society. For more
049:         * information on the Visigoth Software Society, please see
050:         * http://www.visigoths.org/
051:         */
052:
053:        package freemarker.template;
054:
055:        import java.io.*;
056:        import java.util.*;
057:        import javax.swing.tree.TreePath;
058:        import freemarker.core.*;
059:
060:        import freemarker.debug.impl.DebuggerService;
061:
062:        /**
063:         * <p>A core FreeMarker API that represents a compiled template.
064:         * Typically, you will use a {@link Configuration} object to instantiate a template.
065:         *
066:         * <PRE>
067:         Configuration cfg = new Configuration();
068:         ...
069:         Template myTemplate = cfg.getTemplate("myTemplate.html");
070:         </PRE>
071:         *
072:         * <P>However, you can also construct a template directly by passing in to
073:         * the appropriate constructor a java.io.Reader instance that is set to
074:         * read the raw template text. The compiled template is
075:         * stored in an an efficient data structure for later use.
076:         *
077:         * <p>To render the template, i.e. to merge it with a data model, and
078:         * thus produce "cooked" output, call the <tt>process</tt> method.
079:         *
080:         * <p>Any error messages from exceptions thrown during compilation will be
081:         * included in the output stream and thrown back to the calling code.
082:         * To change this behavior, you can install custom exception handlers using
083:         * {@link Configurable#setTemplateExceptionHandler(TemplateExceptionHandler)} on
084:         * a Configuration object (for all templates belonging to a configuration) or on
085:         * a Template object (for a single template).
086:         * 
087:         * <p>It's not legal to modify the values of FreeMarker settings: a) while the
088:         * template is executing; b) if the template object is already accessible from
089:         * multiple threads.
090:         * 
091:         * @version $Id: Template.java,v 1.216.2.3 2006/03/10 17:49:02 revusky Exp $
092:         */
093:
094:        public class Template extends Configurable {
095:            public static final String DEFAULT_NAMESPACE_PREFIX = "D";
096:            public static final String NO_NS_PREFIX = "N";
097:
098:            private Map macros = new HashMap();
099:            private List imports = new Vector();
100:            private TemplateElement rootElement;
101:            private String encoding, defaultNS;
102:            private final String name;
103:            private final ArrayList lines = new ArrayList();
104:            private Map prefixToNamespaceURILookup = new HashMap();
105:            private Map namespaceURIToPrefixLookup = new HashMap();
106:
107:            /**
108:             * A prime constructor to which all other constructors should
109:             * delegate directly or indirectly.
110:             */
111:            private Template(String name, Configuration cfg) {
112:                super (cfg != null ? cfg : Configuration
113:                        .getDefaultConfiguration());
114:                this .name = name;
115:            }
116:
117:            /**
118:             * Constructs a template from a character stream.
119:             *
120:             * @param name the path of the template file relative to the directory what you use to store
121:             *        the templates. See {@link #getName} for more details.
122:             * @param reader the character stream to read from. It will always be closed (Reader.close()).
123:             * @param cfg the Configuration object that this Template is associated with.
124:             *        If this is null, the "default" {@link Configuration} object is used,
125:             *        which is highly discouraged, because it can easily lead to
126:             *        erroneous, unpredictable behaviour.
127:             *        (See more {@link Configuration#getDefaultConfiguration() here...})
128:             * @param encoding This is the encoding that we are supposed to be using. If this is
129:             * non-null (It's not actually necessary because we are using a Reader) then it is
130:             * checked against the encoding specified in the FTL header -- assuming that is specified,
131:             * and if they don't match a WrongEncodingException is thrown.
132:             */
133:            public Template(String name, Reader reader, Configuration cfg,
134:                    String encoding) throws IOException {
135:                this (name, cfg);
136:                this .encoding = encoding;
137:
138:                if (!(reader instanceof  BufferedReader)) {
139:                    reader = new BufferedReader(reader, 0x1000);
140:                }
141:                LineTableBuilder ltb = new LineTableBuilder(reader);
142:                try {
143:                    FMParser parser = new FMParser(this , ltb,
144:                            getConfiguration().getStrictSyntaxMode(),
145:                            getConfiguration().getWhitespaceStripping(),
146:                            getConfiguration().getTagSyntax());
147:                    this .rootElement = parser.Root();
148:                } catch (TokenMgrError exc) {
149:                    throw new ParseException("Token manager error: " + exc, 0,
150:                            0);
151:                } finally {
152:                    ltb.close();
153:                }
154:                DebuggerService.registerTemplate(this );
155:                namespaceURIToPrefixLookup = Collections
156:                        .unmodifiableMap(namespaceURIToPrefixLookup);
157:                prefixToNamespaceURILookup = Collections
158:                        .unmodifiableMap(prefixToNamespaceURILookup);
159:            }
160:
161:            /**
162:             * This is equivalent to Template(name, reader, cfg, null)
163:             */
164:
165:            public Template(String name, Reader reader, Configuration cfg)
166:                    throws IOException {
167:                this (name, reader, cfg, null);
168:            }
169:
170:            /**
171:             * Constructs a template from a character stream.
172:             *
173:             * This is the same as the 3 parameter version when you pass null
174:             * as the cfg parameter.
175:             * 
176:             * @deprecated This constructor uses the "default" {@link Configuration}
177:             * instance, which can easily lead to erroneous, unpredictable behaviour.
178:             * See more {@link Configuration#getDefaultConfiguration() here...}.
179:             */
180:            public Template(String name, Reader reader) throws IOException {
181:                this (name, reader, null);
182:            }
183:
184:            /**
185:             * This constructor is only used internally.
186:             */
187:            Template(String name, TemplateElement root, Configuration config) {
188:                this (name, config);
189:                this .rootElement = root;
190:                DebuggerService.registerTemplate(this );
191:            }
192:
193:            /**
194:             * Returns a trivial template, one that is just a single block of
195:             * plain text, no dynamic content. (Used by the cache module to create
196:             * unparsed templates.)
197:             * @param name the path of the template file relative to the directory what you use to store
198:             *        the templates. See {@link #getName} for more details.
199:             * @param content the block of text that this template represents
200:             * @param config the configuration to which this template belongs
201:             */
202:            static public Template getPlainTextTemplate(String name,
203:                    String content, Configuration config) {
204:                Template template = new Template(name, config);
205:                TextBlock block = new TextBlock(content);
206:                template.rootElement = block;
207:                DebuggerService.registerTemplate(template);
208:                return template;
209:            }
210:
211:            /**
212:             * Processes the template, using data from the map, and outputs
213:             * the resulting text to the supplied <tt>Writer</tt> The elements of the
214:             * map are converted to template models using the default object wrapper
215:             * returned by the {@link Configuration#getObjectWrapper() getObjectWrapper()}
216:             * method of the <tt>Configuration</tt>.
217:             * @param rootMap the root node of the data model.  If null, an
218:             * empty data model is used. Can be any object that the effective object
219:             * wrapper can turn into a <tt>TemplateHashModel</tt>. Basically, simple and
220:             * beans wrapper can turn <tt>java.util.Map</tt> objects into hashes
221:             * and the Jython wrapper can turn both a <tt>PyDictionary</tt> as well as
222:             * any object that implements <tt>__getitem__</tt> into a template hash.
223:             * Naturally, you can pass any object directly implementing
224:             * <tt>TemplateHashModel</tt> as well.
225:             * @param out a <tt>Writer</tt> to output the text to.
226:             * @throws TemplateException if an exception occurs during template processing
227:             * @throws IOException if an I/O exception occurs during writing to the writer.
228:             */
229:            public void process(Object rootMap, Writer out)
230:                    throws TemplateException, IOException {
231:                createProcessingEnvironment(rootMap, out, null).process();
232:            }
233:
234:            /**
235:             * Processes the template, using data from the root map object, and outputs
236:             * the resulting text to the supplied writer, using the supplied
237:             * object wrapper to convert map elements to template models.
238:             * @param rootMap the root node of the data model.  If null, an
239:             * empty data model is used. Can be any object that the effective object
240:             * wrapper can turn into a <tt>TemplateHashModel</tt> Basically, simple and
241:             * beans wrapper can turn <tt>java.util.Map</tt> objects into hashes
242:             * and the Jython wrapper can turn both a <tt>PyDictionary</tt> as well as any
243:             * object that implements <tt>__getitem__</tt> into a template hash.
244:             * Naturally, you can pass any object directly implementing
245:             * <tt>TemplateHashModel</tt> as well.
246:             * @param wrapper The object wrapper to use to wrap objects into
247:             * {@link TemplateModel} instances. If null, the default wrapper retrieved
248:             * by {@link Configurable#getObjectWrapper()} is used.
249:             * @param out the writer to output the text to.
250:             * @param rootNode The root node for recursive processing, this may be null.
251:             * 
252:             * @throws TemplateException if an exception occurs during template processing
253:             * @throws IOException if an I/O exception occurs during writing to the writer.
254:             */
255:            public void process(Object rootMap, Writer out,
256:                    ObjectWrapper wrapper, TemplateNodeModel rootNode)
257:                    throws TemplateException, IOException {
258:                Environment env = createProcessingEnvironment(rootMap, out,
259:                        wrapper);
260:                if (rootNode != null) {
261:                    env.setCurrentVisitorNode(rootNode);
262:                }
263:                env.process();
264:            }
265:
266:            /**
267:             * Processes the template, using data from the root map object, and outputs
268:             * the resulting text to the supplied writer, using the supplied
269:             * object wrapper to convert map elements to template models.
270:             * @param rootMap the root node of the data model.  If null, an
271:             * empty data model is used. Can be any object that the effective object
272:             * wrapper can turn into a <tt>TemplateHashModel</tt> Basically, simple and
273:             * beans wrapper can turn <tt>java.util.Map</tt> objects into hashes
274:             * and the Jython wrapper can turn both a <tt>PyDictionary</tt> as well as any
275:             * object that implements <tt>__getitem__</tt> into a template hash.
276:             * Naturally, you can pass any object directly implementing
277:             * <tt>TemplateHashModel</tt> as well.
278:             * @param wrapper The object wrapper to use to wrap objects into
279:             * {@link TemplateModel} instances. If null, the default wrapper retrieved
280:             * by {@link Configurable#getObjectWrapper()} is used.
281:             * @param out the writer to output the text to.
282:             * 
283:             * @throws TemplateException if an exception occurs during template processing
284:             * @throws IOException if an I/O exception occurs during writing to the writer.
285:             */
286:            public void process(Object rootMap, Writer out,
287:                    ObjectWrapper wrapper) throws TemplateException,
288:                    IOException {
289:                process(rootMap, out, wrapper, null);
290:            }
291:
292:            /**
293:             * Creates a {@link freemarker.core.Environment Environment} object,
294:             * using this template, the data model provided as the root map object, and
295:             * the supplied object wrapper to convert map elements to template models.
296:             * You can then call Environment.process() on the returned environment
297:             * to set off the actual rendering.
298:             * Use this method if you want to do some special initialization on the environment
299:             * before template processing, or if you want to read the environment after template
300:             * processing.
301:             *
302:             * <p>Example:
303:             *
304:             * <p>This:
305:             * <pre>
306:             * Environment env = myTemplate.createProcessingEnvironment(root, out, null);
307:             * env.process();
308:             * </pre>
309:             * is equivalent with this:
310:             * <pre>
311:             * myTemplate.process(root, out);
312:             * </pre>
313:             * But with <tt>createProcessingEnvironment</tt>, you can manipulate the environment
314:             * before and after the processing:
315:             * <pre>
316:             * Environment env = myTemplate.createProcessingEnvironment(root, out);
317:             * env.include("include/common.ftl", null, true);  // before processing
318:             * env.process();
319:             * TemplateModel x = env.getVariable("x");  // after processing
320:             * </pre>
321:             *
322:             * @param rootMap the root node of the data model.  If null, an
323:             * empty data model is used. Can be any object that the effective object
324:             * wrapper can turn into a <tt>TemplateHashModel</tt> Basically, simple and
325:             * beans wrapper can turn <tt>java.util.Map</tt> objects into hashes
326:             * and the Jython wrapper can turn both a <tt>PyDictionary</tt> as well as any
327:             * object that implements <tt>__getitem__</tt> into a template hash.
328:             * Naturally, you can pass any object directly implementing
329:             * <tt>TemplateHashModel</tt> as well.
330:             * @param wrapper The object wrapper to use to wrap objects into
331:             * {@link TemplateModel} instances. If null, the default wrapper retrieved
332:             * by {@link Configurable#getObjectWrapper()} is used.
333:             * @param out the writer to output the text to.
334:             * @return the {@link freemarker.core.Environment Environment} object created for processing
335:             * @throws TemplateException if an exception occurs while setting up the Environment object.
336:             * @throws IOException if an exception occurs doing any auto-imports
337:             */
338:            public Environment createProcessingEnvironment(Object rootMap,
339:                    Writer out, ObjectWrapper wrapper)
340:                    throws TemplateException, IOException {
341:                TemplateHashModel root = null;
342:                if (rootMap instanceof  TemplateHashModel) {
343:                    root = (TemplateHashModel) rootMap;
344:                } else {
345:                    if (wrapper == null) {
346:                        wrapper = getObjectWrapper();
347:                    }
348:
349:                    try {
350:                        root = rootMap != null ? (TemplateHashModel) wrapper
351:                                .wrap(rootMap) : new SimpleHash(wrapper);
352:                        if (root == null) {
353:                            throw new IllegalArgumentException(wrapper
354:                                    .getClass().getName()
355:                                    + " converted "
356:                                    + rootMap.getClass().getName()
357:                                    + " to null.");
358:                        }
359:                    } catch (ClassCastException e) {
360:                        throw new IllegalArgumentException(wrapper.getClass()
361:                                .getName()
362:                                + " could not convert "
363:                                + rootMap.getClass().getName()
364:                                + " to a TemplateHashModel.");
365:                    }
366:                }
367:                Environment env = new Environment(this , root, out);
368:                getConfiguration().doAutoImports(env);
369:                getConfiguration().doAutoIncludes(env);
370:                return env;
371:            }
372:
373:            /**
374:             * Same as <code>createProcessingEnvironment(rootMap, out, null)</code>.
375:             * @see #createProcessingEnvironment(Object rootMap, Writer out, ObjectWrapper wrapper)
376:             */
377:            public Environment createProcessingEnvironment(Object rootMap,
378:                    Writer out) throws TemplateException, IOException {
379:                return createProcessingEnvironment(rootMap, out, null);
380:            }
381:
382:            /**
383:             * Returns a string representing the raw template
384:             * text in canonical form.
385:             */
386:            public String toString() {
387:                StringWriter sw = new StringWriter();
388:                try {
389:                    dump(sw);
390:                } catch (IOException ioe) {
391:                    throw new RuntimeException(ioe.getMessage());
392:                }
393:                return sw.toString();
394:            }
395:
396:            /**
397:             * The path of the template file relative to the directory what you use to store the templates.
398:             * For example, if the real path of template is <tt>"/www/templates/community/forum.fm"</tt>,
399:             * and you use "<tt>"/www/templates"</tt> as
400:             * {@link Configuration#setDirectoryForTemplateLoading "directoryForTemplateLoading"},
401:             * then <tt>name</tt> should be <tt>"community/forum.fm"</tt>. The <tt>name</tt> is used for example when you
402:             * use <tt>&lt;include ...></tt> and you give a path that is relative to the current
403:             * template, or in error messages when FreeMarker logs an error while it processes the template.
404:             */
405:            public String getName() {
406:                return name;
407:            }
408:
409:            /**
410:             * Returns the Configuration object associated with this template.
411:             */
412:            public Configuration getConfiguration() {
413:                return (Configuration) getParent();
414:            }
415:
416:            /**
417:             * Sets the character encoding to use for
418:             * included files. Usually you don't set this value manually,
419:             * instead it is assigned to the template upon loading.
420:             */
421:
422:            public void setEncoding(String encoding) {
423:                this .encoding = encoding;
424:            }
425:
426:            /**
427:             * Returns the character encoding used for reading included files.
428:             */
429:            public String getEncoding() {
430:                return this .encoding;
431:            }
432:
433:            /**
434:             * Dump the raw template in canonical form.
435:             */
436:            public void dump(PrintStream ps) {
437:                ps.print(rootElement.getCanonicalForm());
438:            }
439:
440:            /**
441:             * Dump the raw template in canonical form.
442:             */
443:            public void dump(Writer out) throws IOException {
444:                out.write(rootElement.getCanonicalForm());
445:            }
446:
447:            /**
448:             * Called by code internally to maintain
449:             * a table of macros
450:             */
451:            public void addMacro(Macro macro) {
452:                macros.put(macro.getName(), macro);
453:            }
454:
455:            /**
456:             * Called by code internally to maintain
457:             * a list of imports
458:             */
459:            public void addImport(LibraryLoad ll) {
460:                imports.add(ll);
461:            }
462:
463:            /**
464:             * Returns the template source at the location
465:             * specified by the coordinates given.
466:             * @param beginColumn the first column of the requested source, 1-based
467:             * @param beginLine the first line of the requested source, 1-based
468:             * @param endColumn the last column of the requested source, 1-based
469:             * @param endLine the last line of the requested source, 1-based
470:             * @see freemarker.core.TemplateObject#getSource()
471:             */
472:            public String getSource(int beginColumn, int beginLine,
473:                    int endColumn, int endLine) {
474:                // Our container is zero-based.
475:                --beginLine;
476:                --beginColumn;
477:                --endColumn;
478:                --endLine;
479:                StringBuffer buf = new StringBuffer();
480:                for (int i = beginLine; i <= endLine; i++) {
481:                    if (i < lines.size()) {
482:                        buf.append(lines.get(i));
483:                    }
484:                }
485:                int lastLineLength = lines.get(endLine).toString().length();
486:                int trailingCharsToDelete = lastLineLength - endColumn - 1;
487:                buf.delete(0, beginColumn);
488:                buf.delete(buf.length() - trailingCharsToDelete, buf.length());
489:                return buf.toString();
490:            }
491:
492:            /**
493:             * This is a helper class that builds up the line table
494:             * info for us.
495:             */
496:            private class LineTableBuilder extends FilterReader {
497:
498:                StringBuffer lineBuf = new StringBuffer();
499:                int lastChar;
500:
501:                /**
502:                 * @param r the character stream to wrap
503:                 */
504:                LineTableBuilder(Reader r) {
505:                    super (r);
506:                }
507:
508:                public int read() throws IOException {
509:                    int c = in.read();
510:                    handleChar(c);
511:                    return c;
512:                }
513:
514:                public int read(char cbuf[], int off, int len)
515:                        throws IOException {
516:                    int numchars = in.read(cbuf, off, len);
517:                    for (int i = off; i < off + numchars; i++) {
518:                        char c = cbuf[i];
519:                        handleChar(c);
520:                    }
521:                    return numchars;
522:                }
523:
524:                public void close() throws IOException {
525:                    if (lineBuf.length() > 0) {
526:                        lines.add(lineBuf.toString());
527:                        lineBuf.setLength(0);
528:                    }
529:                    super .close();
530:                }
531:
532:                private void handleChar(int c) {
533:                    if (c == '\n' || c == '\r') {
534:                        if (lastChar == '\r' && c == '\n') { // CRLF under Windoze
535:                            int lastIndex = lines.size() - 1;
536:                            String lastLine = (String) lines.get(lastIndex);
537:                            lines.set(lastIndex, lastLine + '\n');
538:                        } else {
539:                            lineBuf.append((char) c);
540:                            lines.add(lineBuf.toString());
541:                            lineBuf.setLength(0);
542:                        }
543:                    } else if (c == '\t') {
544:                        int numSpaces = 8 - (lineBuf.length() % 8);
545:                        for (int i = 0; i < numSpaces; i++) {
546:                            lineBuf.append(' ');
547:                        }
548:                    } else {
549:                        lineBuf.append((char) c);
550:                    }
551:                    lastChar = c;
552:                }
553:            }
554:
555:            /**
556:             *  @return the root TemplateElement object.
557:             */
558:            public TemplateElement getRootTreeNode() {
559:                return rootElement;
560:            }
561:
562:            public Map getMacros() {
563:                return macros;
564:            }
565:
566:            public List getImports() {
567:                return imports;
568:            }
569:
570:            /**
571:             * This is used internally.
572:             */
573:            public void addPrefixNSMapping(String prefix, String nsURI) {
574:                if (nsURI.length() == 0) {
575:                    throw new IllegalArgumentException(
576:                            "Cannot map empty string URI");
577:                }
578:                if (prefix.length() == 0) {
579:                    throw new IllegalArgumentException(
580:                            "Cannot map empty string prefix");
581:                }
582:                if (prefix.equals(NO_NS_PREFIX)) {
583:                    throw new IllegalArgumentException(
584:                            "The prefix: "
585:                                    + prefix
586:                                    + " cannot be registered, it is reserved for special internal use.");
587:                }
588:                if (prefixToNamespaceURILookup.containsKey(prefix)) {
589:                    throw new IllegalArgumentException("The prefix: '" + prefix
590:                            + "' was repeated. This is illegal.");
591:                }
592:                if (namespaceURIToPrefixLookup.containsKey(nsURI)) {
593:                    throw new IllegalArgumentException("The namespace URI: "
594:                            + nsURI
595:                            + " cannot be mapped to 2 different prefixes.");
596:                }
597:                if (prefix.equals(DEFAULT_NAMESPACE_PREFIX)) {
598:                    this .defaultNS = nsURI;
599:                } else {
600:                    prefixToNamespaceURILookup.put(prefix, nsURI);
601:                    namespaceURIToPrefixLookup.put(nsURI, prefix);
602:                }
603:            }
604:
605:            public String getDefaultNS() {
606:                return this .defaultNS;
607:            }
608:
609:            /**
610:             * @return the NamespaceUri mapped to this prefix in this template. (Or null if there is none.)
611:             */
612:            public String getNamespaceForPrefix(String prefix) {
613:                if (prefix.equals("")) {
614:                    return defaultNS == null ? "" : defaultNS;
615:                }
616:                return (String) prefixToNamespaceURILookup.get(prefix);
617:            }
618:
619:            /**
620:             * @return the prefix mapped to this nsURI in this template. (Or null if there is none.)
621:             */
622:            public String getPrefixForNamespace(String nsURI) {
623:                if (nsURI == null) {
624:                    return null;
625:                }
626:                if (nsURI.length() == 0) {
627:                    return defaultNS == null ? "" : NO_NS_PREFIX;
628:                }
629:                if (nsURI.equals(defaultNS)) {
630:                    return "";
631:                }
632:                return (String) namespaceURIToPrefixLookup.get(nsURI);
633:            }
634:
635:            /**
636:             * @return the prefixed name, based on the ns_prefixes defined
637:             * in this template's header for the local name and node namespace
638:             * passed in as parameters.
639:             */
640:            public String getPrefixedName(String localName, String nsURI) {
641:                if (nsURI == null || nsURI.length() == 0) {
642:                    if (defaultNS != null) {
643:                        return NO_NS_PREFIX + ":" + localName;
644:                    } else {
645:                        return localName;
646:                    }
647:                }
648:                if (nsURI.equals(defaultNS)) {
649:                    return localName;
650:                }
651:                String prefix = getPrefixForNamespace(nsURI);
652:                if (prefix == null) {
653:                    return null;
654:                }
655:                return prefix + ":" + localName;
656:            }
657:
658:            /**
659:             * @return an array of the elements containing the given column and line numbers.
660:             * @param column the column
661:             * @param line the line
662:             */
663:            public TreePath containingElements(int column, int line) {
664:                ArrayList elements = new ArrayList();
665:                TemplateElement element = rootElement;
666:                mainloop: while (element.contains(column, line)) {
667:                    elements.add(element);
668:                    for (Enumeration enumeration = element.children(); enumeration
669:                            .hasMoreElements();) {
670:                        TemplateElement elem = (TemplateElement) enumeration
671:                                .nextElement();
672:                        if (elem.contains(column, line)) {
673:                            element = elem;
674:                            continue mainloop;
675:                        }
676:                    }
677:                    break;
678:                }
679:                if (elements == null || elements.isEmpty()) {
680:                    return null;
681:                }
682:                return new TreePath(elements.toArray());
683:            }
684:
685:            static public class WrongEncodingException extends ParseException {
686:
687:                public String specifiedEncoding;
688:
689:                public WrongEncodingException(String specifiedEncoding) {
690:                    this.specifiedEncoding = specifiedEncoding;
691:                }
692:
693:            }
694:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.