/* * (C) Copyright 2006-2007 Nuxeo SAS (http://nuxeo.com/) and contributors. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Lesser General Public License * (LGPL) version 2.1 which accompanies this distribution, and is available at * http://www.gnu.org/licenses/lgpl.html * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * Contributors: * <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a> * * $Id: WebLayoutManagerImpl.java 28510 2008-01-06 10:21:44Z sfermigier $ */ package org.nuxeo.ecm.platform.forms.layout.service; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.el.ExpressionFactory; import javax.el.ValueExpression; import javax.el.VariableMapper; import javax.faces.view.facelets.ComponentHandler; import javax.faces.view.facelets.FaceletContext; import javax.faces.view.facelets.FaceletHandler; import javax.faces.view.facelets.TagConfig; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuxeo.ecm.platform.forms.layout.api.BuiltinModes; import org.nuxeo.ecm.platform.forms.layout.api.BuiltinWidgetModes; import org.nuxeo.ecm.platform.forms.layout.api.FieldDefinition; import org.nuxeo.ecm.platform.forms.layout.api.Layout; import org.nuxeo.ecm.platform.forms.layout.api.LayoutDefinition; import org.nuxeo.ecm.platform.forms.layout.api.LayoutRow; import org.nuxeo.ecm.platform.forms.layout.api.LayoutRowDefinition; import org.nuxeo.ecm.platform.forms.layout.api.LayoutTypeConfiguration; import org.nuxeo.ecm.platform.forms.layout.api.LayoutTypeDefinition; import org.nuxeo.ecm.platform.forms.layout.api.Widget; import org.nuxeo.ecm.platform.forms.layout.api.WidgetDefinition; import org.nuxeo.ecm.platform.forms.layout.api.WidgetReference; import org.nuxeo.ecm.platform.forms.layout.api.WidgetType; import org.nuxeo.ecm.platform.forms.layout.api.WidgetTypeConfiguration; import org.nuxeo.ecm.platform.forms.layout.api.WidgetTypeDefinition; import org.nuxeo.ecm.platform.forms.layout.api.exceptions.LayoutException; import org.nuxeo.ecm.platform.forms.layout.api.exceptions.WidgetException; import org.nuxeo.ecm.platform.forms.layout.api.impl.LayoutImpl; import org.nuxeo.ecm.platform.forms.layout.api.impl.LayoutRowComparator; import org.nuxeo.ecm.platform.forms.layout.api.impl.LayoutRowImpl; import org.nuxeo.ecm.platform.forms.layout.api.impl.WidgetDefinitionImpl; import org.nuxeo.ecm.platform.forms.layout.api.impl.WidgetImpl; import org.nuxeo.ecm.platform.forms.layout.api.impl.WidgetReferenceImpl; import org.nuxeo.ecm.platform.forms.layout.core.service.AbstractLayoutManager; import org.nuxeo.ecm.platform.forms.layout.core.service.LayoutStoreImpl; import org.nuxeo.ecm.platform.forms.layout.descriptors.LayoutDescriptor; import org.nuxeo.ecm.platform.forms.layout.descriptors.LayoutTypeDescriptor; import org.nuxeo.ecm.platform.forms.layout.descriptors.WidgetDescriptor; import org.nuxeo.ecm.platform.forms.layout.descriptors.WidgetTypeDescriptor; 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.DevTagHandler; import org.nuxeo.ecm.platform.forms.layout.functions.LayoutFunctions; import org.nuxeo.ecm.platform.ui.web.util.ComponentTagUtils; import org.nuxeo.runtime.api.Framework; import org.nuxeo.runtime.model.ComponentInstance; import org.nuxeo.runtime.model.ComponentName; import com.sun.faces.facelets.el.VariableMapperWrapper; /** * Layout service implementation. * * @author <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a> */ public class WebLayoutManagerImpl extends AbstractLayoutManager implements WebLayoutManager { public static final ComponentName NAME = new ComponentName( WebLayoutManagerImpl.class.getName()); private static final Log log = LogFactory.getLog(WebLayoutManagerImpl.class); private static final long serialVersionUID = 1L; public static final String WIDGET_TYPES_EP_NAME = LayoutStoreImpl.WIDGET_TYPES_EP_NAME; /** * @since 6.0 */ public static final String LAYOUT_TYPES_EP_NAME = LayoutStoreImpl.LAYOUT_TYPES_EP_NAME; public static final String WIDGETS_EP_NAME = LayoutStoreImpl.WIDGETS_EP_NAME; public static final String LAYOUTS_EP_NAME = LayoutStoreImpl.LAYOUTS_EP_NAME; public static final String PROPS_REF_EP_NAME = "disabledPropertyRefs"; protected DisabledPropertyRefRegistry disabledPropertyRefsReg; // Runtime component API public WebLayoutManagerImpl() { super(); disabledPropertyRefsReg = new DisabledPropertyRefRegistry(); } @Override public void registerContribution(Object contribution, String extensionPoint, ComponentInstance contributor) { if (extensionPoint.equals(WIDGET_TYPES_EP_NAME)) { registerWidgetType(((WidgetTypeDescriptor) contribution).getWidgetTypeDefinition()); } else if (extensionPoint.equals(LAYOUT_TYPES_EP_NAME)) { registerLayoutType(((LayoutTypeDescriptor) contribution).getLayoutTypeDefinition()); } else if (extensionPoint.equals(LAYOUTS_EP_NAME)) { registerLayout(((LayoutDescriptor) contribution).getLayoutDefinition()); } else if (extensionPoint.equals(WIDGETS_EP_NAME)) { registerWidget(((WidgetDescriptor) contribution).getWidgetDefinition()); } else if (extensionPoint.equals(PROPS_REF_EP_NAME)) { registerDisabledPropertyRef(((DisabledPropertyRefDescriptor) contribution)); } else { log.error(String.format( "Unknown extension point '%s', can't register !", extensionPoint)); } } @Override public void unregisterContribution(Object contribution, String extensionPoint, ComponentInstance contributor) { if (extensionPoint.equals(WIDGET_TYPES_EP_NAME)) { unregisterWidgetType(((WidgetTypeDescriptor) contribution).getWidgetTypeDefinition()); } else if (extensionPoint.equals(LAYOUT_TYPES_EP_NAME)) { unregisterLayoutType(((LayoutTypeDescriptor) contribution).getLayoutTypeDefinition()); } else if (extensionPoint.equals(LAYOUTS_EP_NAME)) { unregisterLayout(((LayoutDescriptor) contribution).getLayoutDefinition()); } else if (extensionPoint.equals(WIDGETS_EP_NAME)) { unregisterWidget(((WidgetDescriptor) contribution).getWidgetDefinition()); } else if (extensionPoint.equals(PROPS_REF_EP_NAME)) { unregisterDisabledPropertyRef(((DisabledPropertyRefDescriptor) contribution)); } else { log.error(String.format( "Unknown extension point '%s', can't unregister !", extensionPoint)); } } // specific API (depends on JSF impl) @Override public String getDefaultStoreCategory() { return JSF_CATEGORY; } protected String getStoreCategory(String cat) { if (StringUtils.isBlank(cat)) { return getDefaultStoreCategory(); } return cat; } @Override public WidgetTypeHandler getWidgetTypeHandler(String typeName) throws WidgetException { return getWidgetTypeHandler(getDefaultStoreCategory(), typeName); } @Override public WidgetTypeHandler getWidgetTypeHandler(String typeCategory, String typeName) throws WidgetException { if (StringUtils.isBlank(typeCategory)) { typeCategory = getDefaultStoreCategory(); } WidgetType type = getLayoutStore().getWidgetType(typeCategory, typeName); if (type == null) { return null; } WidgetTypeHandler handler; try { // Thread context loader is not working in isolated EARs handler = (WidgetTypeHandler) type.getWidgetTypeClass().newInstance(); } catch (Exception e) { log.error("Caught error when instanciating widget type handler", e); return null; } // set properties handler.setProperties(type.getProperties()); return handler; } /** * Evaluates an EL expression in given context. * <p> * If the expression resolves to an EL expression, evaluate it again this * is useful when retrieving the expression from a configuration file. * <p> * If given context is null, do no try to evaluate it and return the * expression itself. * * @param context the facelet context. * @param expression the string expression. */ protected static Object evaluateExpression(FaceletContext context, String expression) { if (expression == null) { return null; } if (context == null) { return expression; } Object value = ComponentTagUtils.resolveElExpression(context, expression); if (value != null && value instanceof String) { // evaluate a second time in case it's another EL expression value = ComponentTagUtils.resolveElExpression(context, (String) value); } return value; } /** * Evaluates an expression to a boolean value. */ protected static Boolean getBooleanValue(FaceletContext context, String expression) { Object value = evaluateExpression(context, expression); if (value instanceof Boolean) { return (Boolean) value; } else if (value == null || value instanceof String) { return Boolean.valueOf((String) value); } else { log.error(String.format("Could not get boolean value for '%s'", value)); return Boolean.FALSE; } } /** * Evaluates an expression to a string value. */ protected static String getStringValue(FaceletContext context, String expression) { Object value = evaluateExpression(context, expression); if (value == null || value instanceof String) { return (String) value; } else { log.error(String.format("Could not get string value for '%s'", value)); return null; } } protected static String getModeFromLayoutMode(FaceletContext context, WidgetDefinition wDef, String layoutMode) { String wMode = getStringValue(context, wDef.getMode(layoutMode)); if (wMode == null) { wMode = BuiltinModes.getWidgetModeFromLayoutMode(layoutMode); } return wMode; } @Override public Widget getWidget(FaceletContext ctx, String widgetName, String widgetCategory, String layoutMode, String valueName, String layoutName) { WidgetReference widgetRef = new WidgetReferenceImpl(widgetCategory, widgetName); WidgetDefinition wDef = lookupWidget(widgetRef); if (wDef != null) { return getWidget(ctx, layoutName, null, wDef, layoutMode, valueName, 0); } return null; } @Override public Widget getWidget(FaceletContext ctx, WidgetDefinition wDef, String layoutMode, String valueName, String layoutName) { if (wDef != null) { return getWidget(ctx, layoutName, null, wDef, layoutMode, valueName, 0); } return null; } /** * Computes a widget from a definition for a mode in a given context. * <p> * If the widget is configured not to be rendered in the given mode, * returns null. * <p> * Sub widgets are also computed recursively. */ @SuppressWarnings("deprecation") protected Widget getWidget(FaceletContext context, String layoutName, LayoutDefinition layoutDef, WidgetDefinition wDef, String layoutMode, String valueName, int level) { VariableMapper orig = null; // avoid variable mapper changes if context is null for tests if (context != null) { // expose widget mode so that it can be used in a mode el // expression orig = context.getVariableMapper(); VariableMapper vm = new VariableMapperWrapper(orig); context.setVariableMapper(vm); ExpressionFactory eFactory = context.getExpressionFactory(); ValueExpression modeVe = eFactory.createValueExpression(layoutMode, String.class); vm.setVariable(RenderVariables.globalVariables.mode.name(), modeVe); } String wMode = getModeFromLayoutMode(context, wDef, layoutMode); if (context != null) { context.setVariableMapper(orig); } if (BuiltinWidgetModes.HIDDEN.equals(wMode)) { return null; } List<Widget> subWidgets = new ArrayList<Widget>(); WidgetDefinition[] swDefs = wDef.getSubWidgetDefinitions(); if (swDefs != null) { for (WidgetDefinition swDef : swDefs) { Widget subWidget = getWidget(context, layoutName, layoutDef, swDef, wMode, valueName, level + 1); if (subWidget != null) { subWidgets.add(subWidget); } } } WidgetReference[] swRefs = wDef.getSubWidgetReferences(); if (swRefs != null) { for (WidgetReference swRef : swRefs) { WidgetDefinition swDef = lookupWidget(layoutDef, swRef); if (swDef == null) { log.error(String.format( "Widget '%s' not found in layout %s", swRef.getName(), layoutName)); } else { Widget subWidget = getWidget(context, layoutName, layoutDef, swDef, wMode, valueName, level + 1); if (subWidget != null) { subWidgets.add(subWidget); } } } } boolean required = getBooleanValue(context, wDef.getRequired(layoutMode, wMode)).booleanValue(); String wType = wDef.getType(); String wTypeCat = wDef.getTypeCategory(); // fill default property and control values from the widget definition Map<String, Serializable> props = new HashMap<String, Serializable>(); Map<String, Serializable> controls = new HashMap<String, Serializable>(); String actualWTypeCat = getStoreCategory(wTypeCat); WidgetTypeDefinition def = getLayoutStore().getWidgetTypeDefinition( actualWTypeCat, wType); WidgetTypeConfiguration conf = def != null ? def.getConfiguration() : null; if (conf != null) { Map<String, Serializable> defaultProps = conf.getDefaultPropertyValues(wMode); if (defaultProps != null && !defaultProps.isEmpty()) { props.putAll(defaultProps); } Map<String, Serializable> defaultControls = conf.getDefaultControlValues(wMode); if (defaultControls != null && !defaultControls.isEmpty()) { controls.putAll(defaultControls); } } props.putAll(wDef.getProperties(layoutMode, wMode)); controls.putAll(wDef.getControls(layoutMode, wMode)); WidgetImpl widget = new WidgetImpl(layoutName, wDef.getName(), wMode, wType, valueName, wDef.getFieldDefinitions(), wDef.getLabel(layoutMode), wDef.getHelpLabel(layoutMode), wDef.isTranslated(), wDef.isHandlingLabels(), props, required, subWidgets.toArray(new Widget[0]), level, wDef.getSelectOptions(), LayoutFunctions.computeWidgetDefinitionId(wDef), wDef.getRenderingInfos(layoutMode)); widget.setControls(controls); widget.setTypeCategory(actualWTypeCat); if (Framework.isDevModeSet()) { widget.setDefinition(wDef); } return widget; } @Override public Layout getLayout(FaceletContext ctx, String layoutName, String mode, String valueName) throws LayoutException { return getLayout(ctx, layoutName, mode, valueName, null, false); } @Override public Layout getLayout(FaceletContext ctx, String layoutName, String mode, String valueName, List<String> selectedRows, boolean selectAllRowsByDefault) { return getLayout(ctx, layoutName, null, mode, valueName, selectedRows, selectAllRowsByDefault); } @Override public Layout getLayout(FaceletContext ctx, String layoutName, String layoutCategory, String mode, String valueName, List<String> selectedRows, boolean selectAllRowsByDefault) { if (StringUtils.isBlank(layoutCategory)) { layoutCategory = getDefaultStoreCategory(); } LayoutDefinition layoutDef = getLayoutStore().getLayoutDefinition( layoutCategory, layoutName); if (layoutDef == null) { log.debug(String.format("Layout '%s' not found for category '%s'", layoutName, layoutCategory)); return null; } return getLayout(ctx, layoutDef, mode, valueName, selectedRows, selectAllRowsByDefault); } @Override public Layout getLayout(FaceletContext ctx, LayoutDefinition layoutDef, String mode, String valueName, List<String> selectedRows, boolean selectAllRowsByDefault) { if (layoutDef == null) { log.debug("Layout definition is null"); return null; } if (ctx == null) { log.warn("Layout creation computed in a null facelet context: expressions " + "found in the layout definition will not be evaluated"); } String layoutName = layoutDef.getName(); LayoutRowDefinition[] rowsDef = layoutDef.getRows(); List<LayoutRow> rows = new ArrayList<LayoutRow>(); Set<String> foundRowNames = new HashSet<String>(); int rowIndex = -1; for (LayoutRowDefinition rowDef : rowsDef) { rowIndex++; String rowName = rowDef.getName(); if (rowName == null) { rowName = rowDef.getDefaultName(rowIndex); if (selectedRows != null) { log.debug(String.format("Generating default name '%s' in " + "layout '%s' for row or column at index %s", rowName, layoutName, Integer.valueOf(rowIndex))); } } boolean emptyRow = true; if (selectedRows != null && !selectedRows.contains(rowName) && !rowDef.isAlwaysSelected()) { continue; } if (selectedRows == null && !selectAllRowsByDefault && !rowDef.isSelectedByDefault() && !rowDef.isAlwaysSelected()) { continue; } List<Widget> widgets = new ArrayList<Widget>(); for (WidgetReference widgetRef : rowDef.getWidgetReferences()) { String widgetName = widgetRef.getName(); if (widgetName == null || widgetName.length() == 0) { // no widget at this place widgets.add(null); continue; } WidgetDefinition wDef = lookupWidget(layoutDef, widgetRef); if (wDef == null) { log.error(String.format( "Widget '%s' not found in layout %s", widgetName, layoutName)); widgets.add(null); continue; } Widget widget = getWidget(ctx, layoutName, layoutDef, wDef, mode, valueName, 0); if (widget != null) { emptyRow = false; } widgets.add(widget); } if (!emptyRow) { rows.add(new LayoutRowImpl(rowName, rowDef.isSelectedByDefault(), rowDef.isAlwaysSelected(), widgets, rowDef.getProperties(mode), LayoutFunctions.computeLayoutRowDefinitionId(rowDef))); } foundRowNames.add(rowName); } if (selectedRows != null) { Collections.sort(rows, new LayoutRowComparator(selectedRows)); for (String selectedRow : selectedRows) { if (!foundRowNames.contains(selectedRow)) { log.debug(String.format( "Selected row or column named '%s' " + "was not found in layout '%s'", selectedRow, layoutName)); } } } String layoutTypeCategory = layoutDef.getTypeCategory(); String actualLayoutTypeCategory = getStoreCategory(layoutTypeCategory); LayoutTypeDefinition layoutTypeDef = null; String layoutType = layoutDef.getType(); if (!StringUtils.isBlank(layoutType)) { // retrieve type for templates and props mapping layoutTypeDef = getLayoutStore().getLayoutTypeDefinition( actualLayoutTypeCategory, layoutType); if (layoutTypeDef == null) { log.debug(String.format( "Layout type '%s' not found for category '%s'", layoutType, layoutTypeCategory)); } } String template = layoutDef.getTemplate(mode); Map<String, Serializable> props = new HashMap<>(); if (layoutTypeDef != null) { if (StringUtils.isEmpty(template)) { template = layoutTypeDef.getTemplate(mode); } LayoutTypeConfiguration conf = layoutTypeDef.getConfiguration(); if (conf != null) { Map<String, Serializable> typeProps = conf.getDefaultPropertyValues(mode); if (typeProps != null) { props.putAll(typeProps); } } } Map<String, Serializable> lprops = layoutDef.getProperties(mode); if (lprops != null) { props.putAll(lprops); } LayoutImpl layout = new LayoutImpl(layoutDef.getName(), mode, template, rows, layoutDef.getColumns(), props, LayoutFunctions.computeLayoutDefinitionId(layoutDef)); layout.setValueName(valueName); layout.setType(layoutType); layout.setTypeCategory(actualLayoutTypeCategory); if (Framework.isDevModeSet()) { layout.setDefinition(layoutDef); // resolve template in "dev" mode, avoiding default lookup on "any" // mode Map<String, String> templates = layoutDef.getTemplates(); String devTemplate = templates != null ? templates.get(BuiltinModes.DEV) : null; if (layoutTypeDef != null && StringUtils.isEmpty(devTemplate)) { Map<String, String> typeTemplates = layoutTypeDef.getTemplates(); devTemplate = typeTemplates != null ? typeTemplates.get(BuiltinModes.DEV) : null; } layout.setDevTemplate(devTemplate); } return layout; } protected WidgetDefinition lookupWidget(LayoutDefinition layoutDef, WidgetReference widgetRef) { String widgetName = widgetRef.getName(); WidgetDefinition wDef = null; if (layoutDef != null) { wDef = layoutDef.getWidgetDefinition(widgetName); } if (wDef == null) { // try in global registry wDef = lookupWidget(widgetRef); } return wDef; } protected WidgetDefinition lookupWidget(WidgetReference widgetRef) { String widgetName = widgetRef.getName(); String cat = widgetRef.getCategory(); WidgetDefinition wDef; if (StringUtils.isBlank(cat)) { wDef = getWidgetDefinition(widgetName); } else { wDef = getLayoutStore().getWidgetDefinition(cat, widgetName); } if (wDef != null) { wDef.setGlobal(true); } return wDef; } @Override public FaceletHandler getFaceletHandler(FaceletContext ctx, TagConfig config, Widget widget) { return getFaceletHandler(ctx, config, widget, null); } @Override public FaceletHandler getFaceletHandler(FaceletContext ctx, TagConfig config, Widget widget, FaceletHandler nextHandler) { String widgetTypeName = widget.getType(); String widgetTypeCategory = widget.getTypeCategory(); WidgetTypeHandler handler = getWidgetTypeHandler(widgetTypeCategory, widgetTypeName); if (handler == null) { FaceletHandlerHelper helper = new FaceletHandlerHelper(ctx, config); String message = String.format( "No widget handler found for type '%s' in category '%s'", widgetTypeName, widgetTypeCategory); log.error(message); ComponentHandler output = helper.getErrorComponentHandler(null, message); return output; } else { FaceletHandler[] subHandlers = null; Widget[] subWidgets = widget.getSubWidgets(); List<FaceletHandler> subHandlersList = new ArrayList<FaceletHandler>(); if (nextHandler != null) { subHandlersList.add(nextHandler); } if (subWidgets != null) { for (Widget subWidget : subWidgets) { FaceletHandler h = getFaceletHandler(ctx, config, subWidget, null); if (h != null) { subHandlersList.add(h); } } } if (!subHandlersList.isEmpty()) { subHandlers = subHandlersList.toArray(new FaceletHandler[0]); } FaceletHandler widgetHandler = handler.getFaceletHandler(ctx, config, widget, subHandlers); if (FaceletHandlerHelper.isDevModeEnabled(ctx)) { // decorate handler with dev handler FaceletHandlerHelper helper = new FaceletHandlerHelper(ctx, config); FaceletHandler devHandler = handler.getDevFaceletHandler(ctx, config, widget); if (devHandler == null) { return widgetHandler; } // expose the widget variable to sub dev handler String widgetTagConfigId = widget.getTagConfigId(); Map<String, ValueExpression> variables = new HashMap<String, ValueExpression>(); ExpressionFactory eFactory = ctx.getExpressionFactory(); ValueExpression widgetVe = eFactory.createValueExpression( widget, Widget.class); variables.put(RenderVariables.widgetVariables.widget.name(), widgetVe); List<String> blockedPatterns = new ArrayList<String>(); blockedPatterns.add(RenderVariables.widgetVariables.widget.name() + "*"); FaceletHandler devAliasHandler = helper.getAliasTagHandler( widgetTagConfigId, variables, blockedPatterns, devHandler); String refId = widget.getName(); FaceletHandler widgetDevHandler = new DevTagHandler(config, refId, widgetHandler, devAliasHandler); return widgetDevHandler; } return widgetHandler; } } @Override public Widget createWidget(FaceletContext ctx, String type, String mode, String valueName, Map<String, Serializable> properties, Widget[] subWidgets) { return createWidget(ctx, type, mode, valueName, null, null, null, null, properties, subWidgets); } @Override public Widget createWidget(FaceletContext ctx, String type, String mode, String valueName, List<FieldDefinition> fieldDefinitions, String label, String helpLabel, Boolean translated, Map<String, Serializable> properties, Widget[] subWidgets) { return createWidget( ctx, createWidgetDefinition(ctx, type, null, mode, valueName, fieldDefinitions, null, label, helpLabel, translated, properties, subWidgets), mode, valueName, subWidgets); } @Override public Widget createWidget(FaceletContext ctx, WidgetDefinition wDef, String mode, String valueName, Widget[] subWidgets) { String wType = wDef.getType(); String wTypeCat = wDef.getTypeCategory(); // fill default property and control values from the widget definition Map<String, Serializable> props = new HashMap<String, Serializable>(); Map<String, Serializable> controls = new HashMap<String, Serializable>(); String actualWTypeCat = getStoreCategory(wTypeCat); WidgetTypeDefinition def = getLayoutStore().getWidgetTypeDefinition( actualWTypeCat, wType); boolean required = false; WidgetTypeConfiguration conf = def != null ? def.getConfiguration() : null; if (conf != null) { Map<String, Serializable> defaultProps = conf.getDefaultPropertyValues(mode); if (defaultProps != null && !defaultProps.isEmpty()) { props.putAll(defaultProps); } Map<String, Serializable> defaultControls = conf.getDefaultControlValues(mode); if (defaultControls != null && !defaultControls.isEmpty()) { controls.putAll(defaultControls); } } Map<String, Serializable> modeProps = wDef.getProperties(mode, mode); if (modeProps != null) { props.putAll(modeProps); Serializable requiredProp = props.get(WidgetDefinition.REQUIRED_PROPERTY_NAME); if (requiredProp != null) { if (requiredProp instanceof Boolean) { required = ((Boolean) requiredProp).booleanValue(); } else if (requiredProp instanceof String) { required = getBooleanValue(ctx, (String) requiredProp).booleanValue(); } else { log.error(String.format( "Invalid property '%s' on widget: '%s'", WidgetDefinition.REQUIRED_PROPERTY_NAME, requiredProp)); } } } Map<String, Serializable> modeControls = wDef.getControls(mode, mode); if (modeControls != null) { controls.putAll(modeControls); } WidgetImpl widget = new WidgetImpl("layout", wDef.getName(), mode, wType, valueName, wDef.getFieldDefinitions(), wDef.getLabel(mode), wDef.getHelpLabel(mode), wDef.isTranslated(), props, required, subWidgets, 0, null, LayoutFunctions.computeWidgetDefinitionId(wDef)); widget.setControls(controls); widget.setTypeCategory(actualWTypeCat); widget.setDynamic(wDef.isDynamic()); widget.setGlobal(wDef.isGlobal()); if (Framework.isDevModeSet()) { widget.setDefinition(wDef); } return widget; } protected WidgetDefinition createWidgetDefinition(FaceletContext ctx, String type, String category, String mode, String valueName, List<FieldDefinition> fieldDefinitions, String widgetName, String label, String helpLabel, Boolean translated, Map<String, Serializable> properties, Widget[] subWidgets) { String wName = widgetName; if (StringUtils.isBlank(widgetName)) { wName = type; } WidgetDefinitionImpl wDef = new WidgetDefinitionImpl(wName, type, label, helpLabel, Boolean.TRUE.equals(translated), null, fieldDefinitions, properties, null); wDef.setDynamic(true); return wDef; } /** * @since 5.6 */ protected void registerDisabledPropertyRef( DisabledPropertyRefDescriptor desc) { disabledPropertyRefsReg.addContribution(desc); log.info(String.format( "Registered disabled property reference descriptor: %s", desc.toString())); } /** * @since 5.6 */ protected void unregisterDisabledPropertyRef( DisabledPropertyRefDescriptor desc) { disabledPropertyRefsReg.removeContribution(desc); log.info(String.format( "Removed disabled property reference descriptor: %s", desc.toString())); } @Override public boolean referencePropertyAsExpression(String name, Serializable value, String widgetType, String widgetMode, String template) { return referencePropertyAsExpression(name, value, widgetType, null, widgetMode, template); } @Override public boolean referencePropertyAsExpression(String name, Serializable value, String widgetType, String widgetTypeCategory, String widgetMode, String template) { if ((value instanceof String) && (ComponentTagUtils.isValueReference((String) value))) { return false; } String cat = widgetTypeCategory; if (widgetTypeCategory == null) { cat = WebLayoutManager.JSF_CATEGORY; } for (DisabledPropertyRefDescriptor desc : disabledPropertyRefsReg.getDisabledPropertyRefs()) { if (Boolean.TRUE.equals(desc.getEnabled()) && desc.matches(name, widgetType, cat, widgetMode, template)) { return false; } } return true; } }