You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@tiles.apache.org by "Mck SembWever (JIRA)" <ji...@apache.org> on 2013/05/27 09:12:23 UTC
[jira] [Commented] (TILES-569) Proposal for conditionals in tiles
definitions
[ 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