[ 
https://issues.apache.org/jira/browse/TILES-569?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13667507#comment-13667507
 ] 

Mck SembWever commented on TILES-569:
-------------------------------------

{quote}I've recently tried the OptionsRenderer suggested in this tutorial 
http://tech.finn.no/2012/07/25/the-ultimate-view-tiles-3/4/, but wasn't able to 
succeed. The defined attributes wasn't available for some reason.{quote}

Marc,
 please post this, with a little more info, on the users list and i'll give you 
the help you need to get things working as they should.
                
> Proposal for conditionals in tiles definitions
> ----------------------------------------------
>
>                 Key: TILES-569
>                 URL: https://issues.apache.org/jira/browse/TILES-569
>             Project: Tiles
>          Issue Type: Improvement
>          Components: tiles-core
>    Affects Versions: 3.0.1
>            Reporter: Marc Ewert
>
> Hi,
> I've recently tried the OptionsRenderer suggested in this tutorial 
> [http://tech.finn.no/2012/07/25/the-ultimate-view-tiles-3/4/], but wasn't 
> able to succeed. The defined attributes wasn't available for some reason.
> So I took the idea and implemented my own solution. Perhaps it's something 
> for the trunk? My syntax is as follows:
> {code}
> <tiles-definitions>
>       <definition name="main/*/*" template="/WEB-INF/tiles/_layout/main.jsp">
>           <put-attribute name="title" 
> value="/WEB-INF/tiles/[{1}/{2}|{1}|_common]/title.jsp"/>
>           <put-attribute name="navigation" 
> value="/WEB-INF/tiles/[{1}/{2}|{1}|_common]/navigation.jsp"/>
>           <put-attribute name="content" 
> value="/WEB-INF/tiles/[{1}/{2}|{1}|_common]/content.jsp"/>
>           <put-attribute name="footer" 
> value="/WEB-INF/tiles/[{1}/{2}|{1}|_common]/footer.jsp"/>
>           <put-attribute name="javaScript" 
> value="/WEB-INF/tiles/[{1}/{2}|{1}|_common]/javaScript.jsp"/>
>       </definition>
> </tiles-definitions>
> {code}
> The renderer searches for patterns like [opt_1|opt_2|...|opt_n] which may 
> occur several times in the value partameters. With a backtrack algorithm the 
> first matching valid path is searched and rendered.
> I like the compactness of the notation, no need for attribute lists, which 
> didn't function in my case.
> Here is my renderer implementation, perhaps you are interested in integrating 
> it. The path evaluation eventually has to be refactored. I don't know if 
> there is a more elegant way and how costly the current solution is. Perhaps 
> there has to be done some caching...
> {code}
> /**
>  * Renderer implementation supporting the notation "[CHOICE_1|...|CHOICE_n]" 
> in the paths.
>  * The first matching path replacement will be choosen. 
>  */
> public final class ChoiceRenderer implements Renderer {
>     private static final Pattern CHOICE_PATTERN = 
> Pattern.compile("\\[([^\\]]+)\\]");
>     private final Renderer renderer;
>     /**
>      * Creates a new instance wrapping the given renderer.
>      */
>     public ChoiceRenderer(Renderer renderer) {
>         this.renderer = renderer;
>     }
>     /**
>      * @see 
> org.apache.tiles.request.render.Renderer#isRenderable(java.lang.String, 
> org.apache.tiles.request.Request)
>      */
>     @Override
>     public boolean isRenderable(String path, Request request) {
>         // only the overall format is checked, so no extra handling here
>         return this.renderer.isRenderable(path, request);
>     }
>     /**
>      * @see org.apache.tiles.request.render.Renderer#render(java.lang.String, 
> org.apache.tiles.request.Request)
>      */
>     @Override
>     public void render(String path, Request request) throws IOException {
>         Matcher matcher = CHOICE_PATTERN.matcher(path);
>         List<String[]> groups = new ArrayList<String[]>();
>         StringBuffer sb = new StringBuffer();
>         while (matcher.find()) {
>             // adds a pattern to the resulting path, which will be replaced 
> by the
>             // available choices
>             matcher.appendReplacement(sb, "{[" + groups.size() + "]}");
>             groups.add(matcher.group(1).split("\\|"));
>         }
>         matcher.appendTail(sb);
>         if (groups.isEmpty()) {
>             this.renderer.render(path, request);
>         } else {
>             backtrackPaths(sb.toString(), request, groups, 0);
>         }
>     }
>     private String backtrackPaths(String pathPattern, Request request, 
> List<String[]> groups, int depth)
>             throws IOException {
>         String matchPath = null;
>         String[] parts = groups.get(depth);
>         for (int i = 0; i < parts.length; ++i) {
>             String path = pathPattern.replace("{[" + depth + "]}", parts[i]);
>             if (depth == groups.size() - 1) {
>                 if (isPathValid(path, request)) {
>                     // found the first matching choice
>                     this.renderer.render(path, request);
>                     matchPath = path;
>                     break;
>                 }
>             } else {
>                 matchPath = backtrackPaths(path, request, groups, depth + 1);
>             }
>         }
>         return matchPath;
>     }
>     // TODO should we use caching here?
>     private boolean isPathValid(String path, Request request) {
>         boolean rtn = false;
>         // apparently the corresponding Renderer method seems to check the
>         // path's format only
>         if (this.renderer.isRenderable(path, request)) {
>             try {
>                 rtn = request.getApplicationContext().getResource(path) != 
> null;
>             } catch (IllegalArgumentException e) {
>                 // TODO the javadoc states that null will be returned, but
>                 // instead of it an exception is thrown.
>                 // Seems to be a bug?!
>                 boolean throwException = true;
>                 if (e.getCause() instanceof FileNotFoundException) {
>                     FileNotFoundException fex = (FileNotFoundException) 
> e.getCause();
>                     throwException = fex.getMessage().indexOf(path) == -1;
>                 }
>                 if (throwException) {
>                     // seems to be a different reason as our searched path
>                     throw e;
>                 }
>             }
>         }
>         return rtn;
>     }
> }
> {code}

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

Reply via email to