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: SubWidgetTagHandler.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.FaceletHandler; 038import javax.faces.view.facelets.TagAttribute; 039import javax.faces.view.facelets.TagConfig; 040import javax.faces.view.facelets.TagHandler; 041 042import org.apache.commons.logging.Log; 043import org.apache.commons.logging.LogFactory; 044import org.nuxeo.ecm.platform.forms.layout.api.Widget; 045 046/** 047 * SubWidget tag handler. 048 * <p> 049 * Iterates over a widget subwidgets and apply next handlers as many times as needed. 050 * <p> 051 * Only works when used inside a tag using the {@link WidgetTagHandler}. 052 * 053 * @author <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a> 054 */ 055public class SubWidgetTagHandler extends TagHandler { 056 057 private static final Log log = LogFactory.getLog(SubWidgetTagHandler.class); 058 059 protected final TagConfig config; 060 061 /** 062 * @since 7.2 063 */ 064 protected final TagAttribute recomputeIds; 065 066 public SubWidgetTagHandler(TagConfig config) { 067 super(config); 068 this.config = config; 069 recomputeIds = getAttribute("recomputeIds"); 070 } 071 072 /** 073 * For each subwidget in current widget, exposes widget variables and applies next handler. 074 * <p> 075 * Needs widget to be exposed in context, so works in conjunction with {@link WidgetTagHandler}. 076 * <p> 077 * Widget variables exposed: {@link RenderVariables.widgetVariables#widget} , same variable suffixed with "_n" where 078 * n is the widget level, and {@link RenderVariables.widgetVariables#widgetIndex}. 079 */ 080 public void apply(FaceletContext ctx, UIComponent parent) throws IOException, FacesException, ELException { 081 // resolve subwidgets from widget in context 082 Widget widget = null; 083 String widgetVariableName = RenderVariables.widgetVariables.widget.name(); 084 FaceletHandlerHelper helper = new FaceletHandlerHelper(config); 085 TagAttribute widgetAttribute = helper.createAttribute(widgetVariableName, "#{" + widgetVariableName + "}"); 086 if (widgetAttribute != null) { 087 widget = (Widget) widgetAttribute.getObject(ctx, Widget.class); 088 } 089 if (widget == null) { 090 log.error("Could not resolve widget " + widgetAttribute); 091 return; 092 } 093 094 Widget[] subWidgets = widget.getSubWidgets(); 095 if (subWidgets == null || subWidgets.length == 0) { 096 return; 097 } 098 099 boolean recomputeIdsBool = false; 100 if (recomputeIds != null) { 101 recomputeIdsBool = recomputeIds.getBoolean(ctx); 102 } 103 104 int subWidgetCounter = 0; 105 for (Widget subWidget : subWidgets) { 106 // set unique id on widget before exposing it to the context, but assumes iteration could be done several 107 // times => do not generate id again if already set, unless specified by attribute "recomputeIds" 108 if (subWidget != null && (subWidget.getId() == null || recomputeIdsBool)) { 109 WidgetTagHandler.generateWidgetId(ctx, helper, subWidget, false); 110 } 111 112 // expose widget variables 113 Map<String, ValueExpression> variables = new HashMap<String, ValueExpression>(); 114 ExpressionFactory eFactory = ctx.getExpressionFactory(); 115 ValueExpression subWidgetVe = eFactory.createValueExpression(subWidget, Widget.class); 116 Integer level = null; 117 String tagConfigId = null; 118 if (subWidget != null) { 119 level = Integer.valueOf(subWidget.getLevel()); 120 tagConfigId = subWidget.getTagConfigId(); 121 } 122 123 variables.put(RenderVariables.widgetVariables.widget.name(), subWidgetVe); 124 // variables.put(String.format("%s_%s", 125 // RenderVariables.widgetVariables.widget.name(), level), 126 // subWidgetVe); 127 ValueExpression subWidgetIndexVe = eFactory.createValueExpression(Integer.valueOf(subWidgetCounter), 128 Integer.class); 129 variables.put(RenderVariables.widgetVariables.widgetIndex.name(), subWidgetIndexVe); 130 variables.put(RenderVariables.widgetVariables.widgetIndex.name() + "_" + level, 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 = 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.getAliasFaceletHandler(tagConfigId, variables, blockedPatterns, 150 nextHandler); 151 152 // apply 153 handlerWithVars.apply(ctx, parent); 154 subWidgetCounter++; 155 } 156 } 157}