/* * Copyright 2015 Martin Kouba * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.trimou.handlebars; import org.trimou.engine.interpolation.BracketDotKeySplitter; import org.trimou.engine.interpolation.DotKeySplitter; import org.trimou.engine.interpolation.KeySplitter; import org.trimou.engine.interpolation.MissingValueHandler; import org.trimou.util.Strings; /** * Allows to build the key dynamically and evaluate it afterwards. * * <p> * First a key is built from the params, or rather their * {@link Object#toString()} representations, by default dot notation is used. * Then the helper attempts to find the value from the context. If the helper * represents a section and the value is not null the value is pushed on the * context stack and the section is rendered. If the helper represents a * variable and the value is null, the current {@link MissingValueHandler} is * used. If the helper represents a variable and the final value is not null the * the value's {@link Object#toString()} is rendered. * </p> * * <pre> * {{eval "foo" "bar"}} * </pre> * * is equivalent to: * * <pre> * {{foo.bar}} * </pre> * * On the other hand: * * <pre> * {{#eval "list" idx}} * Element name: {{name}} * {{/eval}} * </pre> * * is equivalent to (provided the idx evaluates to 1): * * <pre> * {{#with list.1}} * Element name: {{name}} * {{/with}} * </pre> * * @author Martin Kouba * @see Notation * @see KeySplitter */ public class EvalHelper extends BasicHelper { private final Notation notation; /** * * @see DotNotation */ public EvalHelper() { this(new DotNotation()); } /** * * @param notation The notation to be used when constructing keys */ public EvalHelper(Notation notation) { this.notation = notation; } @Override public void execute(Options options) { StringBuilder key = new StringBuilder(); for (final Object o : options.getParameters()) { notation.append(key, o.toString()); } Object value = options.getValue(key.toString()); if (isSection(options)) { if (value != null) { options.push(value); options.fn(); options.pop(); } } else { if (value == null) { value = configuration.getMissingValueHandler().handle( options.getTagInfo()); } if (value != null) { convertAndAppend(options, value); } } } public interface Notation { /** * Append the given part to the key builder. * * @param builder * @param part */ void append(StringBuilder builder, String part); } /** * * @author Martin Kouba * @see DotKeySplitter */ public static class DotNotation implements Notation { @Override public void append(StringBuilder builder, String part) { if (builder.length() > 0) { builder.append(Strings.DOT); } builder.append(part); } } /** * * @author Martin Kouba * @see BracketDotKeySplitter */ public static class BracketDotNotation implements Notation { @Override public void append(StringBuilder builder, String part) { if (builder.length() > 0) { builder.append("[\""); builder.append(part); builder.append("\"]"); } else { builder.append(part); } } } }