001/** 002 * Copyright 2005-2018 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.rice.krad.uif.freemarker; 017 018import java.util.Collections; 019 020import org.apache.log4j.Logger; 021import org.kuali.rice.krad.uif.component.Component; 022import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle; 023import org.kuali.rice.krad.uif.lifecycle.ViewLifecyclePhase; 024import org.kuali.rice.krad.uif.lifecycle.ViewLifecycleTaskBase; 025 026import freemarker.core.Environment; 027import freemarker.core.Macro; 028import freemarker.template.TemplateModel; 029 030/** 031 * Perform actual rendering on a component during the lifecycle. 032 * 033 * @author Kuali Rice Team (rice.collab@kuali.org) 034 */ 035public class RenderComponentTask extends ViewLifecycleTaskBase<Component> { 036 037 private static final Logger LOG = Logger.getLogger(RenderComponentTask.class); 038 039 /** 040 * Constructor. 041 * 042 * @param phase The render phase for the component. 043 */ 044 public RenderComponentTask() { 045 super(Component.class); 046 } 047 048 /** 049 * {@inheritDoc} 050 */ 051 @Override 052 protected void performLifecycleTask() { 053 Component component = (Component) getElementState().getElement(); 054 if (!component.isRender() || component.getTemplate() == null) { 055 return; 056 } 057 058 LifecycleRenderingContext renderingContext = ViewLifecycle.getRenderingContext(); 059 renderingContext.clearRenderingBuffer(); 060 061 renderingContext.importTemplate(component.getTemplate()); 062 063 for (String additionalTemplate : component.getAdditionalTemplates()) { 064 renderingContext.importTemplate(additionalTemplate); 065 } 066 067 try { 068 Environment env = renderingContext.getEnvironment(); 069 070 // Check for a single-arg macro, with the parameter name "component" 071 // defer for parent rendering if not found 072 Macro fmMacro = (Macro) env.getMainNamespace().get(component.getTemplateName()); 073 074 if (fmMacro == null) { 075 return; 076 } 077 078 String[] args = fmMacro.getArgumentNames(); 079 if (args == null || args.length != 1 || !component.getComponentTypeName().equals(args[0])) { 080 return; 081 } 082 083 FreeMarkerInlineRenderUtils.renderTemplate(env, component, 084 null, false, false, Collections.<String, TemplateModel> emptyMap()); 085 086 component.setRenderedHtmlOutput(renderingContext.getRenderedOutput()); 087 component.setSelfRendered(true); 088 } catch (Throwable e) { 089 if (ViewLifecycle.isStrict()) { 090 LOG.warn("Error rendering component during lifecycle phase " + getElementState() 091 + " falling back to higher level rendering", e); 092 } else if (ViewLifecycle.isTrace() && LOG.isDebugEnabled()) { 093 LOG.debug("component rendering failed during lifecycle phase " + getElementState() 094 + " falling back to higher level rendering", e); 095 } 096 } 097 098 } 099}