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