public void handleProcessAndRender(Map<Object, Object> parameterMap, Writer writer) { sectionsWithBackings = new HashMap<String, Set<TemplatedSection>>(); processingEvents = new HashMap<String, List<ProcessingEvent>>(); int lastHashCode = 0; // pass one may generate events for other backings to process recurseProcessSectionBackings(templateTree, parameterMap); // iteratively process events till none are thrown... while (processingEvents.size() > 0 && processingEvents.hashCode() != lastHashCode) { Map<String, List<ProcessingEvent>> originalEvents = processingEvents; lastHashCode = processingEvents.hashCode(); processingEvents = new HashMap<String, List<ProcessingEvent>>(); for (Map.Entry<String, List<ProcessingEvent>> entry : originalEvents.entrySet()) { if (sectionsWithBackings.get(entry.getKey()) != null) { Set<TemplatedSection> sections = sectionsWithBackings.get(entry.getKey()); for (TemplatedSection section : sections) { Map<Object, Object> vars = new HashMap<Object, Object>(); if (this.getTemplateVariables() != null) { vars.putAll(this.getTemplateVariables()); } if (section.getTemplateVariables() != null) { vars.putAll(section.getTemplateVariables()); } section.setTemplateVariables(vars); ProcessingContext context = new ProcessingContextImpl(); Collection<ProcessingEvent> newEvents = section .getSectionBacking() .processEvents(context, entry.getValue(), vars, parameterMap); // put the events in their appropriate target location if (newEvents != null) for (ProcessingEvent event : newEvents) { for (String targetName : event.getTargets()) { if (processingEvents.get(targetName) == null) processingEvents.put(targetName, new ArrayList<ProcessingEvent>()); processingEvents.get(targetName).add(event); } } } } } } try { templateTree.render(writer); } catch (TemplateException te) { throw new RuntimeException(te); } catch (IOException ioe) { throw new RuntimeException(ioe); } }
/** * Initial processing pass. Collections events and sections with backings as it goes. Events are * processed in the next pass. * * @param section * @param parameterMap */ private void recurseProcessSectionBackings( TemplatedSection section, Map<Object, Object> parameterMap) { Map<Object, Object> vars = new HashMap<Object, Object>(); if (this.getTemplateVariables() != null) { vars.putAll(this.getTemplateVariables()); } if (section.getTemplateVariables() != null) { vars.putAll(section.getTemplateVariables()); } section.setTemplateVariables(vars); if (section.getSectionBacking() != null) { ProcessingContext context = new ProcessingContextImpl(); TemplatedSectionBacking backing = section.getSectionBacking(); // as we process sections, we accumulate the sections that have backings // so that they may target each other in the events processing pass // the map is Map<Section,List<TemplatedSection>> List<String> targets = backing.getProcessingTargetIds(); if (targets != null) for (String target : targets) { if (sectionsWithBackings.get(target) == null) sectionsWithBackings.put(target, new HashSet<TemplatedSection>()); sectionsWithBackings.get(target).add(section); } Collection<ProcessingEvent> events = backing.process(context, vars, parameterMap); // put the events in their appropriate target location if (events != null && events.size() > 0) for (ProcessingEvent event : events) { for (String targetName : event.getTargets()) { if (processingEvents.get(targetName) == null) processingEvents.put(targetName, new ArrayList<ProcessingEvent>()); processingEvents.get(targetName).add(event); } } } // recurse up the template tree toward the leaf levels if (section.getChildren() != null) for (Object thisSection : section.getChildren().values().toArray()) recurseProcessSectionBackings((TemplatedSection) thisSection, parameterMap); }