All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.myfaces.view.facelets.tag.composite.FacetHandler Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */
package org.apache.myfaces.view.facelets.tag.composite;

import java.beans.BeanDescriptor;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import jakarta.faces.application.ProjectStage;
import jakarta.faces.component.UIComponent;
import jakarta.faces.context.FacesContext;
import jakarta.faces.view.facelets.FaceletContext;
import jakarta.faces.view.facelets.TagAttribute;
import jakarta.faces.view.facelets.TagConfig;
import jakarta.faces.view.facelets.TagException;
import jakarta.faces.view.facelets.TagHandler;

import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletAttribute;
import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletTag;

/**
 * Define the facets used by this composite component.
 * 

* This tag is used inside composite:interface tag. All facets * should be saved under the key UIComponent.FACETS_KEY on the * bean descriptor map as a Map<String, PropertyDescriptor> *

* * @author Leonardo Uribe (latest modification by $Author$) * @version $Revision$ $Date$ */ @JSFFaceletTag(name="composite:facet") public class FacetHandler extends TagHandler implements InterfaceDescriptorCreator { private static final Logger log = Logger.getLogger(FacetHandler.class.getName()); /** * String array defining all standard attributes of this tag. * ATTENTION: this array MUST be sorted alphabetically in order to use binary search!! */ private static final String[] STANDARD_ATTRIBUTES_SORTED = new String[] { "displayName", "expert", "hidden", "name", "preferred", "required", "shortDescription" }; /** * */ @JSFFaceletAttribute(name="name", className="jakarta.el.ValueExpression", deferredValueType="java.lang.String") private final TagAttribute _name; /** * Only available if ProjectStage is Development. */ @JSFFaceletAttribute(name="displayName", className="jakarta.el.ValueExpression", deferredValueType="java.lang.String") private final TagAttribute _displayName; /** * Indicate if the attribute is required or not *

* Myfaces specific feature: this attribute is checked only if project stage is * not ProjectStage.Production when a composite component is created. *

*/ @JSFFaceletAttribute(name="required", className="jakarta.el.ValueExpression", deferredValueType="boolean") private final TagAttribute _required; /** * Only available if ProjectStage is Development. */ @JSFFaceletAttribute(name="preferred", className="jakarta.el.ValueExpression", deferredValueType="boolean") private final TagAttribute _preferred; /** * Only available if ProjectStage is Development. */ @JSFFaceletAttribute(name="expert", className="jakarta.el.ValueExpression", deferredValueType="boolean") private final TagAttribute _expert; /** * Only available if ProjectStage is Development. */ @JSFFaceletAttribute(name="shortDescription", className="jakarta.el.ValueExpression", deferredValueType="java.lang.String") private final TagAttribute _shortDescription; /** * The "hidden" flag is used to identify features that are intended only * for tool use, and which should not be exposed to humans. * Only available if ProjectStage is Development. */ @JSFFaceletAttribute(name="hidden", className="jakarta.el.ValueExpression", deferredValueType="boolean") protected final TagAttribute _hidden; /** * Check if the PropertyDescriptor instance created by this handler * can be cacheable or not. */ private boolean _cacheable; /** * Cached instance used by this component. Note here we have a * "racy single-check". If this field is used, it is supposed * the object cached by this handler is immutable, and this is * granted if all properties not saved as ValueExpression are * "literal". */ private PropertyDescriptor _propertyDescriptor; public FacetHandler(TagConfig config) { super(config); _name = getRequiredAttribute("name"); _displayName = getAttribute("displayName"); _required = getAttribute("required"); _preferred = getAttribute("preferred"); _expert = getAttribute("expert"); _shortDescription = getAttribute("shortDescription"); _hidden = getAttribute("hidden"); // We can reuse the same PropertyDescriptor only if the properties // that requires to be evaluated when apply (build view time) // occur are literal or null. Otherwise we need to create it. // Note that only if ProjectStage is Development, The "displayName", // "shortDescription", "expert", "hidden", and "preferred" attributes are exposed final boolean development = FacesContext.getCurrentInstance().isProjectStage(ProjectStage.Development); if (_name.isLiteral() && (!development || _areDevelopmentAttributesLiteral())) { // Unfortunately its not possible to create the required // PropertyDescriptor instance here, because there is no way // to get a FaceletContext to create ValueExpressions. It is // possible to create it if we not have set all this properties: // required and possible unspecified attributes. This prevents // the racy single-check. _cacheable = true; if (_required == null && !CompositeTagAttributeUtils.containsUnspecifiedAttributes(tag, STANDARD_ATTRIBUTES_SORTED)) { _propertyDescriptor = _createFacetPropertyDescriptor(development); } } else { _cacheable = false; } } /** * True if the "displayName", "shortDescription", "expert", "hidden", and * "preferred" attributes are either null or literal. * @return */ private boolean _areDevelopmentAttributesLiteral() { return CompositeTagAttributeUtils.areAttributesLiteral( _displayName, _shortDescription, _expert, _hidden, _preferred); } @SuppressWarnings("unchecked") @Override public void apply(FaceletContext ctx, UIComponent parent) throws IOException { CompositeComponentBeanInfo beanInfo = (CompositeComponentBeanInfo) parent.getAttributes().get(UIComponent.BEANINFO_KEY); if (beanInfo == null) { if (log.isLoggable(Level.SEVERE)) { log.severe("Cannot find composite bean descriptor UIComponent.BEANINFO_KEY "); } return; } BeanDescriptor beanDescriptor = beanInfo.getBeanDescriptor(); Map facetPropertyDescriptorMap = (Map) beanDescriptor.getValue(UIComponent.FACETS_KEY); if (facetPropertyDescriptorMap == null) { facetPropertyDescriptorMap = new HashMap<>(5); beanDescriptor.setValue(UIComponent.FACETS_KEY, facetPropertyDescriptorMap); } String facetName = _name.getValue(ctx); if (isCacheable()) { if (_propertyDescriptor == null) { _propertyDescriptor = _createFacetPropertyDescriptor(facetName, ctx); } facetPropertyDescriptorMap.put(facetName, _propertyDescriptor); } else { PropertyDescriptor facetDescriptor = _createFacetPropertyDescriptor(facetName, ctx); facetPropertyDescriptorMap.put(facetName, facetDescriptor); } nextHandler.apply(ctx, parent); } /** * This method could be called only if it is not necessary to set the following properties: * targets, default, required, methodSignature and type * * @return */ private PropertyDescriptor _createFacetPropertyDescriptor(boolean development) { try { CompositeComponentPropertyDescriptor facetPropertyDescriptor = new CompositeComponentPropertyDescriptor(_name.getValue()); // If ProjectStage is Development, The "displayName", "shortDescription", // "expert", "hidden", and "preferred" attributes are exposed if (development) { CompositeTagAttributeUtils.addDevelopmentAttributesLiteral(facetPropertyDescriptor, _displayName, _shortDescription, _expert, _hidden, _preferred); } // note that no unspecified attributes are handled here, because the current // tag does not contain any, otherwise this code would not have been called. return facetPropertyDescriptor; } catch (IntrospectionException e) { if (log.isLoggable(Level.SEVERE)) { log.log(Level.SEVERE, "Cannot create PropertyDescriptor for facet ",e); } throw new TagException(tag,e); } } private PropertyDescriptor _createFacetPropertyDescriptor(String facetName, FaceletContext ctx) throws TagException, IOException { try { CompositeComponentPropertyDescriptor facetPropertyDescriptor = new CompositeComponentPropertyDescriptor(facetName); if (_required != null) { facetPropertyDescriptor.setValue("required", _required.getValueExpression(ctx, Boolean.class)); } // If ProjectStage is Development, The "displayName", "shortDescription", // "expert", "hidden", and "preferred" attributes are exposed if (ctx.getFacesContext().isProjectStage(ProjectStage.Development)) { CompositeTagAttributeUtils.addDevelopmentAttributes(facetPropertyDescriptor, ctx, _displayName, _shortDescription, _expert, _hidden, _preferred); } // Any additional attributes are exposed as attributes accessible // from the getValue() and attributeNames() methods on FeatureDescriptor CompositeTagAttributeUtils.addUnspecifiedAttributes(facetPropertyDescriptor, tag, STANDARD_ATTRIBUTES_SORTED, ctx); return facetPropertyDescriptor; } catch (IntrospectionException e) { if (log.isLoggable(Level.SEVERE)) { log.log(Level.SEVERE, "Cannot create PropertyDescriptor for attribute ",e); } throw new TagException(tag,e); } } @Override public boolean isCacheable() { return _cacheable; } @Override public void setCacheable(boolean cacheable) { _cacheable = cacheable; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy