TNodeRepeatMap extends TNode { @Override public void render(TRenderContext context) throws IOException { final Object modelValue = context.getModelValue(this.key); if (!(modelValue instanceof Map)) { if (modelValue == null) { String options = Joiner.on(", ").join(context.getAllModelKeys()); throw new TemplateException("There is no model item with the key: " + this.key + ". Options include: " + options); } else { throw new TemplateException( "Expected a map for (" + rowKeyName + ", " + rowValueName + ") in " + this.key + " but got a " + modelValue); } } @SuppressWarnings("unchecked") Map<String, Object> map = (Map) modelValue; if (map.isEmpty() && this.info.isDevMode()) { context.append("<!-- fmt-repeat: (").append(rowKeyName).append(", ").append(rowValueName).append(") in ").append(this.key) .append(" is empty -->"); } int i = 0; int size = map.size(); for (Map.Entry<String, Object> entry : map.entrySet()) { Map<String, Object> newModelMap = Maps.newHashMap(); newModelMap.put(this.rowKeyName, entry.getKey()); newModelMap.put(this.rowValueName, entry.getValue()); TNodeRepeatIter.addIndexInfo(newModelMap, i, size); TRenderContext childContext = context.childContext(newModelMap); if (!this.onlyChildren) { context.append("<").append(qName); attributes.render(childContext); context.append(">"); } for (TNode node : getChildren()) { node.render(childContext); } if (!this.onlyChildren) { end.render(childContext); } i++; } } TNodeRepeatMap(SystemInfo info, TextContentParser parser, boolean onlyChildren, String qName, Attributes attributes, String key, String rowKeyName, String rowValueName); @Override void render(TRenderContext context);  }
@Test public void testEmptyRender() throws Exception { final TNodeRepeatMap repeat = new TNodeRepeatMap(info, TextContentParserTest.createTestTextContentParser(), false, null, TNode.EMPTY_ATTRIBUTES, "map", "key", "value"); Map<String, Object> model = Collections.<String, Object>singletonMap("map", Collections.emptyMap()); final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); repeat.render(new TRenderContext(outputStream, model)); assertEquals("<!-- fmt-repeat: (key, value) in map is empty -->", outputStream.toString()); }