Source Code Cross Referenced for AutoLinkResolver.java in  » J2EE » wicket » org » apache » wicket » markup » resolver » 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 » J2EE » wicket » org.apache.wicket.markup.resolver 
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.wicket.markup.resolver;
018:
019:        import java.util.HashMap;
020:        import java.util.HashSet;
021:        import java.util.Map;
022:        import java.util.Set;
023:
024:        import org.apache.wicket.Component;
025:        import org.apache.wicket.MarkupContainer;
026:        import org.apache.wicket.Page;
027:        import org.apache.wicket.PageParameters;
028:        import org.apache.wicket.ResourceReference;
029:        import org.apache.wicket.application.IClassResolver;
030:        import org.apache.wicket.markup.ComponentTag;
031:        import org.apache.wicket.markup.MarkupStream;
032:        import org.apache.wicket.markup.html.PackageResource;
033:        import org.apache.wicket.markup.html.WebMarkupContainer;
034:        import org.apache.wicket.markup.html.link.BookmarkablePageLink;
035:        import org.apache.wicket.markup.html.link.ExternalLink;
036:        import org.apache.wicket.markup.parser.filter.WicketLinkTagHandler;
037:        import org.apache.wicket.protocol.http.RequestUtils;
038:        import org.apache.wicket.util.lang.Packages;
039:        import org.apache.wicket.util.string.Strings;
040:        import org.slf4j.Logger;
041:        import org.slf4j.LoggerFactory;
042:
043:        /**
044:         * The AutoLinkResolver is responsible to handle automatic link resolution. Tags
045:         * are marked "autolink" by the MarkupParser for all tags with href attribute,
046:         * such as anchor and link tags with no explicit wicket id. E.g. <a
047:         * href="Home.html">
048:         * <p>
049:         * If href points to a *.html file, a BookmarkablePageLink will automatically be
050:         * created, except for absolut paths, where an ExternalLink is created.
051:         * <p>
052:         * If href points to a *.html file, it resolves the given URL by searching for a
053:         * page class, either relative or absolute, specified by the href attribute of
054:         * the tag. If relative the href URL must be relative to the package containing
055:         * the associated page. An exception is thrown if no Page class was found.
056:         * <p>
057:         * If href is no *.html file a static reference to the resource is created.
058:         * 
059:         * @see org.apache.wicket.markup.parser.filter.WicketLinkTagHandler
060:         * 
061:         * @author Juergen Donnerstag
062:         * @author Eelco Hillenius
063:         */
064:        public final class AutoLinkResolver implements  IComponentResolver {
065:            /**
066:             * Abstract implementation that has a helper method for creating a resource
067:             * reference.
068:             */
069:            public static abstract class AbstractAutolinkResolverDelegate
070:                    implements  IAutolinkResolverDelegate {
071:                /**
072:                 * Creates a new auto component that references a package resource.
073:                 * 
074:                 * @param container
075:                 *            the parent container
076:                 * @param autoId
077:                 *            the automatically generated id for the auto component
078:                 * @param pathInfo
079:                 *            the path info object that contains information about the
080:                 *            link reference
081:                 * @param attribute
082:                 *            the attribute to replace the value of
083:                 * @return a new auto component or null if the path was absolute
084:                 */
085:                protected final Component newPackageResourceReferenceAutoComponent(
086:                        final MarkupContainer container, final String autoId,
087:                        final PathInfo pathInfo, final String attribute) {
088:                    if (!pathInfo.absolute) {
089:                        // Href is relative. Create a resource reference pointing at
090:                        // this file
091:
092:                        // <wicket:head> components are handled differently. We can
093:                        // not use the container, because it is the container the
094:                        // header has been added to (e.g. the Page). What we need
095:                        // however, is the component (e.g. a Panel) which
096:                        // contributed it.
097:                        Class clazz = container.getMarkupStream()
098:                                .getContainerClass();
099:
100:                        // However if the markup stream is a merged markup stream
101:                        // (inheritance),
102:                        // than we need the class of the markup file which contained the
103:                        // tag.
104:                        if (container.getMarkupStream().getTag()
105:                                .getMarkupClass() != null) {
106:                            clazz = container.getMarkupStream().getTag()
107:                                    .getMarkupClass();
108:                        }
109:
110:                        // Create the component implementing the link
111:                        ResourceReferenceAutolink autoLink = new ResourceReferenceAutolink(
112:                                autoId, clazz, pathInfo.reference, attribute);
113:                        if (autoLink.resourceReference != null) {
114:                            // if the resource reference is null, it means that it the
115:                            // reference was not found as a package resource
116:                            return autoLink;
117:                        }
118:                    }
119:                    // else we can't have absolute resource references, at least not at
120:                    // this time
121:
122:                    // fall back on default processing
123:                    return null;
124:                }
125:            }
126:
127:            /**
128:             * Autolink components delegate component resolution to their parent
129:             * components. Reason: autolink tags don't have wicket:id and users wouldn't
130:             * know where to add the component to.
131:             * 
132:             * @author Juergen Donnerstag
133:             */
134:            public final static class AutolinkBookmarkablePageLink extends
135:                    BookmarkablePageLink {
136:                private static final long serialVersionUID = 1L;
137:
138:                private final String anchor;
139:
140:                /**
141:                 * When using <wicket:link> to let Wicket lookup for pages and create
142:                 * the related links, it's not possible to change the "setAutoEnable"
143:                 * property, which defaults to true. This affects the prototype because,
144:                 * sometimes designers _want_ links to be enabled.
145:                 */
146:                public static boolean autoEnable = true;
147:
148:                /**
149:                 * Construct
150:                 * 
151:                 * @see BookmarkablePageLink#BookmarkablePageLink(String, Class,
152:                 *      PageParameters)
153:                 * 
154:                 * @param id
155:                 * @param pageClass
156:                 * @param parameters
157:                 * @param anchor
158:                 */
159:                public AutolinkBookmarkablePageLink(final String id,
160:                        final Class pageClass, final PageParameters parameters,
161:                        final String anchor) {
162:                    super (id, pageClass, parameters);
163:                    this .anchor = anchor;
164:                    setAutoEnable(autoEnable);
165:                }
166:
167:                /**
168:                 * @see org.apache.wicket.MarkupContainer#isTransparentResolver()
169:                 */
170:                public boolean isTransparentResolver() {
171:                    return true;
172:                }
173:
174:                /**
175:                 * 
176:                 * @see org.apache.wicket.markup.html.link.BookmarkablePageLink#getURL()
177:                 */
178:                protected CharSequence getURL() {
179:                    CharSequence url = super .getURL();
180:                    if (anchor != null) {
181:                        url = url + anchor;
182:                    }
183:
184:                    return url;
185:                }
186:            }
187:
188:            /**
189:             * Interface to delegate the actual resolving of auto components to.
190:             */
191:            public static interface IAutolinkResolverDelegate {
192:                /**
193:                 * Returns a new auto component based on the pathInfo object. The auto
194:                 * component must have the autoId assigned as it's id. Should return
195:                 * null in case the component could not be created as expected and the
196:                 * default resolving should take place.
197:                 * 
198:                 * @param container
199:                 *            the parent container
200:                 * @param autoId
201:                 *            the automatically generated id for the auto component
202:                 * @param pathInfo
203:                 *            the path info object that contains information about the
204:                 *            link reference
205:                 * @return a new auto component or null in case this method couldn't
206:                 *         resolve to a proper auto component
207:                 */
208:                Component newAutoComponent(final MarkupContainer container,
209:                        final String autoId, final PathInfo pathInfo);
210:            }
211:
212:            /**
213:             * Encapsulates different aspects of a path. For instance, the path
214:             * <code>org.apache.wicket.markup.html.tree.Tree/tree.css</code> has
215:             * extension <code>css</code>, is relative (absolute == true) and has no
216:             * page parameters.
217:             */
218:            public static final class PathInfo {
219:                /** whether the reference is absolute. */
220:                private final boolean absolute;
221:
222:                /** An optional anchor like #top */
223:                private final String anchor;
224:
225:                /** The extension if any. */
226:                private final String extension;
227:
228:                /** The optional page parameters. */
229:                private final PageParameters pageParameters;
230:
231:                /** The path exluding any parameters. */
232:                private final String path;
233:
234:                /** The original reference (e.g the full value of a href attribute). */
235:                private final String reference;
236:
237:                /**
238:                 * Construct.
239:                 * 
240:                 * @param reference
241:                 *            the original reference (e.g the full value of a href
242:                 *            attribute)
243:                 */
244:                public PathInfo(final String reference) {
245:                    this .reference = reference;
246:                    // If href contains URL query parameters ..
247:                    String infoPath;
248:                    // get the query string
249:                    int queryStringPos = reference.indexOf("?");
250:                    if (queryStringPos != -1) {
251:                        final String queryString = reference
252:                                .substring(queryStringPos + 1);
253:                        pageParameters = new PageParameters();
254:                        RequestUtils.decodeParameters(queryString,
255:                                pageParameters);
256:                        infoPath = reference.substring(0, queryStringPos);
257:                    } else {
258:                        pageParameters = null;
259:                        infoPath = reference;
260:                    }
261:
262:                    absolute = (infoPath.startsWith("/") || infoPath
263:                            .startsWith("\\"));
264:
265:                    // remove file extension, but remember it
266:                    String extension = null;
267:                    int pos = infoPath.lastIndexOf(".");
268:                    if (pos != -1) {
269:                        extension = infoPath.substring(pos + 1);
270:                        infoPath = infoPath.substring(0, pos);
271:                    }
272:
273:                    String anchor = null;
274:                    if (extension != null) {
275:                        pos = extension.indexOf('#');
276:                        if (pos != -1) {
277:                            anchor = extension.substring(pos);
278:                            extension = extension.substring(0, pos);
279:                        }
280:                    }
281:
282:                    path = infoPath;
283:                    this .extension = extension;
284:                    this .anchor = anchor;
285:                }
286:
287:                /**
288:                 * Gets the anchor (e.g. #top)
289:                 * 
290:                 * @return anchor
291:                 */
292:                public final String getAnchor() {
293:                    return anchor;
294:                }
295:
296:                /**
297:                 * Gets extension.
298:                 * 
299:                 * @return extension
300:                 */
301:                public final String getExtension() {
302:                    return extension;
303:                }
304:
305:                /**
306:                 * Gets pageParameters.
307:                 * 
308:                 * @return pageParameters
309:                 */
310:                public final PageParameters getPageParameters() {
311:                    return pageParameters;
312:                }
313:
314:                /**
315:                 * Gets path.
316:                 * 
317:                 * @return path
318:                 */
319:                public final String getPath() {
320:                    return path;
321:                }
322:
323:                /**
324:                 * Gets reference.
325:                 * 
326:                 * @return reference
327:                 */
328:                public final String getReference() {
329:                    return reference;
330:                }
331:
332:                /**
333:                 * Gets absolute.
334:                 * 
335:                 * @return absolute
336:                 */
337:                public final boolean isAbsolute() {
338:                    return absolute;
339:                }
340:            }
341:
342:            /**
343:             * Resolves to anchor/ link components.
344:             */
345:            private static final class AnchorResolverDelegate extends
346:                    AbstractAutolinkResolverDelegate {
347:                /** the attribute to fetch. */
348:                private static final String attribute = "href";
349:
350:                /**
351:                 * Set of supported extensions for creating bookmarkable page links.
352:                 * Anything that is not in this list will be handled as a resource
353:                 * reference.
354:                 */
355:                private final Set supportedPageExtensions = new HashSet(4);
356:
357:                /**
358:                 * Construct.
359:                 */
360:                public AnchorResolverDelegate() {
361:                    // Initialize supported list of file name extension which'll create
362:                    // bookmarkable pages
363:                    supportedPageExtensions.add("html");
364:                    supportedPageExtensions.add("xml");
365:                    supportedPageExtensions.add("wml");
366:                    supportedPageExtensions.add("svg");
367:                }
368:
369:                /**
370:                 * @see org.apache.wicket.markup.resolver.AutoLinkResolver.IAutolinkResolverDelegate#newAutoComponent(org.apache.wicket.MarkupContainer,
371:                 *      java.lang.String,
372:                 *      org.apache.wicket.markup.resolver.AutoLinkResolver.PathInfo)
373:                 */
374:                public Component newAutoComponent(
375:                        final MarkupContainer container, final String autoId,
376:                        PathInfo pathInfo) {
377:                    if ((pathInfo.extension != null)
378:                            && supportedPageExtensions
379:                                    .contains(pathInfo.extension)) {
380:                        // Obviously a href like href="myPkg.MyLabel.html" will do as
381:                        // well. Wicket will not throw an exception. It accepts it.
382:                        String infoPath = Strings.replaceAll(pathInfo.path,
383:                                "/", ".").toString();
384:
385:                        Page page = container.getPage();
386:                        final IClassResolver defaultClassResolver = page
387:                                .getApplication().getApplicationSettings()
388:                                .getClassResolver();
389:
390:                        String className;
391:                        if (!infoPath.startsWith(".")) {
392:                            // Href is relative. Resolve the url given relative to the
393:                            // current page
394:                            className = Packages.extractPackageName(page
395:                                    .getClass())
396:                                    + "." + infoPath;
397:                        } else {
398:                            // Href is absolute. If class with the same absolute path
399:                            // exists, use it. Else don't change the href.
400:                            className = infoPath.substring(1);
401:                        }
402:
403:                        try {
404:                            final Class clazz = defaultClassResolver
405:                                    .resolveClass(className);
406:                            return new AutolinkBookmarkablePageLink(autoId,
407:                                    clazz, pathInfo.pageParameters,
408:                                    pathInfo.anchor);
409:                        } catch (ClassNotFoundException ex) {
410:                            log.warn("Did not find corresponding java class: "
411:                                    + className);
412:                            // fall through
413:                        }
414:
415:                        // Make sure base markup pages (inheritance) are handled correct
416:                        MarkupContainer parentWithContainer = container;
417:                        if (container.getParent() != null) {
418:                            parentWithContainer = container
419:                                    .findParentWithAssociatedMarkup();
420:                        }
421:                        if ((parentWithContainer instanceof  Page)
422:                                && !infoPath.startsWith(".")
423:                                && page.getMarkupStream().isMergedMarkup()) {
424:                            Class clazz = container.getMarkupStream().getTag()
425:                                    .getMarkupClass();
426:                            if (clazz != null) {
427:                                // Href is relative. Resolve the url given relative to
428:                                // the current page
429:                                className = Packages.extractPackageName(clazz)
430:                                        + "." + infoPath;
431:
432:                                try {
433:                                    clazz = defaultClassResolver
434:                                            .resolveClass(className);
435:                                    return new AutolinkBookmarkablePageLink(
436:                                            autoId, clazz, pathInfo
437:                                                    .getPageParameters(),
438:                                            pathInfo.anchor);
439:                                } catch (ClassNotFoundException ex) {
440:                                    log
441:                                            .warn("Did not find corresponding java class: "
442:                                                    + className);
443:                                    // fall through
444:                                }
445:                            }
446:                        }
447:                    } else {
448:                        // not a registered type for bookmarkable pages; create a link
449:                        // to a resource instead
450:                        return newPackageResourceReferenceAutoComponent(
451:                                container, autoId, pathInfo, attribute);
452:                    }
453:
454:                    // fallthrough
455:                    return null;
456:                }
457:            }
458:
459:            /**
460:             * Autolink components delegate component resolution to their parent
461:             * components. Reason: autolink tags don't have wicket:id and users wouldn't
462:             * know where to add the component to.
463:             * 
464:             * @author Juergen Donnerstag
465:             */
466:            private final static class AutolinkExternalLink extends
467:                    ExternalLink {
468:                private static final long serialVersionUID = 1L;
469:
470:                /**
471:                 * Construct
472:                 * 
473:                 * @param id
474:                 * @param href
475:                 */
476:                public AutolinkExternalLink(final String id, final String href) {
477:                    super (id, href);
478:                }
479:
480:                /**
481:                 * @see org.apache.wicket.MarkupContainer#isTransparentResolver()
482:                 */
483:                public boolean isTransparentResolver() {
484:                    return true;
485:                }
486:            }
487:
488:            /**
489:             * Resolver that returns the proper attribute value from a component tag
490:             * reflecting a URL reference such as src or href.
491:             */
492:            private static interface ITagReferenceResolver {
493:                /**
494:                 * Gets the reference attribute value of the tag depending on the type
495:                 * of the tag. For instance, anchors use the <code>href</code>
496:                 * attribute but script and image references use the <code>src</code>
497:                 * attribute.
498:                 * 
499:                 * @param tag
500:                 *            The component tag. Not for modifcation.
501:                 * @return the tag value that constitutes the reference
502:                 */
503:                String getReference(final ComponentTag tag);
504:            }
505:
506:            /**
507:             * Autolink component that points to a {@link ResourceReference}. Autolink
508:             * component delegate component resolution to their parent components.
509:             * Reason: autolink tags don't have wicket:id and users wouldn't know where
510:             * to add the component to.
511:             */
512:            private final static class ResourceReferenceAutolink extends
513:                    WebMarkupContainer {
514:                private static final long serialVersionUID = 1L;
515:
516:                private final String attribute;
517:
518:                /** Resource reference */
519:                private final ResourceReference resourceReference;
520:
521:                /**
522:                 * @param id
523:                 * @param clazz
524:                 * @param href
525:                 * @param attribute
526:                 */
527:                public ResourceReferenceAutolink(final String id,
528:                        final Class clazz, final String href,
529:                        final String attribute) {
530:                    super (id);
531:
532:                    this .attribute = attribute;
533:                    // Check whether it is a valid resource reference
534:                    if (PackageResource.exists(clazz, href, getLocale(),
535:                            getStyle())) {
536:                        // Create the component implementing the link
537:                        resourceReference = new ResourceReference(clazz, href,
538:                                getLocale(), getStyle());
539:                    } else {
540:                        // The resource does not exist. Set to null and ignore when
541:                        // rendering.
542:                        resourceReference = null;
543:                    }
544:                }
545:
546:                /**
547:                 * @see org.apache.wicket.MarkupContainer#isTransparentResolver()
548:                 */
549:                public boolean isTransparentResolver() {
550:                    return true;
551:                }
552:
553:                /**
554:                 * Handles this link's tag.
555:                 * 
556:                 * @param tag
557:                 *            the component tag
558:                 * @see org.apache.wicket.Component#onComponentTag(ComponentTag)
559:                 */
560:                protected final void onComponentTag(final ComponentTag tag) {
561:                    // Default handling for tag
562:                    super .onComponentTag(tag);
563:
564:                    // only set the href attribute when the resource exists
565:                    if (resourceReference != null) {
566:                        // Set href to link to this link's linkClicked method
567:                        CharSequence url = getRequestCycle().urlFor(
568:                                resourceReference);
569:
570:                        // generate the href attribute
571:                        tag.put(attribute, Strings
572:                                .replaceAll(url, "&", "&amp;"));
573:                    }
574:                }
575:            }
576:
577:            /**
578:             * Resolves to {@link ResourceReference} link components. Typcically used
579:             * for header contributions like javascript and css files.
580:             */
581:            private static final class ResourceReferenceResolverDelegate extends
582:                    AbstractAutolinkResolverDelegate {
583:                private final String attribute;
584:
585:                /**
586:                 * Construct.
587:                 * 
588:                 * @param attribute
589:                 */
590:                public ResourceReferenceResolverDelegate(final String attribute) {
591:                    this .attribute = attribute;
592:                }
593:
594:                /**
595:                 * @see org.apache.wicket.markup.resolver.AutoLinkResolver.IAutolinkResolverDelegate#newAutoComponent(org.apache.wicket.MarkupContainer,
596:                 *      java.lang.String,
597:                 *      org.apache.wicket.markup.resolver.AutoLinkResolver.PathInfo)
598:                 */
599:                public Component newAutoComponent(
600:                        final MarkupContainer container, final String autoId,
601:                        final PathInfo pathInfo) {
602:                    return newPackageResourceReferenceAutoComponent(container,
603:                            autoId, pathInfo, attribute);
604:                }
605:            }
606:
607:            /**
608:             * Resolver object that returns the proper attribute value from component
609:             * tags.
610:             */
611:            private static final class TagReferenceResolver implements 
612:                    ITagReferenceResolver {
613:                /** the attribute to fetch. */
614:                private final String attribute;
615:
616:                /**
617:                 * Construct.
618:                 * 
619:                 * @param attribute
620:                 *            the attribute to fetch
621:                 */
622:                public TagReferenceResolver(final String attribute) {
623:                    this .attribute = attribute;
624:                }
625:
626:                /**
627:                 * Gets the reference attribute value of the tag depending on the type
628:                 * of the tag. For instance, anchors use the <code>href</code>
629:                 * attribute but script and image references use the <code>src</code>
630:                 * attribute.
631:                 * 
632:                 * @param tag
633:                 *            The component tag. Not for modifcation.
634:                 * @return the tag value that constitutes the reference
635:                 */
636:                public String getReference(final ComponentTag tag) {
637:                    return tag.getAttributes().getString(attribute);
638:                }
639:            }
640:
641:            /**
642:             * If no specific resolver is found, always use the href attribute for
643:             * references.
644:             */
645:            private static final TagReferenceResolver DEFAULT_ATTRIBUTE_RESOLVER = new TagReferenceResolver(
646:                    "href");
647:
648:            /** Logging */
649:            private static final Logger log = LoggerFactory
650:                    .getLogger(AutoLinkResolver.class);
651:
652:            private static final long serialVersionUID = 1L;
653:
654:            /**
655:             * Autolink resolver delegates for constructing new autolinks reference
656:             * keyed on tag name (such as &lt;script&gt; or &lt;a&gt;.
657:             */
658:            private final Map tagNameToAutolinkResolverDelegates = new HashMap();
659:
660:            /**
661:             * Resolver objects that know what attribute to read for getting the
662:             * reference keyed on tag name (such as &lt;script&gt; or &lt;a&gt;.
663:             */
664:            private final Map tagNameToTagReferenceResolvers = new HashMap();
665:
666:            /**
667:             * Construct.
668:             */
669:            public AutoLinkResolver() {
670:                // register tag reference resolvers
671:                TagReferenceResolver hrefTagReferenceResolver = new TagReferenceResolver(
672:                        "href");
673:                TagReferenceResolver srcTagReferenceResolver = new TagReferenceResolver(
674:                        "src");
675:                tagNameToTagReferenceResolvers.put("a",
676:                        hrefTagReferenceResolver);
677:                tagNameToTagReferenceResolvers.put("link",
678:                        hrefTagReferenceResolver);
679:                tagNameToTagReferenceResolvers.put("script",
680:                        srcTagReferenceResolver);
681:                tagNameToTagReferenceResolvers.put("img",
682:                        srcTagReferenceResolver);
683:
684:                // register autolink resolver delegates
685:                tagNameToAutolinkResolverDelegates.put("a",
686:                        new AnchorResolverDelegate());
687:                tagNameToAutolinkResolverDelegates.put("link",
688:                        new ResourceReferenceResolverDelegate("href"));
689:                tagNameToAutolinkResolverDelegates.put("script",
690:                        new ResourceReferenceResolverDelegate("src"));
691:                tagNameToAutolinkResolverDelegates.put("img",
692:                        new ResourceReferenceResolverDelegate("src"));
693:            }
694:
695:            /**
696:             * Register (add or replace) a new resolver with the tagName and
697:             * attributeName. The resolver will be invoked each time an appropriate tag
698:             * and attribute is found.
699:             * 
700:             * @param tagName
701:             *            The tag name
702:             * @param attributeName
703:             *            The attribute name
704:             * @param resolver
705:             *            Implements what to do based on the tag and the attribute
706:             */
707:            public final void addTagReferenceResolver(final String tagName,
708:                    final String attributeName,
709:                    final IAutolinkResolverDelegate resolver) {
710:                TagReferenceResolver tagReferenceResolver = new TagReferenceResolver(
711:                        attributeName);
712:                tagNameToTagReferenceResolvers.put(tagName,
713:                        tagReferenceResolver);
714:
715:                tagNameToAutolinkResolverDelegates.put(tagName, resolver);
716:            }
717:
718:            /**
719:             * Get the resolver registered for 'tagName'
720:             * 
721:             * @param tagName
722:             *            The tag's name
723:             * @return The resolver found. Null, if none registered
724:             */
725:            public final IAutolinkResolverDelegate getAutolinkResolverDelegate(
726:                    final String tagName) {
727:                return (IAutolinkResolverDelegate) tagNameToAutolinkResolverDelegates
728:                        .get(tagName);
729:            }
730:
731:            /**
732:             * Automatically creates a BookmarkablePageLink component.
733:             * 
734:             * @see org.apache.wicket.markup.resolver.IComponentResolver#resolve(MarkupContainer,
735:             *      MarkupStream, ComponentTag)
736:             * 
737:             * @param markupStream
738:             *            The current markupStream
739:             * @param tag
740:             *            The current component tag while parsing the markup
741:             * @param container
742:             *            The container parsing its markup
743:             * @return true, if componentId was handle by the resolver. False, otherwise
744:             */
745:            public final boolean resolve(final MarkupContainer container,
746:                    final MarkupStream markupStream, final ComponentTag tag) {
747:                // Must be marked as autolink tag
748:                if (tag.isAutolinkEnabled()) {
749:                    // Try to find the Page matching the href
750:                    // Note: to not use tag.getId() because it will be modified while
751:                    // resolving the link and hence the 2nd render will fail.
752:                    final Component link = resolveAutomaticLink(container,
753:                            WicketLinkTagHandler.AUTOLINK_ID, tag);
754:
755:                    // Add the link to the container
756:                    container.autoAdd(link, markupStream);
757:                    if (log.isDebugEnabled()) {
758:                        log.debug("Added autolink " + link);
759:                    }
760:
761:                    // Tell the container, we resolved the id
762:                    return true;
763:                }
764:
765:                // We were not able to resolve the id
766:                return false;
767:            }
768:
769:            /**
770:             * Resolves the given tag's page class and page parameters by parsing the
771:             * tag component name and then searching for a page class at the absolute or
772:             * relative URL specified by the href attribute of the tag.
773:             * <p>
774:             * None html references are treated similar.
775:             * 
776:             * @param container
777:             *            The container where the link is
778:             * @param id
779:             *            the name of the component
780:             * @param tag
781:             *            the component tag
782:             * @return A BookmarkablePageLink to handle the href
783:             */
784:            private final Component resolveAutomaticLink(
785:                    final MarkupContainer container, final String id,
786:                    final ComponentTag tag) {
787:                final Page page = container.getPage();
788:
789:                // Make the id (page-)unique
790:                final String autoId = id
791:                        + Integer.toString(page.getAutoIndex());
792:
793:                // get the tag name, which is something like 'a' or 'script'
794:                final String tagName = tag.getName();
795:
796:                // By setting the component name, the tag becomes a Wicket component
797:                // tag, which must have a associated Component.
798:                if (tag.getId() == null) {
799:                    tag.setId(autoId);
800:                    tag.setAutoComponentTag(true);
801:                }
802:
803:                // get the reference resolver
804:                ITagReferenceResolver referenceResolver = (ITagReferenceResolver) tagNameToTagReferenceResolvers
805:                        .get(tagName);
806:                if (referenceResolver == null) {
807:                    // fallback on default
808:                    referenceResolver = DEFAULT_ATTRIBUTE_RESOLVER;
809:                }
810:
811:                // get the reference, which is typically the value of e.g. a href or src
812:                // attribute
813:                String reference = referenceResolver.getReference(tag);
814:
815:                // create the path info object
816:                PathInfo pathInfo = new PathInfo(reference);
817:                // now get the resolver delegate
818:                IAutolinkResolverDelegate autolinkResolverDelegate = (IAutolinkResolverDelegate) tagNameToAutolinkResolverDelegates
819:                        .get(tagName);
820:                Component autoComponent = null;
821:                if (autolinkResolverDelegate != null) {
822:                    autoComponent = autolinkResolverDelegate.newAutoComponent(
823:                            container, autoId, pathInfo);
824:                }
825:
826:                if (autoComponent == null) {
827:                    // resolving didn't have the desired result or there was no delegate
828:                    // found; fallback on the default resolving which is a simple
829:                    // component that leaves the tag unchanged
830:                    autoComponent = new AutolinkExternalLink(autoId,
831:                            pathInfo.reference);
832:                }
833:
834:                return autoComponent;
835:            }
836:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.