Source Code Cross Referenced for AbstractMarkupLanguage.java in  » Content-Management-System » apache-lenya-2.0 » org » apache » cocoon » components » language » markup » 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 » Content Management System » apache lenya 2.0 » org.apache.cocoon.components.language.markup 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Licensed to the Apache Software Foundation (ASF) under one or more
003:         * contributor license agreements.  See the NOTICE file distributed with
004:         * this work for additional information regarding copyright ownership.
005:         * The ASF licenses this file to You under the Apache License, Version 2.0
006:         * (the "License"); you may not use this file except in compliance with
007:         * the License.  You may obtain a copy of the License at
008:         * 
009:         *      http://www.apache.org/licenses/LICENSE-2.0
010:         * 
011:         * Unless required by applicable law or agreed to in writing, software
012:         * distributed under the License is distributed on an "AS IS" BASIS,
013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014:         * See the License for the specific language governing permissions and
015:         * limitations under the License.
016:         */
017:        package org.apache.cocoon.components.language.markup;
018:
019:        import org.apache.avalon.framework.activity.Disposable;
020:        import org.apache.avalon.framework.configuration.Configurable;
021:        import org.apache.avalon.framework.configuration.Configuration;
022:        import org.apache.avalon.framework.configuration.ConfigurationException;
023:        import org.apache.avalon.framework.logger.AbstractLogEnabled;
024:        import org.apache.avalon.framework.parameters.Parameters;
025:        import org.apache.avalon.framework.service.ServiceException;
026:        import org.apache.avalon.framework.service.ServiceManager;
027:        import org.apache.avalon.framework.service.Serviceable;
028:
029:        import org.apache.avalon.excalibur.pool.Recyclable;
030:        import org.apache.excalibur.source.Source;
031:        import org.apache.excalibur.source.SourceException;
032:        import org.apache.excalibur.source.SourceResolver;
033:
034:        import org.apache.cocoon.ProcessingException;
035:        import org.apache.cocoon.xml.AbstractXMLPipe;
036:        import org.apache.cocoon.components.language.programming.ProgrammingLanguage;
037:        import org.apache.cocoon.components.source.SourceUtil;
038:        import org.apache.excalibur.store.Store;
039:
040:        import org.xml.sax.Attributes;
041:        import org.xml.sax.SAXException;
042:
043:        import java.io.IOException;
044:        import java.net.MalformedURLException;
045:        import java.util.ArrayList;
046:        import java.util.HashMap;
047:        import java.util.Iterator;
048:        import java.util.LinkedList;
049:        import java.util.List;
050:        import java.util.Map;
051:
052:        /**
053:         * Base implementation of <code>MarkupLanguage</code>. This class uses
054:         * logicsheets as the only means of code generation. Code generation
055:         * should be decoupled from this context!!!
056:         *
057:         * @author <a href="mailto:ricardo@apache.org">Ricardo Rocha</a>
058:         * @author <a href="mailto:dims@yahoo.com">Davanum Srinivas</a>
059:         * @author <a href="mailto:ovidiu@cup.hp.com">Ovidiu Predescu</a>
060:         * @version CVS $Id: AbstractMarkupLanguage.java 433543 2006-08-22 06:22:54Z crossley $
061:         */
062:        public abstract class AbstractMarkupLanguage extends AbstractLogEnabled
063:                implements  MarkupLanguage, Serviceable, Configurable,
064:                Recyclable, Disposable {
065:            /**
066:             * Name "attr-interpolation" of boolean attribute to enable
067:             * expression interpolation in attribute values.
068:             */
069:            public static final String ATTR_INTERPOLATION = "attr-interpolation";
070:
071:            /**
072:             * Name "text-interpolation" of boolean attribute to enable
073:             * expression interpolation inside text nodes.
074:             */
075:            public static final String TEXT_INTERPOLATION = "text-interpolation";
076:
077:            /** The 'file' URL protocol. */
078:            private static final String FILE = "file:";
079:
080:            /** Prefix for cache keys to avoid name clash with the XSLTProcessor */
081:            private static final String CACHE_PREFIX = "logicsheet:";
082:
083:            /** This language name */
084:            protected String name;
085:
086:            /** The supported language table */
087:            protected Map languages;
088:
089:            /** The code-generation logicsheet cache */
090:            protected Store logicsheetCache;
091:
092:            /** The markup language's namespace uri */
093:            private String uri;
094:
095:            /** The markup language's namespace prefix */
096:            private String prefix;
097:
098:            /** Are attribute expressions to be expanded? */
099:            private boolean attrInterpolation;
100:
101:            /** Are text expressions to be expanded? */
102:            private boolean textInterpolation;
103:
104:            /** The service manager */
105:            protected ServiceManager manager;
106:
107:            /** The URL factory source resolver used to resolve URIs */
108:            private SourceResolver resolver;
109:
110:            /**
111:             * Stores the list of logicsheets required by the currently
112:             * loaded program.
113:             */
114:            private final LinkedList logicSheetList = new LinkedList();
115:
116:            /** The default constructor. */
117:            public AbstractMarkupLanguage() {
118:                // Initialize language table
119:                this .languages = new HashMap();
120:            }
121:
122:            /**
123:             * Process additional configuration. Load supported programming
124:             * language definitions
125:             *
126:             * @param conf The language configuration
127:             * @exception ConfigurationException If an error occurs loading logichseets
128:             */
129:            public void configure(Configuration conf)
130:                    throws ConfigurationException {
131:                try {
132:                    this .name = conf.getAttribute("name");
133:
134:                    // Cannot use Parameterizable because parameterize() is called
135:                    // after configure(), and <xsp-language> param's are already
136:                    // needed for processing logicsheet definitions.
137:                    Parameters params = Parameters.fromConfiguration(conf);
138:                    this .uri = params.getParameter("uri");
139:                    this .prefix = params.getParameter("prefix", null);
140:                    this .attrInterpolation = params.getParameterAsBoolean(
141:                            ATTR_INTERPOLATION, false);
142:                    this .textInterpolation = params.getParameterAsBoolean(
143:                            TEXT_INTERPOLATION, false);
144:
145:                    // Set up each target-language
146:                    Configuration[] l = conf.getChildren("target-language");
147:                    for (int i = 0; i < l.length; i++) {
148:                        LanguageDescriptor language = new LanguageDescriptor();
149:                        language.setName(l[i].getAttribute("name"));
150:
151:                        // Create & Store the core logicsheet
152:                        Logicsheet logicsheet = createLogicsheet(l[i], false);
153:                        language.setLogicsheet(logicsheet.getSystemId());
154:
155:                        // Set up each built-in logicsheet
156:                        Configuration[] n = l[i]
157:                                .getChildren("builtin-logicsheet");
158:                        for (int j = 0; j < n.length; j++) {
159:                            // Create & Store the named logicsheets
160:                            NamedLogicsheet namedLogicsheet = (NamedLogicsheet) createLogicsheet(
161:                                    n[j], true);
162:
163:                            language.addNamedLogicsheet(namedLogicsheet
164:                                    .getURI(), namedLogicsheet.getPrefix(),
165:                                    namedLogicsheet.getSystemId());
166:                        }
167:
168:                        this .languages.put(language.getName(), language);
169:                    }
170:                } catch (Exception e) {
171:                    getLogger().warn("Configuration Error: " + e.getMessage(),
172:                            e);
173:                    throw new ConfigurationException("AbstractMarkupLanguage: "
174:                            + e.getMessage(), e);
175:                }
176:            }
177:
178:            /**
179:             * Abstract out the Logicsheet creation.  Handles both Named and regular logicsheets.
180:             */
181:            private Logicsheet createLogicsheet(Configuration configuration,
182:                    boolean named) throws Exception {
183:                Parameters params = Parameters.fromConfiguration(configuration);
184:
185:                Logicsheet logicsheet;
186:                if (named) {
187:                    String location = params.getParameter("href", null);
188:                    String uri = params.getParameter("uri", null);
189:                    String prefix = params.getParameter("prefix", null);
190:
191:                    NamedLogicsheet namedLogicsheet = new NamedLogicsheet(
192:                            location, manager, resolver, getLogicsheetFilter());
193:                    namedLogicsheet.setURI(uri);
194:                    namedLogicsheet.setPrefix(prefix);
195:                    logicsheet = namedLogicsheet;
196:                } else {
197:                    String location = params.getParameter("core-logicsheet",
198:                            null);
199:                    logicsheet = new Logicsheet(location, manager, resolver,
200:                            getLogicsheetFilter());
201:                }
202:
203:                logicsheet.enableLogging(getLogger());
204:
205:                String logicsheetName = logicsheet.getSystemId();
206:                logicsheetCache
207:                        .store(CACHE_PREFIX + logicsheetName, logicsheet);
208:
209:                return logicsheet;
210:            }
211:
212:            /**
213:             * Set the global service manager.
214:             * @param manager The sitemap-specified service manager
215:             */
216:            public void service(ServiceManager manager) throws ServiceException {
217:                this .manager = manager;
218:
219:                // Initialize logicsheet cache
220:                this .logicsheetCache = (Store) manager
221:                        .lookup(Store.TRANSIENT_STORE);
222:
223:                // Initialize the source resolver
224:                this .resolver = (SourceResolver) this .manager
225:                        .lookup(SourceResolver.ROLE);
226:            }
227:
228:            /**
229:             * Recycle this component: clear logic sheet list and dependencies.
230:             */
231:            public void recycle() {
232:                this .logicSheetList.clear();
233:            }
234:
235:            /**
236:             * Release all resources.
237:             */
238:            public void dispose() {
239:                this .manager.release(this .logicsheetCache);
240:                this .logicsheetCache = null;
241:
242:                this .manager.release(this .resolver);
243:                this .resolver = null;
244:                this .manager = null;
245:                this .languages.clear();
246:            }
247:
248:            /**
249:             * Return the markup language name. Two markup languages are
250:             * well-know at the moment: sitemap and xsp.
251:             *
252:             * @return The language name.
253:             */
254:            public String getName() {
255:                return this .name;
256:            }
257:
258:            /**
259:             * Returns the namespace URI for this language.
260:             */
261:            public String getURI() {
262:                return this .uri;
263:            }
264:
265:            /**
266:             * Returns the namespace prefix for this language.
267:             */
268:            public String getPrefix() {
269:                return this .prefix;
270:            }
271:
272:            /**
273:             * Returns true if expansion of attribute expressions is enabled
274:             * for this language.
275:             */
276:            public boolean hasAttrInterpolation() {
277:                return this .attrInterpolation;
278:            }
279:
280:            /**
281:             * Returns true if expansion of expressions inside text nodes is enabled
282:             * for this language.
283:             */
284:            public boolean hasTextInterpolation() {
285:                return this .textInterpolation;
286:            }
287:
288:            /**
289:             * Return the source document's encoding. This can be <code>null</code> for
290:             * the platform's default encoding. The default implementation returns
291:             * <code>null</code>, but derived classes may override it if encoding applies to
292:             * their concrete languages.
293:             *
294:             * FIXME: There should be a way to get the
295:             * XML document's encoding as seen by the parser; unfortunately, this
296:             * information is not returned by current DOM or SAX parsers...
297:             *
298:             * @return The document-specified encoding
299:             */
300:            public String getEncoding() {
301:                return null;
302:            }
303:
304:            /**
305:             * Returns a filter that chains on the fly the requested
306:             * transformers for source code generation. This method scans the
307:             * input SAX events for built-in logicsheet declared as namespace
308:             * attribute on the root element. Derived class should overide
309:             * this method and the public inner class in order to add more
310:             * specif action and to build a more specific transformer chain.
311:             *
312:             * @param logicsheetMarkupGenerator the logicsheet markup generator
313:             * @return XMLFilter the filter that build on the fly the transformer chain
314:             */
315:            protected TransformerChainBuilderFilter getTransformerChainBuilder(
316:                    LogicsheetCodeGenerator logicsheetMarkupGenerator) {
317:                return new TransformerChainBuilderFilter(
318:                        logicsheetMarkupGenerator);
319:            }
320:
321:            /**
322:             * Prepare the input source for logicsheet processing and code
323:             * generation with a preprocess filter.  The return
324:             * <code>XMLFilter</code> object is the first filter on the
325:             * transformer chain.  The default implementation does nothing by
326:             * returning a identity filter, but derived classes should (at
327:             * least) use the passed programming language to quote
328:             * <code>Strings</code>
329:             *
330:             * @param filename The source filename
331:             * @param language The target programming language
332:             * @return The preprocess filter
333:             */
334:            protected AbstractXMLPipe getPreprocessFilter(String filename,
335:                    AbstractXMLPipe filter, ProgrammingLanguage language) {
336:                // No-op
337:                return filter;
338:            }
339:
340:            /**
341:             * Add a dependency on an external file to the document for inclusion in
342:             * generated code. This is used to populate a list of <code>File</code>'s
343:             * tested for change on each invocation; this information is used to assert whether regeneration is necessary.
344:             *
345:             * @param location The file path of the dependent file
346:             * @see AbstractMarkupLanguage
347:             * @see org.apache.cocoon.generation.ServerPagesGenerator
348:             * @see org.apache.cocoon.generation.AbstractServerPage
349:             */
350:            protected abstract void addDependency(String location);
351:
352:            /**
353:             * Generate source code from the input document for the target
354:             * <code>ProgrammingLanguage</code>. After preprocessing the input
355:             * document, this method applies logicsheets in the following
356:             * order:
357:             *
358:             * <ul>
359:             * <li>User-defined logicsheets</li>
360:             * <li>Namespace-mapped logicsheets</li>
361:             * <li>Language-specific logicsheet</li>
362:             * </ul>
363:             *
364:             * @param source The input source
365:             * @param filename The input document's original filename
366:             * @param programmingLanguage The target programming language
367:             * @return The generated source code
368:             * @exception Exception If an error occurs during code generation
369:             */
370:            public String generateCode(Source source, String filename,
371:                    ProgrammingLanguage programmingLanguage) throws Exception {
372:
373:                String languageName = programmingLanguage.getLanguageName();
374:                LanguageDescriptor language = (LanguageDescriptor) this .languages
375:                        .get(languageName);
376:                if (language == null) {
377:                    throw new IllegalArgumentException(
378:                            "Unsupported programming language: " + languageName);
379:                }
380:
381:                // Create code generator
382:                LogicsheetCodeGenerator codeGenerator = new LogicsheetCodeGenerator();
383:                codeGenerator.enableLogging(getLogger());
384:                codeGenerator.initialize();
385:                // Set the transformer chain builder filter
386:                TransformerChainBuilderFilter tranBuilder = getTransformerChainBuilder(codeGenerator);
387:                tranBuilder.setLanguageDescriptor(language);
388:
389:                // Get the needed preprocess filter
390:                AbstractXMLPipe preprocessor = getPreprocessFilter(filename,
391:                        tranBuilder, programmingLanguage);
392:                return codeGenerator.generateCode(source, preprocessor);
393:            }
394:
395:            /**
396:             * Add logicsheet list to the code generator.
397:             * @param codeGenerator The code generator
398:             */
399:            protected void addLogicsheetsToGenerator(
400:                    LogicsheetCodeGenerator codeGenerator)
401:                    throws MalformedURLException, IOException, SAXException,
402:                    ProcessingException {
403:
404:                if (codeGenerator == null) {
405:                    getLogger().debug(
406:                            "This should never happen: codeGenerator is null");
407:                    throw new SAXException("codeGenerator must never be null.");
408:                }
409:
410:                // Walk backwards and remove duplicates.
411:                LinkedList newLogicSheetList = new LinkedList();
412:                for (int i = logicSheetList.size() - 1; i >= 0; i--) {
413:                    Logicsheet logicsheet = (Logicsheet) logicSheetList.get(i);
414:                    if (newLogicSheetList.indexOf(logicsheet) == -1)
415:                        newLogicSheetList.addFirst(logicsheet);
416:                }
417:
418:                // Add the list of logicsheets now.
419:                Iterator iterator = newLogicSheetList.iterator();
420:                while (iterator.hasNext()) {
421:                    Logicsheet logicsheet = (Logicsheet) iterator.next();
422:                    codeGenerator.addLogicsheet(logicsheet);
423:                }
424:            }
425:
426:            /**
427:             * Add a logicsheet to the code generator.
428:             * @param language Target programming language of the logicsheet
429:             * @param logicsheetLocation Location of the logicsheet to be added
430:             * @exception MalformedURLException If location is invalid
431:             * @exception IOException IO Error
432:             * @exception SAXException Logicsheet parse error
433:             */
434:            protected void addLogicsheetToList(LanguageDescriptor language,
435:                    String logicsheetLocation) throws IOException,
436:                    SAXException, ProcessingException {
437:                Source inputSource = null;
438:                String logicsheetName;
439:                try {
440:                    // Logicsheet is reusable (across multiple XSPs) object,
441:                    // and it is resolved via urlResolver, and not via per-request
442:                    // temporary resolver.
443:                    // Resolve logicsheet location relative to sitemap from where it is used.
444:                    inputSource = this .resolver.resolveURI(logicsheetLocation);
445:                    logicsheetName = inputSource.getURI();
446:                } catch (SourceException se) {
447:                    throw SourceUtil.handle(se);
448:                } finally {
449:                    this .resolver.release(inputSource);
450:                }
451:
452:                // Logicsheets are chained by looking at the namespaces on the xsl:stylesheet
453:                // root node.  To get at these namespaces, the stylesheet must be parsed.
454:                // Stylesheets are cached that we have only one chance to fill the namespaces.
455:                // To avoid a race condition, we have to lock the critical section.
456:                // For maximum concurrency we lock the cache, store if necessary the new,
457:                // unparsed logicsheet, and then lock the logicsheet for the long-running
458:                // parse operation.
459:
460:                Logicsheet logicsheet;
461:                synchronized (logicsheetCache) {
462:                    String cacheKey = CACHE_PREFIX + logicsheetName;
463:                    logicsheet = (Logicsheet) logicsheetCache.get(cacheKey);
464:                    if (logicsheet == null) {
465:                        // Resolver (local) could not be used as it is temporary
466:                        // (per-request) object, yet Logicsheet is being cached and reused
467:                        // across multiple requests. "Global" url-factory-based resolver
468:                        // passed to the Logicsheet.
469:                        logicsheet = new Logicsheet(logicsheetName, manager,
470:                                resolver, getLogicsheetFilter());
471:                        logicsheetCache.store(cacheKey, logicsheet);
472:                    }
473:                }
474:
475:                synchronized (logicsheet) {
476:                    Map namespaces = logicsheet.getNamespaceURIs();
477:                    if (namespaces == null)
478:                        logicsheet.fillNamespaceURIs();
479:                }
480:
481:                if (getLogger().isDebugEnabled()) {
482:                    getLogger().debug(
483:                            "addLogicsheetToList: " + "name: " + logicsheetName
484:                                    + ", location: " + logicsheetLocation
485:                                    + ", instance: " + logicsheet);
486:                }
487:
488:                if (logicsheetName.startsWith(FILE)) {
489:                    String filename = logicsheetName.substring(FILE.length());
490:                    addDependency(filename);
491:                    getLogger().debug(
492:                            "addLogicsheetToList: "
493:                                    + "adding dependency on file " + filename);
494:                }
495:
496:                logicSheetList.add(logicsheet);
497:
498:                Map namespaces = logicsheet.getNamespaceURIs();
499:                if (!logicsheetLocation.equals(language.getLogicsheet())) {
500:                    if (namespaces.size() > 0) {
501:                        Iterator iter = namespaces.keySet().iterator();
502:                        while (iter.hasNext()) {
503:                            String namespace = (String) iter.next();
504:                            String namedLogicsheetName = language
505:                                    .getNamedLogicsheetByURI(namespace);
506:                            if (namedLogicsheetName != null
507:                                    && !logicsheetLocation
508:                                            .equals(namedLogicsheetName)) {
509:                                getLogger().debug(
510:                                        "Adding embedded logic sheet for "
511:                                                + namespace + ": "
512:                                                + namedLogicsheetName);
513:                                // Add embedded logic sheets too.
514:                                addLogicsheetToList(language,
515:                                        namedLogicsheetName);
516:                            }
517:                        }
518:                    }
519:                }
520:            }
521:
522:            /**
523:             * Return the optional filter to prepocess logicsheets.
524:             */
525:            protected LogicsheetFilter getLogicsheetFilter() {
526:                return new LogicsheetFilter();
527:            }
528:
529:            //
530:            // Inner classes
531:            //
532:
533:            /** This class holds transient information about a target programming language. */
534:            protected static class LanguageDescriptor {
535:                /** The progamming language name */
536:                protected String name;
537:
538:                /** The progamming language core logicsheet */
539:                protected String logicsheet;
540:
541:                /** The list of built-in logicsheets defined for this target language */
542:                protected HashMap namedLogicsheets;
543:
544:                /** The default constructor */
545:                protected LanguageDescriptor() {
546:                    this .namedLogicsheets = new HashMap();
547:                }
548:
549:                /**
550:                 * Set the programming language's name
551:                 * @param name The programming language's name
552:                 */
553:                protected void setName(String name) {
554:                    this .name = name;
555:                }
556:
557:                /**
558:                 * Return the programming language's name
559:                 * @return The programming language's name
560:                 */
561:                protected String getName() {
562:                    return this .name;
563:                }
564:
565:                /**
566:                 * Set the programming language's core logichseet location
567:                 * @param logicsheet The programming language's core logichseet location
568:                 */
569:                protected void setLogicsheet(String logicsheet) {
570:                    this .logicsheet = logicsheet;
571:                }
572:
573:                /**
574:                 * Return the programming language's core logichseet location
575:                 * @return The programming language's core logichseet location
576:                 */
577:                protected String getLogicsheet() {
578:                    return this .logicsheet;
579:                }
580:
581:                /**
582:                 * Add a namespace-mapped logicsheet to this language
583:                 * @param prefix The logichseet's namespace prefix
584:                 * @param uri The logichseet's namespace uri
585:                 * @param namedLogicsheet The logichseet's location
586:                 */
587:                protected void addNamedLogicsheet(String uri, String prefix,
588:                        String namedLogicsheet) {
589:                    this .namedLogicsheets.put(uri, namedLogicsheet);
590:                }
591:
592:                /**
593:                 * Return a namespace-mapped logicsheet given its uri
594:                 * @return The namespace-mapped logicsheet
595:                 */
596:                protected String getNamedLogicsheetByURI(String uri) {
597:                    return (String) this .namedLogicsheets.get(uri);
598:                }
599:            }
600:
601:            /**
602:             * An XMLFilter that build the chain of transformers on the fly.
603:             * Each time a stylesheet is found, a call to the code generator is done
604:             * to add the new transformer at the end of the current transformer chain.
605:             */
606:            public class TransformerChainBuilderFilter extends AbstractXMLPipe {
607:                /** The markup generator */
608:                protected LogicsheetCodeGenerator logicsheetMarkupGenerator;
609:
610:                /** the language description */
611:                protected LanguageDescriptor language;
612:
613:                private boolean isRootElem;
614:                private List startPrefixes;
615:
616:                /**
617:                 * the constructor depends on the code generator
618:                 * @param logicsheetMarkupGenerator The code generator
619:                 */
620:                protected TransformerChainBuilderFilter(
621:                        LogicsheetCodeGenerator logicsheetMarkupGenerator) {
622:                    this .logicsheetMarkupGenerator = logicsheetMarkupGenerator;
623:                }
624:
625:                /**
626:                 * This method should be called prior to receiving any SAX event.
627:                 * Indeed the language information is needed to get the core stylesheet.
628:                 * @param language the language in used
629:                 */
630:                protected void setLanguageDescriptor(LanguageDescriptor language) {
631:                    this .language = language;
632:                }
633:
634:                /** @see org.xml.sax.ContentHandler */
635:                public void startDocument() throws SAXException {
636:                    isRootElem = true;
637:                    startPrefixes = new ArrayList();
638:                }
639:
640:                /** @see org.xml.sax.ContentHandler */
641:                public void startPrefixMapping(String prefix, String uri)
642:                        throws SAXException {
643:                    if (!isRootElem) {
644:                        super .startPrefixMapping(prefix, uri);
645:                    } else {
646:                        // Cache the prefix mapping
647:                        String[] prefixNamingArray = new String[2];
648:                        prefixNamingArray[0] = prefix;
649:                        prefixNamingArray[1] = uri;
650:                        this .startPrefixes.add(prefixNamingArray);
651:                    }
652:                }
653:
654:                /** @see org.xml.sax.ContentHandler */
655:                public void startElement(String namespaceURI, String localName,
656:                        String qName, Attributes atts) throws SAXException {
657:                    if (isRootElem) {
658:                        isRootElem = false;
659:                        try {
660:                            // Add namespace-mapped logicsheets
661:                            int prefixesCount = this .startPrefixes.size();
662:                            for (int i = 0; i < prefixesCount; i++) {
663:                                String[] prefixNamingArray = (String[]) this .startPrefixes
664:                                        .get(i);
665:                                String namedLogicsheetName = this .language
666:                                        .getNamedLogicsheetByURI(prefixNamingArray[1]);
667:                                if (namedLogicsheetName != null) {
668:                                    AbstractMarkupLanguage.this 
669:                                            .addLogicsheetToList(language,
670:                                                    namedLogicsheetName);
671:                                }
672:                            }
673:
674:                            // Add the language stylesheet (Always the last one)
675:                            AbstractMarkupLanguage.this .addLogicsheetToList(
676:                                    language, this .language.getLogicsheet());
677:                            AbstractMarkupLanguage.this 
678:                                    .addLogicsheetsToGenerator(this .logicsheetMarkupGenerator);
679:                        } catch (ProcessingException pe) {
680:                            throw new SAXException(pe);
681:                        } catch (IOException ioe) {
682:                            throw new SAXException(ioe);
683:                        }
684:
685:                        // All stylesheet have been configured and correctly setup.
686:                        // Starts firing SAX events, especially the startDocument event,
687:                        // and the cached prefixNaming.
688:                        super .startDocument();
689:                        int prefixesCount = this .startPrefixes.size();
690:                        for (int i = 0; i < prefixesCount; i++) {
691:                            String[] prefixNamingArray = (String[]) this .startPrefixes
692:                                    .get(i);
693:                            super .startPrefixMapping(prefixNamingArray[0],
694:                                    prefixNamingArray[1]);
695:                        }
696:                    }
697:                    // Call super method
698:                    super.startElement(namespaceURI, localName, qName, atts);
699:                }
700:            }
701:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.