001/* 002 * (C) Copyright 2006-2007 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache 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.apache.org/licenses/LICENSE-2.0 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 * 016 * Contributors: 017 * <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a> 018 * 019 * $Id: LayoutRowWidgetTagHandler.java 30553 2008-02-24 15:51:31Z atchertchian $ 020 */ 021 022package org.nuxeo.ecm.platform.forms.layout.facelets; 023 024import java.io.IOException; 025import java.io.Serializable; 026import java.util.ArrayList; 027import java.util.HashMap; 028import java.util.List; 029import java.util.Map; 030 031import javax.el.ELException; 032import javax.el.ExpressionFactory; 033import javax.el.ValueExpression; 034import javax.faces.FacesException; 035import javax.faces.component.UIComponent; 036import javax.faces.view.facelets.FaceletContext; 037import javax.faces.view.facelets.FaceletException; 038import javax.faces.view.facelets.FaceletHandler; 039import javax.faces.view.facelets.TagAttribute; 040import javax.faces.view.facelets.TagConfig; 041import javax.faces.view.facelets.TagHandler; 042 043import org.apache.commons.logging.Log; 044import org.apache.commons.logging.LogFactory; 045import org.nuxeo.ecm.platform.forms.layout.api.LayoutRow; 046import org.nuxeo.ecm.platform.forms.layout.api.Widget; 047 048/** 049 * Layout widget recursion tag handler. 050 * <p> 051 * Iterates over a layout row widgets and apply next handlers as many times as needed. 052 * <p> 053 * Only works when used inside a tag using the {@link LayoutRowTagHandler}. 054 * 055 * @author <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a> 056 */ 057public class LayoutRowWidgetTagHandler extends TagHandler { 058 059 private static final Log log = LogFactory.getLog(LayoutRowWidgetTagHandler.class); 060 061 protected final TagConfig config; 062 063 /** 064 * @since 7.2 065 */ 066 protected final TagAttribute recomputeIds; 067 068 public LayoutRowWidgetTagHandler(TagConfig config) { 069 super(config); 070 this.config = config; 071 recomputeIds = getAttribute("recomputeIds"); 072 } 073 074 /** 075 * For each widget in current row, exposes widget variables and applies next handler. 076 * <p> 077 * Needs row to be exposed in context, so works in conjunction with {@link LayoutRowTagHandler}. 078 * <p> 079 * Widget variables exposed: {@link RenderVariables.widgetVariables#widget} , same variable suffixed with "_n" where 080 * n is the widget level, and {@link RenderVariables.widgetVariables#widgetIndex}. 081 */ 082 public void apply(FaceletContext ctx, UIComponent parent) throws IOException, FacesException, FaceletException, 083 ELException { 084 085 // resolve widgets from row in context 086 LayoutRow row = null; 087 String rowVariableName = RenderVariables.rowVariables.layoutRow.name(); 088 FaceletHandlerHelper helper = new FaceletHandlerHelper(config); 089 TagAttribute rowAttribute = helper.createAttribute(rowVariableName, "#{" + rowVariableName + "}"); 090 if (rowAttribute != null) { 091 row = (LayoutRow) rowAttribute.getObject(ctx, LayoutRow.class); 092 } 093 if (row == null) { 094 log.error("Could not resolve layout row " + rowAttribute); 095 return; 096 } 097 098 Widget[] widgets = row.getWidgets(); 099 if (widgets == null || widgets.length == 0) { 100 return; 101 } 102 103 boolean recomputeIdsBool = false; 104 if (recomputeIds != null) { 105 recomputeIdsBool = recomputeIds.getBoolean(ctx); 106 } 107 108 int widgetCounter = 0; 109 for (Widget widget : widgets) { 110 // set unique id on widget before exposing it to the context, but assumes iteration could be done several 111 // times => do not generate id again if already set, unless specified by attribute "recomputeIds" 112 if (widget != null && (widget.getId() == null || recomputeIdsBool)) { 113 WidgetTagHandler.generateWidgetId(ctx, helper, widget, false); 114 } 115 116 // expose widget variables 117 Map<String, ValueExpression> variables = new HashMap<String, ValueExpression>(); 118 ExpressionFactory eFactory = ctx.getExpressionFactory(); 119 ValueExpression widgetVe = eFactory.createValueExpression(widget, Widget.class); 120 variables.put(RenderVariables.widgetVariables.widget.name(), widgetVe); 121 Integer level = null; 122 String tagConfigId = null; 123 if (widget != null) { 124 level = Integer.valueOf(widget.getLevel()); 125 tagConfigId = widget.getTagConfigId(); 126 } 127 variables.put(RenderVariables.widgetVariables.widget.name() + "_" + level, widgetVe); 128 ValueExpression widgetIndexVe = eFactory.createValueExpression(Integer.valueOf(widgetCounter), 129 Integer.class); 130 variables.put(RenderVariables.widgetVariables.widgetIndex.name(), widgetIndexVe); 131 variables.put(RenderVariables.widgetVariables.widgetIndex.name() + "_" + level, widgetIndexVe); 132 133 // XXX: expose widget controls too, need to figure out 134 // why controls cannot be references to widget.controls like 135 // properties are in TemplateWidgetTypeHandler 136 if (widget != null) { 137 for (Map.Entry<String, Serializable> ctrl : widget.getControls().entrySet()) { 138 String key = ctrl.getKey(); 139 String name = RenderVariables.widgetVariables.widgetControl.name() + "_" + key; 140 Serializable value = ctrl.getValue(); 141 variables.put(name, eFactory.createValueExpression(value, Object.class)); 142 } 143 } 144 145 List<String> blockedPatterns = new ArrayList<String>(); 146 blockedPatterns.add(RenderVariables.widgetVariables.widget.name() + "*"); 147 blockedPatterns.add(RenderVariables.widgetVariables.widgetIndex.name() + "*"); 148 blockedPatterns.add(RenderVariables.widgetVariables.widgetControl.name() + "_*"); 149 150 FaceletHandler handler = helper.getAliasFaceletHandler(tagConfigId, variables, blockedPatterns, nextHandler); 151 152 // apply 153 handler.apply(ctx, parent); 154 widgetCounter++; 155 } 156 } 157}