001/* 002 * (C) Copyright 2006-2007 Nuxeo SAS (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a> 016 * 017 * $Id: SubWidgetTagHandler.java 30553 2008-02-24 15:51:31Z atchertchian $ 018 */ 019 020package org.nuxeo.ecm.platform.forms.layout.facelets; 021 022import java.io.IOException; 023import java.io.Serializable; 024import java.util.ArrayList; 025import java.util.HashMap; 026import java.util.List; 027import java.util.Map; 028 029import javax.el.ELException; 030import javax.el.ExpressionFactory; 031import javax.el.ValueExpression; 032import javax.faces.FacesException; 033import javax.faces.component.UIComponent; 034import javax.faces.view.facelets.FaceletContext; 035import javax.faces.view.facelets.FaceletHandler; 036import javax.faces.view.facelets.TagAttribute; 037import javax.faces.view.facelets.TagConfig; 038import javax.faces.view.facelets.TagHandler; 039 040import org.apache.commons.logging.Log; 041import org.apache.commons.logging.LogFactory; 042import org.nuxeo.ecm.platform.forms.layout.api.Widget; 043 044/** 045 * SubWidget tag handler. 046 * <p> 047 * Iterates over a widget subwidgets and apply next handlers as many times as needed. 048 * <p> 049 * Only works when used inside a tag using the {@link WidgetTagHandler}. 050 * 051 * @author <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a> 052 */ 053public class SubWidgetTagHandler extends TagHandler { 054 055 private static final Log log = LogFactory.getLog(SubWidgetTagHandler.class); 056 057 protected final TagConfig config; 058 059 /** 060 * @since 7.2 061 */ 062 protected final TagAttribute recomputeIds; 063 064 public SubWidgetTagHandler(TagConfig config) { 065 super(config); 066 this.config = config; 067 recomputeIds = getAttribute("recomputeIds"); 068 } 069 070 /** 071 * For each subwidget in current widget, exposes widget variables and applies next handler. 072 * <p> 073 * Needs widget to be exposed in context, so works in conjunction with {@link WidgetTagHandler}. 074 * <p> 075 * Widget variables exposed: {@link RenderVariables.widgetVariables#widget} , same variable suffixed with "_n" where 076 * n is the widget level, and {@link RenderVariables.widgetVariables#widgetIndex}. 077 */ 078 public void apply(FaceletContext ctx, UIComponent parent) throws IOException, FacesException, ELException { 079 // resolve subwidgets from widget in context 080 Widget widget = null; 081 String widgetVariableName = RenderVariables.widgetVariables.widget.name(); 082 FaceletHandlerHelper helper = new FaceletHandlerHelper(ctx, config); 083 TagAttribute widgetAttribute = helper.createAttribute(widgetVariableName, 084 String.format("#{%s}", widgetVariableName)); 085 if (widgetAttribute != null) { 086 widget = (Widget) widgetAttribute.getObject(ctx, Widget.class); 087 } 088 if (widget == null) { 089 log.error("Could not resolve widget " + widgetAttribute); 090 return; 091 } 092 093 Widget[] subWidgets = widget.getSubWidgets(); 094 if (subWidgets == null || subWidgets.length == 0) { 095 return; 096 } 097 098 boolean recomputeIdsBool = false; 099 if (recomputeIds != null) { 100 recomputeIdsBool = recomputeIds.getBoolean(ctx); 101 } 102 103 int subWidgetCounter = 0; 104 for (Widget subWidget : subWidgets) { 105 // set unique id on widget before exposing it to the context, but assumes iteration could be done several 106 // times => do not generate id again if already set, unless specified by attribute "recomputeIds" 107 if (subWidget != null && (subWidget.getId() == null || recomputeIdsBool)) { 108 WidgetTagHandler.generateWidgetId(helper, subWidget, false); 109 } 110 111 // expose widget variables 112 Map<String, ValueExpression> variables = new HashMap<String, ValueExpression>(); 113 ExpressionFactory eFactory = ctx.getExpressionFactory(); 114 ValueExpression subWidgetVe = eFactory.createValueExpression(subWidget, Widget.class); 115 Integer level = null; 116 String tagConfigId = null; 117 if (subWidget != null) { 118 level = Integer.valueOf(subWidget.getLevel()); 119 tagConfigId = subWidget.getTagConfigId(); 120 } 121 122 variables.put(RenderVariables.widgetVariables.widget.name(), subWidgetVe); 123 // variables.put(String.format("%s_%s", 124 // RenderVariables.widgetVariables.widget.name(), level), 125 // subWidgetVe); 126 ValueExpression subWidgetIndexVe = eFactory.createValueExpression(Integer.valueOf(subWidgetCounter), 127 Integer.class); 128 variables.put(RenderVariables.widgetVariables.widgetIndex.name(), subWidgetIndexVe); 129 variables.put(String.format("%s_%s", RenderVariables.widgetVariables.widgetIndex.name(), level), 130 subWidgetIndexVe); 131 132 // XXX: expose widget controls too, need to figure out 133 // why controls cannot be references to widget.controls like 134 // properties are in TemplateWidgetTypeHandler 135 if (subWidget != null) { 136 for (Map.Entry<String, Serializable> ctrl : subWidget.getControls().entrySet()) { 137 String key = ctrl.getKey(); 138 String name = String.format("%s_%s", RenderVariables.widgetVariables.widgetControl.name(), key); 139 Serializable value = ctrl.getValue(); 140 variables.put(name, eFactory.createValueExpression(value, Object.class)); 141 } 142 } 143 144 List<String> blockedPatterns = new ArrayList<String>(); 145 blockedPatterns.add(RenderVariables.widgetVariables.widget.name()); 146 blockedPatterns.add(RenderVariables.widgetVariables.widgetIndex.name() + "*"); 147 blockedPatterns.add(RenderVariables.widgetVariables.widgetControl.name() + "_*"); 148 149 FaceletHandler handlerWithVars = helper.getAliasTagHandler(tagConfigId, variables, blockedPatterns, 150 nextHandler); 151 152 // apply 153 handlerWithVars.apply(ctx, parent); 154 subWidgetCounter++; 155 } 156 } 157}