Source Code Cross Referenced for PageLoaderProcessor.java in  » Web-Framework » Tapestry » org » apache » tapestry » internal » services » 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 » Web Framework » Tapestry » org.apache.tapestry.internal.services 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        // Copyright 2007 The Apache Software Foundation
002:        //
003:        // Licensed under the Apache License, Version 2.0 (the "License");
004:        // you may not use this file except in compliance with the License.
005:        // You may obtain a copy of the License at
006:        //
007:        //     http://www.apache.org/licenses/LICENSE-2.0
008:        //
009:        // Unless required by applicable law or agreed to in writing, software
010:        // distributed under the License is distributed on an "AS IS" BASIS,
011:        // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012:        // See the License for the specific language governing permissions and
013:        // limitations under the License.
014:
015:        package org.apache.tapestry.internal.services;
016:
017:        import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newCaseInsensitiveMap;
018:        import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newMap;
019:        import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newStack;
020:        import static org.apache.tapestry.ioc.internal.util.InternalUtils.isBlank;
021:        import static org.apache.tapestry.ioc.internal.util.InternalUtils.isNonBlank;
022:
023:        import java.util.Locale;
024:        import java.util.Map;
025:
026:        import org.apache.commons.logging.Log;
027:        import org.apache.tapestry.Binding;
028:        import org.apache.tapestry.ComponentResources;
029:        import org.apache.tapestry.TapestryConstants;
030:        import org.apache.tapestry.internal.bindings.LiteralBinding;
031:        import org.apache.tapestry.internal.parser.AttributeToken;
032:        import org.apache.tapestry.internal.parser.BlockToken;
033:        import org.apache.tapestry.internal.parser.BodyToken;
034:        import org.apache.tapestry.internal.parser.CommentToken;
035:        import org.apache.tapestry.internal.parser.ComponentTemplate;
036:        import org.apache.tapestry.internal.parser.DTDToken;
037:        import org.apache.tapestry.internal.parser.EndElementToken;
038:        import org.apache.tapestry.internal.parser.ExpansionToken;
039:        import org.apache.tapestry.internal.parser.ParameterToken;
040:        import org.apache.tapestry.internal.parser.StartComponentToken;
041:        import org.apache.tapestry.internal.parser.StartElementToken;
042:        import org.apache.tapestry.internal.parser.TemplateToken;
043:        import org.apache.tapestry.internal.parser.TextToken;
044:        import org.apache.tapestry.internal.structure.BlockImpl;
045:        import org.apache.tapestry.internal.structure.BodyPageElement;
046:        import org.apache.tapestry.internal.structure.ComponentPageElement;
047:        import org.apache.tapestry.internal.structure.Page;
048:        import org.apache.tapestry.internal.structure.PageElement;
049:        import org.apache.tapestry.internal.structure.PageImpl;
050:        import org.apache.tapestry.ioc.Location;
051:        import org.apache.tapestry.ioc.internal.util.IdAllocator;
052:        import org.apache.tapestry.ioc.internal.util.OneShotLock;
053:        import org.apache.tapestry.ioc.internal.util.TapestryException;
054:        import org.apache.tapestry.ioc.util.Stack;
055:        import org.apache.tapestry.model.ComponentModel;
056:        import org.apache.tapestry.model.EmbeddedComponentModel;
057:        import org.apache.tapestry.services.BindingSource;
058:        import org.apache.tapestry.services.PersistentFieldManager;
059:
060:        /**
061:         * Contains all the work-state related to the {@link PageLoaderImpl}.
062:         */
063:        class PageLoaderProcessor {
064:            private static final String INHERIT_PREFIX = "inherit:";
065:
066:            private static Runnable NO_OP = new Runnable() {
067:                public void run() {
068:                    // Do nothing.
069:                }
070:            };
071:
072:            private Stack<ComponentPageElement> _activeElementStack = newStack();
073:
074:            private boolean _addAttributesAsComponentBindings = false;
075:
076:            private boolean _dtdAdded;
077:
078:            private final Stack<BodyPageElement> _bodyPageElementStack = newStack();
079:
080:            // You can use a stack as a queue
081:            private final Stack<ComponentPageElement> _componentQueue = newStack();
082:
083:            private final Stack<Boolean> _discardEndTagStack = newStack();
084:
085:            private final Stack<Runnable> _endElementCommandStack = newStack();
086:
087:            private final IdAllocator _idAllocator = new IdAllocator();
088:
089:            private final LinkFactory _linkFactory;
090:
091:            private ComponentModel _loadingComponentModel;
092:
093:            private ComponentPageElement _loadingElement;
094:
095:            private final Map<String, Map<String, Binding>> _componentIdToBindingMap = newMap();
096:
097:            private Locale _locale;
098:
099:            private final OneShotLock _lock = new OneShotLock();
100:
101:            private Page _page;
102:
103:            private final PageElementFactory _pageElementFactory;
104:
105:            private final PersistentFieldManager _persistentFieldManager;
106:
107:            private final ComponentTemplateSource _templateSource;
108:
109:            public PageLoaderProcessor(ComponentTemplateSource templateSource,
110:                    PageElementFactory pageElementFactory,
111:                    LinkFactory linkFactory,
112:                    PersistentFieldManager persistentFieldManager) {
113:                _templateSource = templateSource;
114:                _pageElementFactory = pageElementFactory;
115:                _linkFactory = linkFactory;
116:                _persistentFieldManager = persistentFieldManager;
117:            }
118:
119:            private void bindParameterFromTemplate(
120:                    ComponentPageElement component, AttributeToken token) {
121:                String name = token.getName();
122:                ComponentResources resources = component
123:                        .getComponentResources();
124:
125:                // If already bound (i.e., from the component class, via @Component), then
126:                // ignore the value in the template. This may need improving to just ignore
127:                // the value if it is an unprefixed literal string.
128:
129:                if (resources.isBound(name))
130:                    return;
131:
132:                // Meta default of literal for the template.
133:
134:                String defaultBindingPrefix = determineDefaultBindingPrefix(
135:                        component, name,
136:                        TapestryConstants.LITERAL_BINDING_PREFIX);
137:
138:                Binding binding = findBinding(_loadingElement, component, name,
139:                        token.getValue(), defaultBindingPrefix, token
140:                                .getLocation());
141:
142:                if (binding != null) {
143:                    component.bindParameter(name, binding);
144:
145:                    Map<String, Binding> bindingMap = _componentIdToBindingMap
146:                            .get(component.getCompleteId());
147:                    bindingMap.put(name, binding);
148:                }
149:            }
150:
151:            private void addMixinsToComponent(ComponentPageElement component,
152:                    EmbeddedComponentModel model, String mixins) {
153:                if (model != null) {
154:                    for (String mixinClassName : model.getMixinClassNames())
155:                        _pageElementFactory.addMixinByClassName(component,
156:                                mixinClassName);
157:                }
158:
159:                if (mixins != null) {
160:                    for (String type : mixins.split(","))
161:                        _pageElementFactory.addMixinByTypeName(component, type);
162:                }
163:            }
164:
165:            private void bindParametersFromModel(EmbeddedComponentModel model,
166:                    ComponentPageElement loadingComponent,
167:                    ComponentPageElement component,
168:                    Map<String, Binding> bindingMap) {
169:                for (String name : model.getParameterNames()) {
170:                    String value = model.getParameterValue(name);
171:
172:                    String defaultBindingPrefix = determineDefaultBindingPrefix(
173:                            component, name,
174:                            TapestryConstants.PROP_BINDING_PREFIX);
175:
176:                    Binding binding = findBinding(loadingComponent, component,
177:                            name, value, defaultBindingPrefix, component
178:                                    .getLocation());
179:
180:                    if (binding != null) {
181:                        component.bindParameter(name, binding);
182:
183:                        // So that the binding can be shared if inherited by a subcomponent
184:                        bindingMap.put(name, binding);
185:                    }
186:                }
187:            }
188:
189:            /**
190:             * Creates a new binding, or returns an existing binding (or null) for the "inherit:" binding
191:             * prefix. Mostly a wrapper around
192:             * {@link BindingSource#newBinding(String, ComponentResources, ComponentResources, String, String, Location)
193:             * 
194:             * @return the new binding, or an existing binding (if inherited), or null (if inherited, and
195:             *         the containing parameter is not bound)
196:             */
197:            private Binding findBinding(ComponentPageElement loadingComponent,
198:                    ComponentPageElement component, String name, String value,
199:                    String defaultBindingPrefix, Location location) {
200:                if (value.startsWith(INHERIT_PREFIX)) {
201:                    String loadingParameterName = value
202:                            .substring(INHERIT_PREFIX.length());
203:                    Map<String, Binding> loadingComponentBindingMap = _componentIdToBindingMap
204:                            .get(loadingComponent.getCompleteId());
205:
206:                    // This may return null if the parameter is not bound in the loading component.
207:
208:                    Binding existing = loadingComponentBindingMap
209:                            .get(loadingParameterName);
210:
211:                    if (existing == null)
212:                        return null;
213:
214:                    String description = String
215:                            .format(
216:                                    "InheritedBinding[parameter %s %s(inherited from %s of %s)]",
217:                                    name, component.getCompleteId(),
218:                                    loadingParameterName, loadingComponent
219:                                            .getCompleteId());
220:
221:                    // This helps with debugging, and re-orients any thrown exceptions
222:                    // to the location of the inherited binding, rather than the container component's
223:                    // binding.
224:
225:                    return new InheritedBinding(description, existing, location);
226:                }
227:
228:                return _pageElementFactory.newBinding(name, loadingComponent
229:                        .getComponentResources(), component
230:                        .getComponentResources(), defaultBindingPrefix, value,
231:                        location);
232:            }
233:
234:            /**
235:             * Determines the default binding prefix for a particular parameter.
236:             * 
237:             * @param component
238:             *            the component which will have a parameter bound
239:             * @param parameterName
240:             *            the name of the parameter
241:             * @param informalParameterBindingPrefix
242:             *            the default to use for informal parameters
243:             * @return the binding prefix
244:             */
245:            private String determineDefaultBindingPrefix(
246:                    ComponentPageElement component, String parameterName,
247:                    String informalParameterBindingPrefix) {
248:                String defaultBindingPrefix = component
249:                        .getDefaultBindingPrefix(parameterName);
250:
251:                return defaultBindingPrefix != null ? defaultBindingPrefix
252:                        : informalParameterBindingPrefix;
253:            }
254:
255:            private PageElement newRenderBodyElement() {
256:                return _pageElementFactory
257:                        .newRenderBodyElement(_loadingElement);
258:            }
259:
260:            private void addToBody(PageElement element) {
261:                _bodyPageElementStack.peek().addToBody(element);
262:            }
263:
264:            private void attribute(AttributeToken token) {
265:                // This kind of bookkeeping is ugly, we probably should have distinct (if very similar)
266:                // tokens for attributes and for parameter bindings.
267:
268:                if (_addAttributesAsComponentBindings) {
269:                    ComponentPageElement activeElement = _activeElementStack
270:                            .peek();
271:
272:                    bindParameterFromTemplate(activeElement, token);
273:                    return;
274:                }
275:
276:                PageElement element = _pageElementFactory.newAttributeElement(
277:                        _loadingElement.getComponentResources(), token);
278:
279:                addToBody(element);
280:            }
281:
282:            private void body(BodyToken token) {
283:                addToBody(newRenderBodyElement());
284:
285:                // BODY tokens are *not* matched by END_ELEMENT tokens. Nor will there be
286:                // text or comment content "inside" the BODY.
287:            }
288:
289:            private void comment(CommentToken token) {
290:                PageElement commentElement = _pageElementFactory
291:                        .newCommentElement(token);
292:
293:                addToBody(commentElement);
294:            }
295:
296:            /**
297:             * Invoked whenever a token (start, startComponent, etc.) is encountered that will eventually
298:             * have a matching end token. Sets up the behavior for the end token.
299:             * 
300:             * @param discard
301:             *            if true, the end is discarded (if false the end token is added to the active body
302:             *            element)
303:             * @param command
304:             *            command to execute to return processor state back to what it was before the
305:             *            command executed
306:             */
307:            private void configureEnd(boolean discard, Runnable command) {
308:                _discardEndTagStack.push(discard);
309:                _endElementCommandStack.push(command);
310:            }
311:
312:            private void endElement(EndElementToken token) {
313:                // discard will be false if the matching start token was for a static element, and will be
314:                // true otherwise (component, block, parameter).
315:
316:                boolean discard = _discardEndTagStack.pop();
317:
318:                if (!discard) {
319:                    PageElement element = _pageElementFactory.newEndElement();
320:
321:                    addToBody(element);
322:                }
323:
324:                Runnable command = _endElementCommandStack.pop();
325:
326:                // Used to return environment to prior state.
327:
328:                command.run();
329:            }
330:
331:            private void expansion(ExpansionToken token) {
332:                PageElement element = _pageElementFactory.newExpansionElement(
333:                        _loadingElement.getComponentResources(), token);
334:
335:                addToBody(element);
336:            }
337:
338:            private String generateEmbeddedId(String embeddedType,
339:                    IdAllocator idAllocator) {
340:                // Component types may be in folders; strip off the folder part for starters.
341:
342:                int slashx = embeddedType.lastIndexOf("/");
343:
344:                String baseId = embeddedType.substring(slashx + 1)
345:                        .toLowerCase();
346:
347:                // The idAllocator is pre-loaded with all the component ids from the template, so even
348:                // if the lower-case type matches the id of an existing component, there won't be a name
349:                // collision.
350:
351:                return idAllocator.allocateId(baseId);
352:            }
353:
354:            /**
355:             * As currently implemented, this should be invoked just once and then the PageLoaderProcessor
356:             * instance should be discarded.
357:             */
358:            public Page loadPage(String logicalPageName, String pageClassName,
359:                    Locale locale) {
360:                // Ensure that loadPage() may only be invoked once.
361:
362:                _lock.lock();
363:
364:                _locale = locale;
365:
366:                _page = new PageImpl(logicalPageName, _locale, _linkFactory,
367:                        _persistentFieldManager);
368:
369:                loadRootComponent(pageClassName);
370:
371:                workComponentQueue();
372:
373:                // The page is *loaded* before it is attached to the request.
374:                // This is to help ensure that no client-specific information leaks
375:                // into the page.
376:
377:                _page.loaded();
378:
379:                return _page;
380:            }
381:
382:            private void loadRootComponent(String className) {
383:                ComponentPageElement rootComponent = _pageElementFactory
384:                        .newRootComponentElement(_page, className);
385:
386:                _page.setRootElement(rootComponent);
387:
388:                _componentQueue.push(rootComponent);
389:            }
390:
391:            /**
392:             * Do you smell something? I'm smelling that this class needs to be redesigned to not need a
393:             * central method this large and hard to test. I think a lot of instance and local variables
394:             * need to be bundled up into some kind of process object. This code is effectively too big to
395:             * be tested except through integration testing.
396:             */
397:            private void loadTemplateForComponent(
398:                    ComponentPageElement loadingElement) {
399:                _loadingElement = loadingElement;
400:                _loadingComponentModel = loadingElement.getComponentResources()
401:                        .getComponentModel();
402:
403:                String componentClassName = _loadingComponentModel
404:                        .getComponentClassName();
405:                ComponentTemplate template = _templateSource.getTemplate(
406:                        _loadingComponentModel, _locale);
407:
408:                // When the template for a component is missing, we pretend it consists of just a RenderBody
409:                // phase. Missing is not an error ... many component simply do not have a template.
410:
411:                if (template.isMissing()) {
412:                    _loadingElement.addToTemplate(newRenderBodyElement());
413:                    return;
414:                }
415:
416:                // Pre-allocate ids to avoid later name collisions.
417:
418:                Log log = _loadingComponentModel.getLog();
419:
420:                // Don't have a case-insensitive Set, so we'll make due with a Map
421:                Map<String, Boolean> embeddedIds = newCaseInsensitiveMap();
422:
423:                for (String id : _loadingComponentModel
424:                        .getEmbeddedComponentIds())
425:                    embeddedIds.put(id, true);
426:
427:                _idAllocator.clear();
428:
429:                for (String id : template.getComponentIds()) {
430:                    _idAllocator.allocateId(id);
431:                    embeddedIds.remove(id);
432:                }
433:
434:                if (!embeddedIds.isEmpty())
435:                    log.error(ServicesMessages.embeddedComponentsNotInTemplate(
436:                            embeddedIds.keySet(), componentClassName));
437:
438:                _addAttributesAsComponentBindings = false;
439:
440:                // The outermost elements of the template belong in the loading component's template list,
441:                // not its body list. This shunt allows everyone else to not have to make that decision,
442:                // they can add to the "body" and (if there isn't an active component), the shunt will
443:                // add the element to the component's template.
444:
445:                BodyPageElement shunt = new BodyPageElement() {
446:                    public void addToBody(PageElement element) {
447:                        _loadingElement.addToTemplate(element);
448:                    }
449:                };
450:
451:                _bodyPageElementStack.push(shunt);
452:
453:                for (TemplateToken token : template.getTokens()) {
454:                    switch (token.getTokenType()) {
455:                    case TEXT:
456:                        text((TextToken) token);
457:                        break;
458:
459:                    case EXPANSION:
460:                        expansion((ExpansionToken) token);
461:                        break;
462:
463:                    case BODY:
464:                        body((BodyToken) token);
465:                        break;
466:
467:                    case START_ELEMENT:
468:                        startElement((StartElementToken) token);
469:                        break;
470:
471:                    case START_COMPONENT:
472:                        startComponent((StartComponentToken) token);
473:                        break;
474:
475:                    case ATTRIBUTE:
476:                        attribute((AttributeToken) token);
477:                        break;
478:
479:                    case END_ELEMENT:
480:                        endElement((EndElementToken) token);
481:                        break;
482:
483:                    case COMMENT:
484:                        comment((CommentToken) token);
485:                        break;
486:
487:                    case BLOCK:
488:                        block((BlockToken) token);
489:                        break;
490:
491:                    case PARAMETER:
492:                        parameter((ParameterToken) token);
493:                        break;
494:
495:                    case DTD:
496:                        dtd((DTDToken) token);
497:                        break;
498:
499:                    default:
500:                        throw new IllegalStateException("Not implemented yet: "
501:                                + token);
502:                    }
503:                }
504:
505:                // For neatness / symmetry:
506:
507:                _bodyPageElementStack.pop(); // the shunt
508:
509:                // TODO: Check that all stacks are empty. That should never happen, as long
510:                // as the ComponentTemplate is valid.
511:            }
512:
513:            private void parameter(ParameterToken token) {
514:                BlockImpl block = new BlockImpl(token.getLocation());
515:                String name = token.getName();
516:
517:                Binding binding = new LiteralBinding("block parameter " + name,
518:                        block, token.getLocation());
519:
520:                // TODO: Check that the t:parameter doesn't appear outside of an embedded component.
521:
522:                _activeElementStack.peek().bindParameter(name, binding);
523:
524:                setupBlock(block);
525:            }
526:
527:            private void setupBlock(BodyPageElement block) {
528:                _bodyPageElementStack.push(block);
529:
530:                Runnable cleanup = new Runnable() {
531:                    public void run() {
532:                        _bodyPageElementStack.pop();
533:                    }
534:                };
535:
536:                configureEnd(true, cleanup);
537:            }
538:
539:            private void block(BlockToken token) {
540:                // Don't use the page element factory here becauses we need something that is both Block and
541:                // BodyPageElement and don't want to use casts.
542:
543:                BlockImpl block = new BlockImpl(token.getLocation());
544:
545:                String id = token.getId();
546:
547:                if (id != null)
548:                    _loadingElement.addBlock(id, block);
549:
550:                setupBlock(block);
551:            }
552:
553:            private void startComponent(StartComponentToken token) {
554:                String elementName = token.getElementName();
555:
556:                // Initial guess: the type from the token (but this may be null in many cases).
557:                String embeddedType = token.getComponentType();
558:
559:                String embeddedId = token.getId();
560:
561:                String embeddedComponentClassName = null;
562:
563:                // We know that if embeddedId is null, embeddedType is not.
564:
565:                if (embeddedId == null)
566:                    embeddedId = generateEmbeddedId(embeddedType, _idAllocator);
567:
568:                EmbeddedComponentModel embeddedModel = _loadingComponentModel
569:                        .getEmbeddedComponentModel(embeddedId);
570:
571:                if (embeddedModel != null) {
572:                    String modelType = embeddedModel.getComponentType();
573:
574:                    if (isNonBlank(modelType) && embeddedType != null) {
575:                        Log log = _loadingComponentModel.getLog();
576:                        log.error(ServicesMessages.compTypeConflict(embeddedId,
577:                                embeddedType, modelType));
578:                    }
579:
580:                    embeddedType = modelType;
581:                    embeddedComponentClassName = embeddedModel
582:                            .getComponentClassName();
583:                }
584:
585:                if (isBlank(embeddedType)
586:                        && isBlank(embeddedComponentClassName))
587:                    throw new TapestryException(ServicesMessages
588:                            .noTypeForEmbeddedComponent(embeddedId,
589:                                    _loadingComponentModel
590:                                            .getComponentClassName()), token,
591:                            null);
592:
593:                ComponentPageElement newComponent = _pageElementFactory
594:                        .newComponentElement(_page, _loadingElement,
595:                                embeddedId, embeddedType,
596:                                embeddedComponentClassName, elementName, token
597:                                        .getLocation());
598:
599:                addMixinsToComponent(newComponent, embeddedModel, token
600:                        .getMixins());
601:
602:                Map<String, Binding> bindingMap = newMap();
603:                _componentIdToBindingMap.put(newComponent.getCompleteId(),
604:                        bindingMap);
605:
606:                if (embeddedModel != null)
607:                    bindParametersFromModel(embeddedModel, _loadingElement,
608:                            newComponent, bindingMap);
609:
610:                addToBody(newComponent);
611:
612:                // Remember to load the template for this new component
613:                _componentQueue.push(newComponent);
614:
615:                // Any attribute tokens that immediately follow should be
616:                // used to bind parameters.
617:
618:                _addAttributesAsComponentBindings = true;
619:
620:                // Any attributes (including component parameters) that come up belong on this component.
621:
622:                _activeElementStack.push(newComponent);
623:
624:                // Set things up so that content inside the component is added to the component's body.
625:
626:                _bodyPageElementStack.push(newComponent);
627:
628:                // And clean that up when the end element is reached.
629:
630:                Runnable cleanup = new Runnable() {
631:                    public void run() {
632:                        _activeElementStack.pop();
633:                        _bodyPageElementStack.pop();
634:                    }
635:                };
636:
637:                // The start tag is not added to the body of the component, so neither should
638:                // the end tag.
639:                configureEnd(true, cleanup);
640:            }
641:
642:            private void startElement(StartElementToken token) {
643:                PageElement element = _pageElementFactory
644:                        .newStartElement(token);
645:
646:                addToBody(element);
647:
648:                // Controls how attributes are interpretted.
649:                _addAttributesAsComponentBindings = false;
650:
651:                // Start will be matched by end:
652:
653:                // Do NOT discard the end tag; add it to the body.
654:
655:                configureEnd(false, NO_OP);
656:            }
657:
658:            private void text(TextToken token) {
659:                PageElement element = _pageElementFactory.newTextElement(token);
660:
661:                addToBody(element);
662:            }
663:
664:            private void dtd(DTDToken token) {
665:                // first DTD encountered wins.
666:                if (_dtdAdded)
667:                    return;
668:
669:                PageElement element = _pageElementFactory.newDTDElement(token);
670:                // since rendering via the markup writer is to the document tree,
671:                // we don't really care where this gets placed in the tree; the
672:                // DTDPageElement will set the dtd of the document directly, rather than
673:                // writing anything to the markup writer
674:                _page.getRootElement().addToTemplate(element);
675:
676:                _dtdAdded = true;
677:            }
678:
679:            /** Works the component queue, until exausted. */
680:            private void workComponentQueue() {
681:                while (!_componentQueue.isEmpty()) {
682:                    ComponentPageElement componentElement = _componentQueue
683:                            .pop();
684:
685:                    loadTemplateForComponent(componentElement);
686:                }
687:            }
688:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.