/* * (C) Copyright 2006-2014 Nuxeo SA (http://nuxeo.com/) and others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Contributors: * <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a> * * $Id: AbstractWidgetTypeHandler.java 28491 2008-01-04 19:04:30Z sfermigier $ */ package org.nuxeo.ecm.platform.forms.layout.facelets.plugins; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.faces.component.UIComponent; import javax.faces.view.facelets.CompositeFaceletHandler; import javax.faces.view.facelets.FaceletContext; import javax.faces.view.facelets.FaceletHandler; import javax.faces.view.facelets.TagAttribute; import javax.faces.view.facelets.TagAttributes; import javax.faces.view.facelets.TagConfig; import javax.faces.view.facelets.ValidatorHandler; import org.apache.commons.lang.StringUtils; import org.nuxeo.ecm.core.api.validation.DocumentValidationService; import org.nuxeo.ecm.platform.forms.layout.api.BuiltinWidgetModes; import org.nuxeo.ecm.platform.forms.layout.api.Widget; import org.nuxeo.ecm.platform.forms.layout.api.exceptions.WidgetException; import org.nuxeo.ecm.platform.forms.layout.facelets.FaceletHandlerHelper; import org.nuxeo.ecm.platform.forms.layout.facelets.RenderVariables; import org.nuxeo.ecm.platform.forms.layout.facelets.WidgetTypeHandler; import org.nuxeo.ecm.platform.forms.layout.facelets.dev.WidgetTypeDevTagHandler; import org.nuxeo.ecm.platform.ui.web.tag.handler.LeafFaceletHandler; import org.nuxeo.ecm.platform.ui.web.tag.handler.TagConfigFactory; import org.nuxeo.ecm.platform.ui.web.validator.DocumentConstraintValidator; import org.nuxeo.runtime.api.Framework; import com.sun.faces.facelets.tag.ui.InsertHandler; /** * Abstract widget type handler. * * @author <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a> */ public abstract class AbstractWidgetTypeHandler extends WidgetTypeHandler { /** * @since 6.0 */ public static final String DEV_TEMPLATE_PROPERTY_NAME = "dev_template"; /** * @since 6.0 */ public static final String DISABLE_DEV_PROPERTY_NAME = "disable_dev"; protected final TagConfig tagConfig; protected Map<String, String> properties; protected Widget widget; protected final TagAttribute widgetAttr; public AbstractWidgetTypeHandler(TagConfig config) { super(config); tagConfig = config; widgetAttr = getAttribute("widget"); } @Override public void apply(FaceletContext ctx, UIComponent parent) throws IOException { if (widget == null) { // resolve widget attribute instead, useful for the runtime tag library Widget wi = (Widget) widgetAttr.getObject(ctx, Widget.class); if (wi != null) { apply(ctx, parent, wi); } } else { apply(ctx, parent, widget); } } public abstract void apply(FaceletContext ctx, UIComponent parent, Widget widget) throws WidgetException, IOException; public FaceletHandler getDevFaceletHandler(TagConfig tagConfig, Widget widget) throws WidgetException { if (Boolean.parseBoolean(getProperty(DISABLE_DEV_PROPERTY_NAME)) || Boolean.parseBoolean((String) widget.getProperty(DISABLE_DEV_PROPERTY_NAME))) { return null; } // lookup in the widget type configuration String template = (String) widget.getProperty(DEV_TEMPLATE_PROPERTY_NAME); if (StringUtils.isBlank(template)) { template = getProperty(DEV_TEMPLATE_PROPERTY_NAME); } FaceletHandlerHelper helper = new FaceletHandlerHelper(tagConfig); TagAttribute widgetAttr = helper.createAttribute("widget", "#{" + RenderVariables.widgetVariables.widget.name() + "}"); TagAttributes devWidgetAttributes; if (StringUtils.isBlank(template)) { devWidgetAttributes = FaceletHandlerHelper.getTagAttributes(widgetAttr); } else { devWidgetAttributes = FaceletHandlerHelper.getTagAttributes(widgetAttr, helper.createAttribute("template", template)); } TagConfig devWidgetConfig = TagConfigFactory.createTagConfig(tagConfig, widget.getTagConfigId(), devWidgetAttributes, new LeafFaceletHandler()); return new WidgetTypeDevTagHandler(devWidgetConfig); } public String getProperty(String name) { if (properties != null) { return properties.get(name); } return null; } /** * Helper method, throws an exception if property value is null. */ public String getRequiredProperty(String name) throws WidgetException { String value = getProperty(name); if (value == null) { throw new WidgetException("Required property '" + name + "' is missing on widget type configuration"); } return value; } public void setProperties(Map<String, String> properties) { this.properties = properties; } public void setWidget(Widget widget) { this.widget = widget; } /** * Returns sub handlers as computed from tag information. * <p> * Adds an sub insert handler slot named {@link RenderVariables.widgetTemplatingZones#inside_input_widget} when * widget is in edit mode. * <p> * Adds an sub document constraint validator handler named {@link DocumentConstraintValidator#VALIDATOR_ID} when * widget is in edit mode. * <p> * * @since 6.0 */ protected FaceletHandler getNextHandler(FaceletContext ctx, TagConfig tagConfig, Widget widget, FaceletHandler[] subHandlers, FaceletHandlerHelper helper) { boolean isEdit = BuiltinWidgetModes.EDIT.equals(widget.getMode()); return getNextHandler(ctx, tagConfig, widget, subHandlers, helper, isEdit, isEdit); } /** * Returns sub handlers as computed from tag information. * <p> * Adds an input slot if corresponding boolean parameter is true. * <p> * Adds an document constraint validator if corresponding boolean parameter is true. * * @since 7.2 */ protected FaceletHandler getNextHandler(FaceletContext ctx, TagConfig tagConfig, Widget widget, FaceletHandler[] subHandlers, FaceletHandlerHelper helper, boolean addInputSlot, boolean addDocumentConstraintValidator) { FaceletHandler leaf; List<FaceletHandler> handlers = new ArrayList<>(); if (nextHandler != null && !(nextHandler instanceof LeafFaceletHandler)) { handlers.add(nextHandler); } if (subHandlers != null && subHandlers.length > 0) { for (FaceletHandler fh : subHandlers) { if (fh != null && !(fh instanceof LeafFaceletHandler)) { handlers.add(fh); } } } if (addInputSlot) { FaceletHandler slot = getInputSlotHandler(ctx, tagConfig, widget, subHandlers, helper); if (slot != null) { handlers.add(slot); } } DocumentValidationService validationService = Framework.getService(DocumentValidationService.class); if (addDocumentConstraintValidator && validationService.isActivated(DocumentConstraintValidator.CTX_JSFVALIDATOR, null)) { FaceletHandler v = getDocumentConstraintValidatorHandler(ctx, tagConfig, widget, subHandlers, helper); if (v != null) { handlers.add(v); } } if (handlers.size() == 0) { leaf = new LeafFaceletHandler(); } else { leaf = new CompositeFaceletHandler(handlers.toArray(new FaceletHandler[] {})); } return leaf; } protected FaceletHandler getInputSlotHandler(FaceletContext ctx, TagConfig tagConfig, Widget widget, FaceletHandler[] subHandlers, FaceletHandlerHelper helper) { TagConfig config = TagConfigFactory.createTagConfig(tagConfig, tagConfig.getTagId(), FaceletHandlerHelper.getTagAttributes(helper.createAttribute("name", RenderVariables.widgetTemplatingZones.inside_input_widget.name())), new LeafFaceletHandler()); return new InsertHandler(config); } protected FaceletHandler getDocumentConstraintValidatorHandler(FaceletContext ctx, TagConfig tagConfig, Widget widget, FaceletHandler[] subHandlers, FaceletHandlerHelper helper) { // XXX maybe take into account control on widget to handle sub properties validation (or not) ValidatorHandler validator = helper.getValidateHandler(tagConfig.getTagId(), FaceletHandlerHelper.getTagAttributes(), new LeafFaceletHandler(), DocumentConstraintValidator.VALIDATOR_ID); return validator; } }