package ca.uhn.fhir.narrative.template.tags; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import ca.uhn.fhir.narrative.template.nodes.LNode; class Cycle extends Tag { private static final String PREPEND = "\"'"; /* * Cycle is usually used within a loop to alternate * between values, like colors or DOM classes. */ @Override public Object render(Map<String, Object> context, LNode... nodes) { // The group-name is either the first token-expression, or if that is // null (indicating there is no name), give it the name PREPEND followed // by the number of expressions in the cycle-group. String groupName = nodes[0] == null ? PREPEND + (nodes.length - 1) : super.asString(nodes[0].render(context)); // Prepend a groupName with a single- and double quote as to not // let the groupName conflict with other variable assignments groupName = PREPEND + groupName; Object obj = context.remove(groupName); List<Object> elements = new ArrayList<Object>(); for (int i = 1; i < nodes.length; i++) { elements.add(nodes[i].render(context)); } CycleGroup group; if (obj == null) { group = new CycleGroup(elements.size()); } else { group = (CycleGroup) obj; } context.put(groupName, group); return group.next(elements); } private static class CycleGroup { private final int sizeFirstCycle; private int currentIndex; CycleGroup(int sizeFirstCycle) { this.sizeFirstCycle = sizeFirstCycle; this.currentIndex = 0; } Object next(List<Object> elements) { Object obj; if (currentIndex >= elements.size()) { obj = ""; } else { obj = elements.get(currentIndex); } currentIndex++; if (currentIndex == sizeFirstCycle) { currentIndex = 0; } return obj; } } }