001/* 002 * (C) Copyright 2006-2014 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: AbstractWidgetTypeHandler.java 28491 2008-01-04 19:04:30Z sfermigier $ 020 */ 021 022package org.nuxeo.ecm.platform.forms.layout.facelets.plugins; 023 024import java.io.IOException; 025import java.util.ArrayList; 026import java.util.List; 027import java.util.Map; 028 029import javax.faces.component.UIComponent; 030import javax.faces.view.facelets.CompositeFaceletHandler; 031import javax.faces.view.facelets.FaceletContext; 032import javax.faces.view.facelets.FaceletHandler; 033import javax.faces.view.facelets.TagAttribute; 034import javax.faces.view.facelets.TagAttributes; 035import javax.faces.view.facelets.TagConfig; 036import javax.faces.view.facelets.ValidatorHandler; 037 038import org.apache.commons.lang.StringUtils; 039import org.nuxeo.ecm.platform.forms.layout.api.BuiltinWidgetModes; 040import org.nuxeo.ecm.platform.forms.layout.api.Widget; 041import org.nuxeo.ecm.platform.forms.layout.api.exceptions.WidgetException; 042import org.nuxeo.ecm.platform.forms.layout.facelets.FaceletHandlerHelper; 043import org.nuxeo.ecm.platform.forms.layout.facelets.RenderVariables; 044import org.nuxeo.ecm.platform.forms.layout.facelets.WidgetTypeHandler; 045import org.nuxeo.ecm.platform.forms.layout.facelets.dev.WidgetTypeDevTagHandler; 046import org.nuxeo.ecm.platform.ui.web.tag.handler.LeafFaceletHandler; 047import org.nuxeo.ecm.platform.ui.web.tag.handler.TagConfigFactory; 048import org.nuxeo.ecm.platform.ui.web.validator.DocumentConstraintValidator; 049 050import com.sun.faces.facelets.tag.ui.InsertHandler; 051 052/** 053 * Abstract widget type handler. 054 * 055 * @author <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a> 056 */ 057public abstract class AbstractWidgetTypeHandler extends WidgetTypeHandler { 058 059 /** 060 * @since 6.0 061 */ 062 public static final String DEV_TEMPLATE_PROPERTY_NAME = "dev_template"; 063 064 /** 065 * @since 6.0 066 */ 067 public static final String DISABLE_DEV_PROPERTY_NAME = "disable_dev"; 068 069 protected final TagConfig tagConfig; 070 071 protected Map<String, String> properties; 072 073 protected Widget widget; 074 075 protected final TagAttribute widgetAttr; 076 077 public AbstractWidgetTypeHandler(TagConfig config) { 078 super(config); 079 tagConfig = config; 080 widgetAttr = getAttribute("widget"); 081 } 082 083 @Override 084 public void apply(FaceletContext ctx, UIComponent parent) throws IOException { 085 if (widget == null) { 086 // resolve widget attribute instead, useful for the runtime tag library 087 Widget wi = (Widget) widgetAttr.getObject(ctx, Widget.class); 088 if (wi != null) { 089 apply(ctx, parent, wi); 090 } 091 } else { 092 apply(ctx, parent, widget); 093 } 094 } 095 096 public abstract void apply(FaceletContext ctx, UIComponent parent, Widget widget) throws WidgetException, 097 IOException; 098 099 public FaceletHandler getDevFaceletHandler(TagConfig tagConfig, Widget widget) throws WidgetException { 100 if (Boolean.parseBoolean(getProperty(DISABLE_DEV_PROPERTY_NAME)) 101 || Boolean.parseBoolean((String) widget.getProperty(DISABLE_DEV_PROPERTY_NAME))) { 102 return null; 103 } 104 // lookup in the widget type configuration 105 String template = (String) widget.getProperty(DEV_TEMPLATE_PROPERTY_NAME); 106 if (StringUtils.isBlank(template)) { 107 template = getProperty(DEV_TEMPLATE_PROPERTY_NAME); 108 } 109 FaceletHandlerHelper helper = new FaceletHandlerHelper(tagConfig); 110 TagAttribute widgetAttr = helper.createAttribute("widget", 111 "#{" + RenderVariables.widgetVariables.widget.name() + "}"); 112 TagAttributes devWidgetAttributes; 113 if (StringUtils.isBlank(template)) { 114 devWidgetAttributes = FaceletHandlerHelper.getTagAttributes(widgetAttr); 115 } else { 116 devWidgetAttributes = FaceletHandlerHelper.getTagAttributes(widgetAttr, 117 helper.createAttribute("template", template)); 118 } 119 TagConfig devWidgetConfig = TagConfigFactory.createTagConfig(tagConfig, widget.getTagConfigId(), 120 devWidgetAttributes, new LeafFaceletHandler()); 121 return new WidgetTypeDevTagHandler(devWidgetConfig); 122 } 123 124 public String getProperty(String name) { 125 if (properties != null) { 126 return properties.get(name); 127 } 128 return null; 129 } 130 131 /** 132 * Helper method, throws an exception if property value is null. 133 */ 134 public String getRequiredProperty(String name) throws WidgetException { 135 String value = getProperty(name); 136 if (value == null) { 137 throw new WidgetException("Required property '" + name + "' is missing on widget type configuration"); 138 } 139 return value; 140 } 141 142 public void setProperties(Map<String, String> properties) { 143 this.properties = properties; 144 } 145 146 public void setWidget(Widget widget) { 147 this.widget = widget; 148 } 149 150 /** 151 * Returns sub handlers as computed from tag information. 152 * <p> 153 * Adds an sub insert handler slot named {@link RenderVariables.widgetTemplatingZones#inside_input_widget} when 154 * widget is in edit mode. 155 * <p> 156 * Adds an sub document constraint validator handler named {@link DocumentConstraintValidator#VALIDATOR_ID} when 157 * widget is in edit mode. 158 * <p> 159 * 160 * @since 6.0 161 */ 162 protected FaceletHandler getNextHandler(FaceletContext ctx, TagConfig tagConfig, Widget widget, 163 FaceletHandler[] subHandlers, FaceletHandlerHelper helper) { 164 boolean isEdit = BuiltinWidgetModes.EDIT.equals(widget.getMode()); 165 return getNextHandler(ctx, tagConfig, widget, subHandlers, helper, isEdit, isEdit); 166 } 167 168 /** 169 * Returns sub handlers as computed from tag information. 170 * <p> 171 * Adds an input slot if corresponding boolean parameter is true. 172 * <p> 173 * Adds an document constraint validator if corresponding boolean parameter is true. 174 * 175 * @since 7.2 176 */ 177 protected FaceletHandler getNextHandler(FaceletContext ctx, TagConfig tagConfig, Widget widget, 178 FaceletHandler[] subHandlers, FaceletHandlerHelper helper, boolean addInputSlot, 179 boolean addDocumentConstraintValidator) { 180 FaceletHandler leaf; 181 List<FaceletHandler> handlers = new ArrayList<>(); 182 if (nextHandler != null && !(nextHandler instanceof LeafFaceletHandler)) { 183 handlers.add(nextHandler); 184 } 185 if (subHandlers != null && subHandlers.length > 0) { 186 for (FaceletHandler fh : subHandlers) { 187 if (fh != null && !(fh instanceof LeafFaceletHandler)) { 188 handlers.add(fh); 189 } 190 } 191 } 192 if (addInputSlot) { 193 FaceletHandler slot = getInputSlotHandler(ctx, tagConfig, widget, subHandlers, helper); 194 if (slot != null) { 195 handlers.add(slot); 196 } 197 } 198 if (addDocumentConstraintValidator) { 199 FaceletHandler v = getDocumentConstraintValidatorHandler(ctx, tagConfig, widget, subHandlers, helper); 200 if (v != null) { 201 handlers.add(v); 202 } 203 } 204 if (handlers.size() == 0) { 205 leaf = new LeafFaceletHandler(); 206 } else { 207 leaf = new CompositeFaceletHandler(handlers.toArray(new FaceletHandler[] {})); 208 } 209 return leaf; 210 } 211 212 protected FaceletHandler getInputSlotHandler(FaceletContext ctx, TagConfig tagConfig, Widget widget, 213 FaceletHandler[] subHandlers, FaceletHandlerHelper helper) { 214 TagConfig config = TagConfigFactory.createTagConfig(tagConfig, tagConfig.getTagId(), 215 FaceletHandlerHelper.getTagAttributes(helper.createAttribute("name", 216 RenderVariables.widgetTemplatingZones.inside_input_widget.name())), new LeafFaceletHandler()); 217 return new InsertHandler(config); 218 } 219 220 protected FaceletHandler getDocumentConstraintValidatorHandler(FaceletContext ctx, TagConfig tagConfig, 221 Widget widget, FaceletHandler[] subHandlers, FaceletHandlerHelper helper) { 222 // XXX maybe take into account control on widget to handle sub properties validation (or not) 223 ValidatorHandler validator = helper.getValidateHandler(tagConfig.getTagId(), 224 FaceletHandlerHelper.getTagAttributes(), new LeafFaceletHandler(), 225 DocumentConstraintValidator.VALIDATOR_ID); 226 return validator; 227 } 228 229}