private CharSequence iterableContext(Iterable<?> context, Options options) throws IOException { if (options.isFalsy(context)) { return options.inverse(); } StringBuilder buffer = new StringBuilder(); Iterator<?> iterator = reverse(context); int index = 0; Context parent = options.context; while (iterator.hasNext()) { Object element = iterator.next(); boolean first = index == 0; boolean even = index % 2 == 0; boolean last = !iterator.hasNext(); Context current = Context.newContext(parent, element) .data("index", index) .data("first", first ? "first" : "") .data("last", last ? "last" : "") .data("odd", even ? "" : "odd") .data("even", even ? "even" : ""); buffer.append(options.fn(current)); index++; } return buffer; }
@SuppressWarnings("unchecked") @Override protected void merge(final Context context, final Writer writer) throws IOException { if (body == null) { return; } final String helperName; Helper<Object> helper = helper(name); Template template = body; final Object childContext; Context currentScope = context; if (helper == null) { childContext = transform(context.get(name)); if (inverted) { helperName = UnlessHelper.NAME; } else if (childContext instanceof Iterable) { helperName = EachHelper.NAME; } else if (childContext instanceof Boolean) { helperName = IfHelper.NAME; } else if (childContext instanceof Lambda) { helperName = WithHelper.NAME; template = Lambdas.compile( handlebars, (Lambda<Object, Object>) childContext, context, template, startDelimiter, endDelimiter); } else { helperName = WithHelper.NAME; currentScope = Context.newContext(context, childContext); } // A built-in helper might be override it. helper = handlebars.helper(helperName); } else { helperName = name; childContext = transform(determineContext(context)); } Options options = new Options.Builder(handlebars, helperName, TagType.SECTION, currentScope, template) .setInverse(inverse == null ? Template.EMPTY : inverse) .setParams(params(currentScope)) .setHash(hash(context)) .build(); options.data(Context.PARAM_SIZE, this.params.size()); CharSequence result = helper.apply(childContext, options); if (!isEmpty(result)) { writer.append(result); } }
private CharSequence hashContext(Object context, Options options) throws IOException { StringBuilder buffer = new StringBuilder(); Context parent = options.context; Iterator<Map.Entry<String, Object>> iterator = reverse(options.propertySet(context)); while (iterator.hasNext()) { Map.Entry<String, Object> entry = iterator.next(); Context current = Context.newContext(parent, entry.getValue()).data("key", entry.getKey()); buffer.append(options.fn(current)); } return buffer; }
@Override public CharSequence apply(final Object context, final Options options) throws IOException { if (context == null) { return null; } if (options.params.length <= 0) { return context.toString(); } Context ctx = Context.newBuilder(options.context, context).build(); Object lookup = ctx.get(options.param(0).toString()); if (lookup == null) { return null; } return lookup.toString(); }