| /* |
| * 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 javax.faces.component; |
| |
| import org.apache.myfaces.core.api.shared._ComponentUtils; |
| import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent; |
| import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFJspProperty; |
| import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty; |
| |
| import javax.el.ValueExpression; |
| import javax.faces.FacesException; |
| import javax.faces.component.behavior.Behavior; |
| import javax.faces.component.behavior.ClientBehavior; |
| import javax.faces.component.visit.VisitCallback; |
| import javax.faces.component.visit.VisitContext; |
| import javax.faces.context.FacesContext; |
| import javax.faces.event.AbortProcessingException; |
| import javax.faces.event.BehaviorEvent; |
| import javax.faces.event.FacesEvent; |
| import javax.faces.event.FacesListener; |
| import javax.faces.event.PostAddToViewEvent; |
| import javax.faces.event.PostValidateEvent; |
| import javax.faces.event.PreRemoveFromViewEvent; |
| import javax.faces.event.PreRenderComponentEvent; |
| import javax.faces.event.PreValidateEvent; |
| import javax.faces.event.SystemEvent; |
| import javax.faces.event.SystemEventListener; |
| import javax.faces.render.RenderKit; |
| import javax.faces.render.Renderer; |
| import javax.faces.view.Location; |
| import java.io.IOException; |
| import java.io.Serializable; |
| import java.lang.reflect.Array; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.logging.Logger; |
| import javax.faces.event.PhaseId; |
| |
| |
| /** |
| * Standard implementation of the UIComponent base class; all standard JSF components extend this class. |
| * <p> |
| * <i>Disclaimer</i>: The official definition for the behaviour of this class is the JSF 1.1 specification but for legal |
| * reasons the specification cannot be replicated here. Any javadoc here therefore describes the current implementation |
| * rather than the spec, though this class has been verified as correctly implementing the spec. |
| * |
| * see Javadoc of <a href="http://java.sun.com/javaee/javaserverfaces/1.2/docs/api/index.html">JSF Specification</a> for |
| * more. |
| */ |
| @JSFComponent(type = "javax.faces.ComponentBase", family = "javax.faces.ComponentBase", |
| desc = "base component when all components must inherit", |
| tagClass = "javax.faces.webapp.UIComponentELTag", configExcluded = true) |
| @JSFJspProperty(name = "binding", returnType = "javax.faces.component.UIComponent", |
| longDesc = "Identifies a backing bean property (of type UIComponent or appropriate subclass) to bind " |
| + "to this component instance. This value must be an EL expression.", |
| desc = "backing bean property to bind to this component instance") |
| public abstract class UIComponentBase extends UIComponent |
| { |
| private static Logger log = Logger.getLogger(UIComponentBase.class.getName()); |
| |
| private static final String _STRING_BUILDER_KEY |
| = "javax.faces.component.UIComponentBase.SHARED_STRING_BUILDER"; |
| |
| // See ViewPoolProcessor for comments and usages |
| static final int RESET_MODE_OFF = 0; |
| static final int RESET_MODE_SOFT = 1; |
| static final int RESET_MODE_HARD = 2; |
| |
| private _ComponentAttributesMap _attributesMap = null; |
| private _PassThroughAttributesMap _passthroughAttributesMap = null; |
| private List<UIComponent> _childrenList = null; |
| private Map<String, UIComponent> _facetMap = null; |
| private _DeltaList<FacesListener> _facesListeners = null; |
| private String _clientId = null; |
| private String _id = null; |
| private UIComponent _parent = null; |
| private boolean _transient = false; |
| |
| private String _rendererType; |
| private String _markCreated; |
| private String _facetName; |
| |
| private int _capabilities = 0; |
| private final static int FLAG_IS_RENDERER_TYPE_SET = 1; |
| private final static int FLAG_ADDED_BY_HANDLER = 2; |
| private final static int FLAG_FACET_CREATED_UIPANEL = 4; |
| private final static int FLAG_PASSTHROUGH_ATTRIBUTE_MAP_SET = 8; |
| |
| /** |
| * This map holds ClientBehavior instances. |
| * |
| * Note that BehaviorBase implements PartialStateHolder, so this class |
| * should deal with that fact on clearInitialState() and |
| * markInitialState() methods. |
| * |
| * Also, the map used by this instance is not set from outside this class. |
| * |
| * Note it is possible (but maybe not expected/valid) to manipulate |
| * the values of the map(the list) but not put instances on the map |
| * directly, because ClientBehaviorHolder.getClientBehaviors says that |
| * this method should return a non null unmodificable map. |
| * |
| */ |
| private Map<String, List<ClientBehavior>> _behaviorsMap = null; |
| private transient Map<String, List<ClientBehavior>> _unmodifiableBehaviorsMap = null; |
| |
| private transient FacesContext _facesContext; |
| private transient Boolean _cachedIsRendered; |
| private transient Renderer _cachedRenderer; |
| |
| public UIComponentBase() |
| { |
| } |
| |
| /** |
| * Set an identifier for this component which is unique within the scope of the nearest ancestor NamingContainer |
| * component. The id is not necessarily unique across all components in the current view. |
| * <p> |
| * The id must start with an underscore if it is generated by the JSF framework, and must <i>not</i> start with an |
| * underscore if it has been specified by the user (eg in a JSP tag). |
| * <p> |
| * The first character of the id must be an underscore or letter. Following characters may be letters, digits, |
| * underscores or dashes. |
| * <p> |
| * Null is allowed as a parameter, and will reset the id to null. |
| * <p> |
| * The clientId of this component is reset by this method; see getClientId for more info. |
| * |
| * @throws IllegalArgumentException |
| * if the id is not valid. |
| */ |
| @Override |
| public void setId(String id) |
| { |
| isIdValid(id); |
| _id = id; |
| _clientId = null; |
| } |
| |
| /** |
| * <p>Set the parent <code>UIComponent</code> of this |
| * <code>UIComponent</code>.</p> |
| * |
| * @param parent The new parent, or <code>null</code> for the root node |
| * of a component tree |
| */ |
| @Override |
| public void setParent(UIComponent parent) |
| { |
| // removing kids OR this is UIViewRoot |
| if (parent == null) |
| { |
| // not UIViewRoot... |
| if (_parent != null && _parent.isInView()) |
| { |
| // trigger the "remove event" lifecycle |
| // and call setInView(false) for all children/facets |
| // doing this => recursive |
| FacesContext facesContext = getFacesContext(); |
| if (facesContext.isProcessingEvents()) |
| { |
| _publishPreRemoveFromViewEvent(facesContext, this); |
| } |
| else |
| { |
| _updateInView(this, false); |
| } |
| } |
| _parent = null; |
| } |
| else |
| { |
| _parent = parent; |
| if (parent.isInView()) |
| { |
| // trigger the ADD_EVENT and call setInView(true) |
| // recursive for all kids/facets... |
| // Application.publishEvent(java.lang.Class, java.lang.Object) must be called, passing |
| // PostAddToViewEvent.class as the first argument and the newly added component as the second |
| // argument. |
| FacesContext facesContext = parent.isCachedFacesContext() ? |
| parent.getFacesContext() : getFacesContext(); |
| if (facesContext.isProcessingEvents()) |
| { |
| _publishPostAddToViewEvent(facesContext, this); |
| } |
| else |
| { |
| _updateInView(this, true); |
| } |
| } |
| } |
| } |
| |
| |
| /** |
| * Publish PostAddToViewEvent to the component and all facets and children. |
| * |
| * @param context |
| * @param component |
| */ |
| private static void _publishPostAddToViewEvent(FacesContext context, UIComponent component) |
| { |
| component.setInView(true); |
| context.getApplication().publishEvent(context, PostAddToViewEvent.class, component.getClass(), component); |
| |
| if (component.getChildCount() > 0) |
| { |
| // PostAddToViewEvent could cause component relocation |
| // (h:outputScript, h:outputStylesheet, composite:insertChildren, composite:insertFacet) |
| // so we need to check if the component was relocated or not |
| |
| List<UIComponent> children = component.getChildren(); |
| for (int i = 0; i < children.size(); i++) |
| { |
| // spin on same index while component removed/replaced |
| // to prevent skipping components: |
| while (true) |
| { |
| UIComponent child = children.get(i); |
| child.pushComponentToEL(context, child); |
| try |
| { |
| _publishPostAddToViewEvent(context, child); |
| } |
| finally |
| { |
| child.popComponentFromEL(context); |
| } |
| if (i < children.size() && children.get(i) != child) |
| { |
| continue; |
| } |
| break; |
| } |
| } |
| } |
| if (component.getFacetCount() > 0) |
| { |
| for (UIComponent child : component.getFacets().values()) |
| { |
| child.pushComponentToEL(context, child); |
| try |
| { |
| _publishPostAddToViewEvent(context, child); |
| } |
| finally |
| { |
| child.popComponentFromEL(context); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Publish PreRemoveFromViewEvent to the component and all facets and children. |
| * |
| * @param context |
| * @param component |
| */ |
| private static void _publishPreRemoveFromViewEvent(FacesContext context, UIComponent component) |
| { |
| component.setInView(false); |
| context.getApplication().publishEvent(context, PreRemoveFromViewEvent.class, component.getClass(), component); |
| |
| if (component.getChildCount() > 0) |
| { |
| for (int i = 0, childCount = component.getChildCount(); i < childCount; i++) |
| { |
| UIComponent child = component.getChildren().get(i); |
| _publishPreRemoveFromViewEvent(context, child); |
| } |
| } |
| if (component.getFacetCount() > 0) |
| { |
| for (UIComponent child : component.getFacets().values()) |
| { |
| _publishPreRemoveFromViewEvent(context, child); |
| } |
| } |
| } |
| |
| private static void _updateInView(UIComponent component, boolean isInView) |
| { |
| component.setInView(isInView); |
| |
| if (component.getChildCount() > 0) |
| { |
| for (int i = 0, childCount = component.getChildCount(); i < childCount; i++) |
| { |
| UIComponent child = component.getChildren().get(i); |
| _updateInView(child, isInView); |
| } |
| } |
| if (component.getFacetCount() > 0) |
| { |
| for (UIComponent child : component.getFacets().values()) |
| { |
| _updateInView(child, isInView); |
| } |
| } |
| } |
| |
| /** |
| * |
| * @param eventName |
| * @param behavior |
| * |
| * @since 2.0 |
| */ |
| public void addClientBehavior(String eventName, ClientBehavior behavior) |
| { |
| Collection<String> eventNames = getEventNames(); |
| if (eventNames == null) |
| { |
| throw new IllegalStateException("Attempting to add a Behavior to a component, " |
| + "that does not support any event types. getEventTypes() must return a non-null Set."); |
| } |
| |
| if (eventNames.contains(eventName)) |
| { |
| if (_behaviorsMap == null) |
| { |
| _behaviorsMap = new HashMap<>(5, 1f); |
| } |
| |
| List<ClientBehavior> behaviorsForEvent = _behaviorsMap.get(eventName); |
| if (behaviorsForEvent == null) |
| { |
| // Normally have client only 1 client behaviour per event name, so size 2 must be sufficient: |
| behaviorsForEvent = new _DeltaList<>(2); |
| _behaviorsMap.put(eventName, behaviorsForEvent); |
| } |
| |
| behaviorsForEvent.add(behavior); |
| _unmodifiableBehaviorsMap = null; |
| } |
| } |
| |
| /** |
| * Invoke any listeners attached to this object which are listening for an event whose type matches the specified |
| * event's runtime type. |
| * <p> |
| * This method does not propagate the event up to parent components, ie listeners attached to parent components |
| * don't automatically get called. |
| * <p> |
| * If any of the listeners throws AbortProcessingException then that exception will prevent any further listener |
| * callbacks from occurring, and the exception propagates out of this method without alteration. |
| * <p> |
| * ActionEvent events are typically queued by the renderer associated with this component in its decode method; |
| * ValueChangeEvent events by the component's validate method. In either case the event's source property references |
| * a component. At some later time the UIViewRoot component iterates over its queued events and invokes the |
| * broadcast method on each event's source object. |
| * |
| * @param event |
| * must not be null. |
| */ |
| @Override |
| public void broadcast(FacesEvent event) throws AbortProcessingException |
| { |
| if (event == null) |
| { |
| throw new NullPointerException("event"); |
| } |
| |
| if (event instanceof BehaviorEvent && event.getComponent() == this) |
| { |
| Behavior behavior = ((BehaviorEvent) event).getBehavior(); |
| behavior.broadcast((BehaviorEvent) event); |
| } |
| |
| if (_facesListeners == null) |
| { |
| return; |
| } |
| // perf: _facesListeners is RandomAccess instance (javax.faces.component._DeltaList) |
| for (int i = 0, size = _facesListeners.size(); i < size; i++) |
| { |
| FacesListener facesListener = _facesListeners.get(i); |
| if (event.isAppropriateListener(facesListener)) |
| { |
| event.processListener(facesListener); |
| } |
| } |
| } |
| |
| @Override |
| public void clearInitialState() |
| { |
| super.clearInitialState(); |
| if (_facesListeners != null) |
| { |
| _facesListeners.clearInitialState(); |
| } |
| if (_behaviorsMap != null) |
| { |
| for (Map.Entry<String, List<ClientBehavior>> entry : _behaviorsMap.entrySet()) |
| { |
| ((PartialStateHolder) entry.getValue()).clearInitialState(); |
| } |
| } |
| if (_systemEventListenerClassMap != null) |
| { |
| for (Map.Entry<Class<? extends SystemEvent>, List<SystemEventListener>> entry : |
| _systemEventListenerClassMap.entrySet()) |
| { |
| ((PartialStateHolder) entry.getValue()).clearInitialState(); |
| } |
| } |
| |
| _capabilities &= ~(FLAG_IS_RENDERER_TYPE_SET); |
| } |
| |
| /** |
| * Check the submitted form parameters for data associated with this component. This default implementation |
| * delegates to this component's renderer if there is one, and otherwise ignores the call. |
| */ |
| @Override |
| public void decode(FacesContext context) |
| { |
| if (context == null) |
| { |
| throw new NullPointerException("context"); |
| } |
| |
| setCachedRenderer(null); |
| Renderer renderer = getRenderer(context); |
| if (renderer != null) |
| { |
| setCachedRenderer(renderer); |
| try |
| { |
| renderer.decode(context, this); |
| } |
| finally |
| { |
| setCachedRenderer(null); |
| } |
| } |
| |
| } |
| |
| @Override |
| public void encodeAll(FacesContext context) throws IOException |
| { |
| if (context == null) |
| { |
| throw new NullPointerException(); |
| } |
| |
| pushComponentToEL(context, this); |
| try |
| { |
| setCachedIsRendered(null); |
| boolean rendered; |
| try |
| { |
| setCachedFacesContext(context); |
| rendered = isRendered(); |
| } |
| finally |
| { |
| setCachedFacesContext(null); |
| } |
| setCachedIsRendered(rendered); |
| if (!rendered) |
| { |
| setCachedIsRendered(null); |
| return; |
| } |
| setCachedRenderer(null); |
| setCachedRenderer(getRenderer(context)); |
| } |
| finally |
| { |
| popComponentFromEL(context); |
| } |
| |
| try |
| { |
| this.encodeBegin(context); |
| |
| // rendering children |
| boolean rendersChildren; |
| try |
| { |
| setCachedFacesContext(context); |
| rendersChildren = this.getRendersChildren(); |
| } |
| finally |
| { |
| setCachedFacesContext(null); |
| } |
| if (rendersChildren) |
| { |
| this.encodeChildren(context); |
| } // let children render itself |
| else |
| { |
| if (this.getChildCount() > 0) |
| { |
| for (int i = 0; i < this.getChildCount(); i++) |
| { |
| UIComponent comp = this.getChildren().get(i); |
| comp.encodeAll(context); |
| } |
| } |
| } |
| this.encodeEnd(context); |
| } |
| finally |
| { |
| setCachedIsRendered(null); |
| setCachedRenderer(null); |
| } |
| } |
| |
| @Override |
| public void encodeBegin(FacesContext context) throws IOException |
| { |
| if (context == null) |
| { |
| throw new NullPointerException("context"); |
| } |
| |
| try |
| { |
| setCachedFacesContext(context); |
| // Call UIComponent.pushComponentToEL(javax.faces.context.FacesContext, javax.faces.component.UIComponent) |
| pushComponentToEL(context, this); |
| |
| if (isRendered()) |
| { |
| // If our rendered property is true, render the beginning of the current state of this |
| // UIComponent to the response contained in the specified FacesContext. |
| |
| // Call Application.publishEvent(java.lang.Class, java.lang.Object), passing BeforeRenderEvent.class as |
| // the first argument and the component instance to be rendered as the second argument. |
| |
| // The main issue we have here is that the listeners are normally just registered |
| // to UIComponent, how do we deal with inherited ones? |
| // We have to ask the EG |
| context.getApplication().publishEvent(context, PreRenderComponentEvent.class, UIComponent.class, this); |
| |
| Renderer renderer = getRenderer(context); |
| if (renderer != null) |
| { |
| // If a Renderer is associated with this UIComponent, the actual encoding will be delegated to |
| // Renderer.encodeBegin(FacesContext, UIComponent). |
| renderer.encodeBegin(context, this); |
| } |
| } |
| } |
| finally |
| { |
| setCachedFacesContext(null); |
| } |
| } |
| |
| @Override |
| public void encodeChildren(FacesContext context) throws IOException |
| { |
| if (context == null) |
| { |
| throw new NullPointerException("context"); |
| } |
| |
| boolean isCachedFacesContext = isCachedFacesContext(); |
| try |
| { |
| if (!isCachedFacesContext) |
| { |
| setCachedFacesContext(context); |
| } |
| if (isRendered()) |
| { |
| // If our rendered property is true, render the child UIComponents of this UIComponent. |
| |
| Renderer renderer = getRenderer(context); |
| if (renderer == null) |
| { |
| // If no Renderer is associated with this UIComponent, iterate over each of the children of this |
| // component and call UIComponent.encodeAll(javax.faces.context.FacesContext). |
| if (getChildCount() > 0) |
| { |
| for (int i = 0, childCount = getChildCount(); i < childCount; i++) |
| { |
| UIComponent child = getChildren().get(i); |
| child.encodeAll(context); |
| } |
| } |
| } |
| else |
| { |
| // If a Renderer is associated with this UIComponent, the actual encoding will be delegated to |
| // Renderer.encodeChildren(FacesContext, UIComponent). |
| renderer.encodeChildren(context, this); |
| } |
| } |
| } |
| finally |
| { |
| if (!isCachedFacesContext) |
| { |
| setCachedFacesContext(null); |
| } |
| } |
| } |
| |
| @Override |
| public void encodeEnd(FacesContext context) throws IOException |
| { |
| if (context == null) |
| { |
| throw new NullPointerException("context"); |
| } |
| try |
| { |
| setCachedFacesContext(context); |
| if (isRendered()) |
| { |
| // If our rendered property is true, render the ending of the current state of this UIComponent. |
| Renderer renderer = getRenderer(context); |
| if (renderer != null) |
| { |
| // If a Renderer is associated with this UIComponent, the actual encoding will be delegated to |
| // Renderer.encodeEnd(FacesContext, UIComponent). |
| renderer.encodeEnd(context, this); |
| } |
| } |
| } |
| finally |
| { |
| // Call UIComponent.popComponentFromEL(javax.faces.context.FacesContext). before returning regardless |
| // of the value of the rendered property. |
| popComponentFromEL(context); |
| setCachedFacesContext(null); |
| } |
| } |
| |
| /** |
| * Standard method for finding other components by id, inherited by most UIComponent objects. |
| * <p> |
| * The lookup is performed in a manner similar to finding a file in a filesystem; there is a "base" at which to |
| * start, and the id can be for something in the "local directory", or can include a relative path. Here, |
| * NamingContainer components fill the role of directories, and ":" is the "path separator". Note, however, that |
| * although components have a strict parent/child hierarchy, component ids are only prefixed ("namespaced") with the |
| * id of their parent when the parent is a NamingContainer. |
| * <p> |
| * The base node at which the search starts is determined as follows: |
| * <ul> |
| * <li>When expr starts with ':', the search starts with the root component of the tree that this component is in |
| * (ie the ancestor whose parent is null). |
| * <li>Otherwise, if this component is a NamingContainer then the search starts with this component. |
| * <li>Otherwise, the search starts from the nearest ancestor NamingContainer (or the root component if there is no |
| * NamingContainer ancestor). |
| * </ul> |
| * |
| * @param expr |
| * is of form "id1:id2:id3". |
| * @return UIComponent or null if no component with the specified id is found. |
| */ |
| |
| @Override |
| public UIComponent findComponent(String expr) |
| { |
| if (expr == null) |
| { |
| throw new NullPointerException("expr"); |
| } |
| if (expr.length() == 0) |
| { |
| return null; |
| } |
| |
| char separatorChar = getFacesContext().getNamingContainerSeparatorChar(); |
| UIComponent findBase; |
| if (expr.charAt(0) == separatorChar) |
| { |
| findBase = _ComponentUtils.getRootComponent(this); |
| expr = expr.substring(1); |
| } |
| else |
| { |
| if (this instanceof NamingContainer) |
| { |
| findBase = this; |
| } |
| else |
| { |
| findBase = _ComponentUtils.findParentNamingContainer(this, true /* root if not found */); |
| } |
| } |
| |
| int separator = expr.indexOf(separatorChar); |
| if (separator == -1) |
| { |
| return _ComponentUtils.findComponent(findBase, expr, separatorChar); |
| } |
| |
| String id = expr.substring(0, separator); |
| findBase = _ComponentUtils.findComponent(findBase, id, separatorChar); |
| if (findBase == null) |
| { |
| return null; |
| } |
| |
| if (!(findBase instanceof NamingContainer)) |
| { |
| throw new IllegalArgumentException("Intermediate identifier " + id + " in search expression " + expr |
| + " identifies a UIComponent that is not a NamingContainer"); |
| } |
| |
| return findBase.findComponent(expr.substring(separator + 1)); |
| |
| } |
| |
| /** |
| * Get a map through which all the UIComponent's properties, value-bindings and non-property attributes can be read |
| * and written. |
| * <p> |
| * When writing to the returned map: |
| * <ul> |
| * <li>If this component has an explicit property for the specified key then the setter method is called. An |
| * IllegalArgumentException is thrown if the property is read-only. If the property is readable then the old value |
| * is returned, otherwise null is returned. |
| * <li>Otherwise the key/value pair is stored in a map associated with the component. |
| * </ul> |
| * Note that value-bindings are <i>not</i> written by put calls to this map. Writing to the attributes map using a |
| * key for which a value-binding exists will just store the value in the attributes map rather than evaluating the |
| * binding, effectively "hiding" the value-binding from later attributes.get calls. Setter methods on components |
| * commonly do <i>not</i> evaluate a binding of the same name; they just store the provided value directly on the |
| * component. |
| * <p> |
| * When reading from the returned map: |
| * <ul> |
| * <li>If this component has an explicit property for the specified key then the getter method is called. If the |
| * property exists, but is read-only (ie only a setter method is defined) then an IllegalArgumentException is |
| * thrown. |
| * <li>If the attribute map associated with the component has an entry with the specified key, then that is |
| * returned. |
| * <li>If this component has a value-binding for the specified key, then the value-binding is evaluated to fetch the |
| * value. |
| * <li>Otherwise, null is returned. |
| * </ul> |
| * Note that components commonly define getter methods such that they evaluate a value-binding of the same name if |
| * there isn't yet a local property. |
| * <p> |
| * Assigning values to the map which are not explicit properties on the underlying component can be used to "tunnel" |
| * attributes from the JSP tag (or view-specific equivalent) to the associated renderer without modifying the |
| * component itself. |
| * <p> |
| * Any value-bindings and non-property attributes stored in this map are automatically serialized along with the |
| * component when the view is serialized. |
| */ |
| @Override |
| public Map<String, Object> getAttributes() |
| { |
| if (_attributesMap == null) |
| { |
| _attributesMap = new _ComponentAttributesMap(this); |
| } |
| |
| return _attributesMap; |
| } |
| |
| @Override |
| public Map<String, Object> getPassThroughAttributes(boolean create) |
| { |
| // Take into account the param "create" in MyFaces case does not have |
| // sense at all |
| if (_passthroughAttributesMap == null) |
| { |
| if (!create) |
| { |
| if ((_capabilities & FLAG_PASSTHROUGH_ATTRIBUTE_MAP_SET) != 0) |
| { |
| // Was already created, return wrapper |
| _passthroughAttributesMap = new _PassThroughAttributesMap(this); |
| } |
| } |
| else |
| { |
| _passthroughAttributesMap = new _PassThroughAttributesMap(this); |
| _capabilities |= FLAG_PASSTHROUGH_ATTRIBUTE_MAP_SET; |
| } |
| } |
| return _passthroughAttributesMap; |
| } |
| |
| /** |
| * Return the number of direct child components this component has. |
| * <p> |
| * Identical to getChildren().size() except that when this component has no children this method will not force an |
| * empty list to be created. |
| */ |
| @Override |
| public int getChildCount() |
| { |
| return _childrenList == null ? 0 : _childrenList.size(); |
| } |
| |
| /** |
| * Return a list of the UIComponent objects which are direct children of this component. |
| * <p> |
| * The list object returned has some non-standard behaviour: |
| * <ul> |
| * <li>The list is type-checked; only UIComponent objects can be added. |
| * <li>If a component is added to the list with an id which is the same as some other component in the list then an |
| * exception is thrown. However multiple components with a null id may be added. |
| * <li>The component's parent property is set to this component. If the component already had a parent, then the |
| * component is first removed from its original parent's child list. |
| * </ul> |
| */ |
| @Override |
| public List<UIComponent> getChildren() |
| { |
| if (_childrenList == null) |
| { |
| _childrenList = new _ComponentChildrenList(this); |
| } |
| return _childrenList; |
| } |
| |
| /** |
| * |
| * @return |
| * |
| * @since 2.0 |
| */ |
| public Map<String,List<ClientBehavior>> getClientBehaviors() |
| { |
| if(_behaviorsMap == null) |
| { |
| return Collections.emptyMap(); |
| } |
| |
| return wrapBehaviorsMap(); |
| } |
| |
| /** |
| * Get a string which can be output to the response which uniquely identifies this UIComponent within the current |
| * view. |
| * <p> |
| * The component should have an id attribute already assigned to it; however if the id property is currently null |
| * then a unique id is generated and set for this component. This only happens when components are programmatically |
| * created without ids, as components created by a ViewHandler should be assigned ids when they are created. |
| * <p> |
| * If this component is a descendant of a NamingContainer then the client id is of form |
| * "{namingContainerId}:{componentId}". Note that the naming container's id may itself be of compound form if it has |
| * an ancestor naming container. Note also that this only applies to naming containers; other UIComponent types in |
| * the component's ancestry do not affect the clientId. |
| * <p> |
| * Finally the renderer associated with this component is asked to convert the id into a suitable form. This allows |
| * escaping of any characters in the clientId which are significant for the markup language generated by that |
| * renderer. |
| */ |
| @Override |
| public String getClientId(FacesContext context) |
| { |
| if (context == null) |
| { |
| throw new NullPointerException("context"); |
| } |
| |
| if (_clientId != null) |
| { |
| return _clientId; |
| } |
| |
| String id = getId(); |
| if (id == null) |
| { |
| // Although this is an error prone side effect, we automatically create a new id |
| // just to be compatible to the RI |
| |
| // The documentation of UniqueIdVendor says that this interface should be implemented by |
| // components that also implements NamingContainer. The only component that does not implement |
| // NamingContainer but UniqueIdVendor is UIViewRoot. Anyway we just can't be 100% sure about this |
| // fact, so it is better to scan for the closest UniqueIdVendor. If it is not found use |
| // viewRoot.createUniqueId, otherwise use UniqueIdVendor.createUniqueId(context,seed). |
| UniqueIdVendor parentUniqueIdVendor = _ComponentUtils.closest(UniqueIdVendor.class, this); |
| if (parentUniqueIdVendor == null) |
| { |
| UIViewRoot viewRoot = context.getViewRoot(); |
| if (viewRoot != null) |
| { |
| id = viewRoot.createUniqueId(); |
| } |
| else |
| { |
| // The RI throws a NPE |
| String location = getComponentLocation(this); |
| throw new FacesException("Cannot create clientId. No id is assigned for component" |
| + " to create an id and UIViewRoot is not defined: " |
| + _ComponentUtils.getPathToComponent(this) |
| + (location != null ? " created from: " + location : "")); |
| } |
| } |
| else |
| { |
| id = parentUniqueIdVendor.createUniqueId(context, null); |
| } |
| setId(id); |
| } |
| |
| UIComponent namingContainer = _ComponentUtils.findParentNamingContainer(this, false); |
| if (namingContainer != null) |
| { |
| String containerClientId = namingContainer.getContainerClientId(context); |
| if (containerClientId != null) |
| { |
| StringBuilder bld = _getSharedStringBuilder(context); |
| _clientId = bld.append(containerClientId).append( |
| context.getNamingContainerSeparatorChar()).append(id).toString(); |
| } |
| else |
| { |
| _clientId = id; |
| } |
| } |
| else |
| { |
| _clientId = id; |
| } |
| |
| Renderer renderer = getRenderer(context); |
| if (renderer != null) |
| { |
| _clientId = renderer.convertClientId(context, _clientId); |
| } |
| |
| // -=Leonardo Uribe=- In jsf 1.1 and 1.2 this warning has sense, but in jsf 2.0 it is common to have |
| // components without any explicit id (UIViewParameter components and UIOuput resource components) instances. |
| // So, this warning is becoming obsolete in this new context and should be removed. |
| //if (idWasNull && log.isLoggable(Level.WARNING)) |
| //{ |
| // log.warning("WARNING: Component " + _clientId |
| // + " just got an automatic id, because there was no id assigned yet. " |
| // + "If this component was created dynamically (i.e. not by a JSP tag) you should assign it an " |
| // + "explicit static id or assign it the id you get from " |
| // + "the createUniqueId from the current UIViewRoot " |
| // + "component right after creation! Path to Component: " + _ComponentUtils.getPathToComponent(this)); |
| //} |
| |
| return _clientId; |
| } |
| |
| /** |
| * |
| * @return |
| * |
| * @since 2.0 |
| */ |
| public String getDefaultEventName() |
| { |
| // if a default event exists for a component, this method is overriden thus assume null |
| return null; |
| } |
| |
| /** |
| * |
| * @return |
| * |
| * @since 2.0 |
| */ |
| public Collection<String> getEventNames() |
| { |
| // must be specified by the implementing component. |
| // Returning null will force an error message in addClientBehavior. |
| return null; |
| } |
| |
| @Override |
| public UIComponent getFacet(String name) |
| { |
| return _facetMap == null ? null : _facetMap.get(name); |
| } |
| |
| /** |
| * @since 1.2 |
| */ |
| @Override |
| public int getFacetCount() |
| { |
| return _facetMap == null ? 0 : _facetMap.size(); |
| } |
| |
| @Override |
| public Map<String, UIComponent> getFacets() |
| { |
| if (_facetMap == null) |
| { |
| _facetMap = new _ComponentFacetMap<>(this); |
| } |
| return _facetMap; |
| } |
| |
| @Override |
| public Iterator<UIComponent> getFacetsAndChildren() |
| { |
| // we can't use _facetMap and _childrenList here directly, |
| // because some component implementation could keep their |
| // own properties for facets and children and just override |
| // getFacets() and getChildren() (e.g. seen in PrimeFaces). |
| // See MYFACES-2611 for details. |
| if (getFacetCount() == 0) |
| { |
| if (getChildCount() == 0) |
| { |
| return Collections.<UIComponent>emptyIterator(); |
| } |
| |
| return getChildren().iterator(); |
| } |
| else |
| { |
| if (getChildCount() == 0) |
| { |
| return getFacets().values().iterator(); |
| } |
| |
| return new _FacetsAndChildrenIterator(getFacets(), getChildren()); |
| } |
| } |
| |
| /** |
| * Get a string which uniquely identifies this UIComponent within the scope of the nearest ancestor NamingContainer |
| * component. The id is not necessarily unique across all components in the current view. |
| */ |
| @JSFProperty(rtexprvalue = true) |
| @Override |
| public String getId() |
| { |
| return _id; |
| } |
| |
| @Override |
| public UIComponent getParent() |
| { |
| return _parent; |
| } |
| |
| @Override |
| public String getRendererType() |
| { |
| // rendererType is literal-only, no ValueExpression - MYFACES-3136: |
| // Even if this is true, according to JSF spec section 8 Rendering Model, |
| // this part is essential to implement "delegated implementation" pattern, |
| // so we can't do this optimization here. Instead, JSF developers could prevent |
| // this evaluation overriding this method directly. |
| if (_rendererType != null) |
| { |
| return _rendererType; |
| } |
| ValueExpression expression = getValueExpression("rendererType"); |
| if (expression != null) |
| { |
| return (String) expression.getValue(getFacesContext().getELContext()); |
| } |
| return null; |
| } |
| |
| /** |
| * Indicates whether this component or its renderer manages the invocation of the rendering methods of its child |
| * components. When this is true: |
| * <ul> |
| * <li>This component's encodeBegin method will only be called after all the child components have been created and |
| * added to this component. <li>This component's encodeChildren method will be called after its encodeBegin method. |
| * Components for which this method returns false do not get this method invoked at all. <li>No rendering methods |
| * will be called automatically on child components; this component is required to invoke the |
| * encodeBegin/encodeEnd/etc on them itself. |
| * </ul> |
| */ |
| @Override |
| public boolean getRendersChildren() |
| { |
| Renderer renderer = getRenderer(getFacesContext()); |
| return renderer != null ? renderer.getRendersChildren() : false; |
| } |
| |
| /** |
| * <code>invokeOnComponent</code> must be implemented in <code>UIComponentBase</code> too... |
| */ |
| @Override |
| public boolean invokeOnComponent(FacesContext context, String clientId, ContextCallback callback) |
| throws FacesException |
| { |
| if (isCachedFacesContext()) |
| { |
| return super.invokeOnComponent(context, clientId, callback); |
| } |
| else |
| { |
| try |
| { |
| setCachedFacesContext(context); |
| return super.invokeOnComponent(context, clientId, callback); |
| } |
| finally |
| { |
| setCachedFacesContext(null); |
| } |
| } |
| } |
| |
| @Override |
| public boolean visitTree(VisitContext context, VisitCallback callback) |
| { |
| if (isCachedFacesContext()) |
| { |
| return super.visitTree(context, callback); |
| } |
| else |
| { |
| try |
| { |
| setCachedFacesContext(context.getFacesContext()); |
| return super.visitTree(context, callback); |
| } |
| finally |
| { |
| setCachedFacesContext(null); |
| } |
| } |
| } |
| |
| /** |
| * A boolean value that indicates whether this component should be rendered. Default value: true. |
| **/ |
| @Override |
| @JSFProperty |
| public boolean isRendered() |
| { |
| if (_cachedIsRendered != null) |
| { |
| return Boolean.TRUE.equals(_cachedIsRendered); |
| } |
| return (Boolean) getStateHelper().eval(PropertyKeys.rendered, DEFAULT_RENDERED); |
| } |
| |
| @JSFProperty(literalOnly = true, istransient = true, tagExcluded = true) |
| @Override |
| public boolean isTransient() |
| { |
| return _transient; |
| } |
| |
| @Override |
| public void markInitialState() |
| { |
| super.markInitialState(); |
| |
| // Enable copyFullInitialState behavior when delta is written into this component. |
| ((_DeltaStateHelper)getStateHelper()).setCopyFullInitialState(true); |
| |
| if (_facesListeners != null) |
| { |
| _facesListeners.markInitialState(); |
| } |
| if (_behaviorsMap != null) |
| { |
| for (Map.Entry<String, List<ClientBehavior>> entry : _behaviorsMap.entrySet()) |
| { |
| ((PartialStateHolder) entry.getValue()).markInitialState(); |
| } |
| } |
| if (_systemEventListenerClassMap != null) |
| { |
| for (Map.Entry<Class<? extends SystemEvent>, List<SystemEventListener>> entry : |
| _systemEventListenerClassMap.entrySet()) |
| { |
| ((PartialStateHolder) entry.getValue()).markInitialState(); |
| } |
| } |
| } |
| |
| @Override |
| protected void addFacesListener(FacesListener listener) |
| { |
| if (listener == null) |
| { |
| throw new NullPointerException("listener"); |
| } |
| if (_facesListeners == null) |
| { |
| // How many facesListeners have single component normally? |
| _facesListeners = new _DeltaList<>(5); |
| } |
| _facesListeners.add(listener); |
| } |
| |
| @Override |
| protected FacesContext getFacesContext() |
| { |
| if (_facesContext == null) |
| { |
| return FacesContext.getCurrentInstance(); |
| } |
| else |
| { |
| return _facesContext; |
| } |
| } |
| |
| // FIXME: Notify EG for generic usage |
| @Override |
| protected FacesListener[] getFacesListeners(Class clazz) |
| { |
| if (clazz == null) |
| { |
| throw new NullPointerException("Class is null"); |
| } |
| if (!FacesListener.class.isAssignableFrom(clazz)) |
| { |
| throw new IllegalArgumentException("Class " + clazz.getName() + " must implement " + FacesListener.class); |
| } |
| |
| if (_facesListeners == null) |
| { |
| return (FacesListener[]) Array.newInstance(clazz, 0); |
| } |
| |
| List<FacesListener> lst = null; |
| // perf: _facesListeners is RandomAccess instance (javax.faces.component._DeltaList) |
| for (int i = 0, size = _facesListeners.size(); i < size; i++) |
| { |
| FacesListener facesListener = _facesListeners.get(i); |
| if (facesListener != null && clazz.isAssignableFrom(facesListener.getClass())) |
| { |
| if (lst == null) |
| { |
| lst = new ArrayList<>(5); |
| } |
| lst.add(facesListener); |
| } |
| } |
| |
| if (lst == null || lst.isEmpty()) |
| { |
| return (FacesListener[]) Array.newInstance(clazz, 0); |
| } |
| |
| return lst.toArray((FacesListener[]) Array.newInstance(clazz, lst.size())); |
| } |
| |
| @Override |
| protected Renderer getRenderer(FacesContext context) |
| { |
| if (context == null) |
| { |
| throw new NullPointerException("context"); |
| } |
| Renderer renderer = getCachedRenderer(); |
| if (renderer != null) |
| { |
| return renderer; |
| } |
| String rendererType = getRendererType(); |
| if (rendererType == null) |
| { |
| return null; |
| } |
| |
| RenderKit renderKit = context.getRenderKit(); |
| renderer = renderKit.getRenderer(getFamily(), rendererType); |
| if (renderer == null) |
| { |
| String location = getComponentLocation(this); |
| String logStr = "No Renderer found for component " + _ComponentUtils.getPathToComponent(this) |
| + " (component-family=" + getFamily() |
| + ", renderer-type=" + rendererType + ')' |
| + (location != null ? " created from: " + location : ""); |
| |
| getFacesContext().getExternalContext().log(logStr); |
| log.warning(logStr); |
| } |
| return renderer; |
| } |
| |
| @Override |
| protected void removeFacesListener(FacesListener listener) |
| { |
| if (listener == null) |
| { |
| throw new NullPointerException("listener is null"); |
| } |
| |
| if (_facesListeners != null) |
| { |
| _facesListeners.remove(listener); |
| } |
| } |
| |
| @Override |
| public void queueEvent(FacesEvent event) |
| { |
| if (event == null) |
| { |
| throw new NullPointerException("event"); |
| } |
| UIComponent parent = getParent(); |
| if (parent == null) |
| { |
| throw new IllegalStateException("component is not a descendant of a UIViewRoot"); |
| } |
| parent.queueEvent(event); |
| } |
| |
| @Override |
| public void processDecodes(FacesContext context) |
| { |
| try |
| { |
| setCachedFacesContext(context); |
| // Call UIComponent.pushComponentToEL(javax.faces.context.FacesContext, javax.faces.component.UIComponent) |
| pushComponentToEL(context, this); |
| if (_isPhaseExecutable(context)) |
| { |
| // Call the processDecodes() method of all facets and children of this UIComponent, in the order |
| // determined by a call to getFacetsAndChildren(). |
| int facetCount = getFacetCount(); |
| if (facetCount > 0) |
| { |
| for (UIComponent facet : getFacets().values()) |
| { |
| facet.processDecodes(context); |
| } |
| } |
| for (int i = 0, childCount = getChildCount(); i < childCount; i++) |
| { |
| UIComponent child = getChildren().get(i); |
| child.processDecodes(context); |
| } |
| |
| try |
| { |
| // Call the decode() method of this component. |
| decode(context); |
| } |
| catch (RuntimeException e) |
| { |
| // If a RuntimeException is thrown during decode processing, call FacesContext.renderResponse() |
| // and re-throw the exception. |
| context.renderResponse(); |
| throw e; |
| } |
| } |
| } |
| finally |
| { |
| // Call UIComponent.popComponentFromEL(javax.faces.context.FacesContext) from inside of a finally |
| // block, just before returning. |
| |
| popComponentFromEL(context); |
| setCachedFacesContext(null); |
| } |
| } |
| |
| @Override |
| public void processValidators(FacesContext context) |
| { |
| try |
| { |
| setCachedFacesContext(context); |
| // Call UIComponent.pushComponentToEL(javax.faces.context.FacesContext, javax.faces.component.UIComponent) |
| pushComponentToEL(context, this); |
| if (_isPhaseExecutable(context)) |
| { |
| //Pre validation event dispatch for component |
| context.getApplication().publishEvent(context, PreValidateEvent.class, getClass(), this); |
| |
| try |
| { |
| // Call the processValidators() method of all facets and children of this UIComponent, in the order |
| // determined by a call to getFacetsAndChildren(). |
| int facetCount = getFacetCount(); |
| if (facetCount > 0) |
| { |
| for (UIComponent facet : getFacets().values()) |
| { |
| facet.processValidators(context); |
| } |
| } |
| |
| for (int i = 0, childCount = getChildCount(); i < childCount; i++) |
| { |
| UIComponent child = getChildren().get(i); |
| child.processValidators(context); |
| } |
| } |
| finally |
| { |
| context.getApplication().publishEvent(context, PostValidateEvent.class, getClass(), this); |
| } |
| } |
| } |
| finally |
| { |
| popComponentFromEL(context); |
| setCachedFacesContext(null); |
| } |
| } |
| |
| /** |
| * This isn't an input component, so just pass on the processUpdates call to child components and facets that might |
| * be input components. |
| * <p> |
| * Components that were never rendered can't possibly be receiving update data (no corresponding fields were ever |
| * put into the response) so if this component is not rendered then this method does not invoke processUpdates on |
| * its children. |
| */ |
| @Override |
| public void processUpdates(FacesContext context) |
| { |
| try |
| { |
| setCachedFacesContext(context); |
| // Call UIComponent.pushComponentToEL(javax.faces.context.FacesContext, javax.faces.component.UIComponent) |
| pushComponentToEL(context, this); |
| if (_isPhaseExecutable(context)) |
| { |
| // Call the processUpdates() method of all facets and children of this UIComponent, in the order |
| // determined by a call to getFacetsAndChildren(). |
| int facetCount = getFacetCount(); |
| if (facetCount > 0) |
| { |
| for (UIComponent facet : getFacets().values()) |
| { |
| facet.processUpdates(context); |
| } |
| } |
| |
| for (int i = 0, childCount = getChildCount(); i < childCount; i++) |
| { |
| UIComponent child = getChildren().get(i); |
| child.processUpdates(context); |
| } |
| } |
| } |
| finally |
| { |
| // After returning from the processUpdates() method on a child or facet, call |
| // UIComponent.popComponentFromEL(javax.faces.context.FacesContext) |
| popComponentFromEL(context); |
| |
| setCachedFacesContext(null); |
| } |
| } |
| |
| @Override |
| public Object processSaveState(FacesContext context) |
| { |
| if (context == null) |
| { |
| throw new NullPointerException("context"); |
| } |
| |
| if (isTransient()) |
| { |
| // consult the transient property of this component. If true, just return null. |
| return null; |
| } |
| |
| // Call UIComponent.pushComponentToEL(javax.faces.context.FacesContext, javax.faces.component.UIComponent) |
| pushComponentToEL(context, this); |
| |
| Map<String, Object> facetMap; |
| |
| List<Object> childrenList; |
| |
| Object savedState; |
| try |
| { |
| facetMap = null; |
| int facetCount = getFacetCount(); |
| if (facetCount > 0) |
| { |
| // Call the processSaveState() method of all facets and children of this UIComponent in the order |
| // determined by a call to getFacetsAndChildren(), skipping children and facets that are transient. |
| |
| // To improve speed and robustness, the facets and children processing is splited to maintain the |
| // facet --> state coherence based on the facet's name |
| for (Map.Entry<String, UIComponent> entry : getFacets().entrySet()) |
| { |
| UIComponent component = entry.getValue(); |
| if (!component.isTransient()) |
| { |
| if (facetMap == null) |
| { |
| facetMap = new HashMap<>(facetCount, 1); |
| } |
| |
| facetMap.put(entry.getKey(), component.processSaveState(context)); |
| } |
| } |
| } |
| childrenList = null; |
| int childCount = getChildCount(); |
| if (childCount > 0) |
| { |
| // Call the processSaveState() method of all facets and children of this UIComponent in the order |
| // determined by a call to getFacetsAndChildren(), skipping children and facets that are transient. |
| |
| // To improve speed and robustness, the facets and children processing is splited to maintain the |
| // facet --> state coherence based on the facet's name |
| for (int i = 0; i < childCount; i++) |
| { |
| UIComponent child = getChildren().get(i); |
| if (!child.isTransient()) |
| { |
| if (childrenList == null) |
| { |
| childrenList = new ArrayList<>(childCount); |
| } |
| |
| Object childState = child.processSaveState(context); |
| if (childState != null) |
| { // FIXME: Isn't that check dangerous for restoration since the child isn't marked transient? |
| childrenList.add(childState); |
| } |
| } |
| } |
| } |
| |
| // Call the saveState() method of this component. |
| savedState = saveState(context); |
| } |
| finally |
| { |
| // Ensure that UIComponent.popComponentFromEL(javax.faces.context.FacesContext) is called |
| // correctly after each child or facet. |
| popComponentFromEL(context); |
| } |
| |
| // Encapsulate the child state and your state into a Serializable Object and return it. |
| return new Object[] { savedState, facetMap, childrenList }; |
| } |
| |
| @SuppressWarnings("unchecked") |
| @Override |
| public void processRestoreState(FacesContext context, Object state) |
| { |
| if (context == null) |
| { |
| throw new NullPointerException("context"); |
| } |
| |
| Object[] stateValues = (Object[]) state; |
| |
| try |
| { |
| // Call UIComponent.pushComponentToEL(javax.faces.context.FacesContext, javax.faces.component.UIComponent) |
| pushComponentToEL(context, this); |
| |
| // Call the restoreState() method of this component. |
| restoreState(context, stateValues[0]); |
| |
| Map<String, Object> facetMap = (Map<String, Object>) stateValues[1]; |
| if (facetMap != null && getFacetCount() > 0) |
| { |
| // Call the processRestoreState() method of all facets and children of this UIComponent in the order |
| // determined by a call to getFacetsAndChildren(). |
| |
| // To improve speed and robustness, the facets and children processing is splited to maintain the |
| // facet --> state coherence based on the facet's name |
| for (Map.Entry<String, UIComponent> entry : getFacets().entrySet()) |
| { |
| Object facetState = facetMap.get(entry.getKey()); |
| if (facetState != null) |
| { |
| entry.getValue().processRestoreState(context, facetState); |
| } |
| else |
| { |
| context.getExternalContext().log("No state found to restore facet " + entry.getKey()); |
| } |
| } |
| } |
| List<Object> childrenList = (List<Object>) stateValues[2]; |
| if (childrenList != null && getChildCount() > 0) |
| { |
| // Call the processRestoreState() method of all facets and children of this UIComponent in the order |
| // determined by a call to getFacetsAndChildren(). |
| |
| // To improve speed and robustness, the facets and children processing is splited to maintain the |
| // facet --> state coherence based on the facet's name |
| int idx = 0; |
| for (int i = 0, childCount = getChildCount(); i < childCount; i++) |
| { |
| UIComponent child = getChildren().get(i); |
| if (!child.isTransient()) |
| { |
| Object childState = childrenList.get(idx++); |
| if (childState != null) |
| { |
| child.processRestoreState(context, childState); |
| } |
| else |
| { |
| context.getExternalContext().log("No state found to restore child of component " + getId()); |
| } |
| } |
| } |
| } |
| } |
| finally |
| { |
| // After returning from the processRestoreState() method on a child or facet, call |
| // UIComponent.popComponentFromEL(javax.faces.context.FacesContext) |
| popComponentFromEL(context); |
| } |
| } |
| |
| /** |
| * Gets the Location of the given UIComponent from its attribute map. |
| * @param component |
| * @return |
| */ |
| private String getComponentLocation(UIComponent component) |
| { |
| Location location = (Location) component.getAttributes().get(UIComponent.VIEW_LOCATION_KEY); |
| return location == null ? null : location.toString(); |
| } |
| |
| @Override |
| public void setTransient(boolean transientFlag) |
| { |
| _transient = transientFlag; |
| } |
| |
| /** |
| * Serializes objects which are "attached" to this component but which are not UIComponent children of it. Examples |
| * are validator and listener objects. To be precise, it returns an object which implements java.io.Serializable, |
| * and which when serialized will persist the state of the provided object. |
| * <p> |
| * If the attachedObject is a List then every object in the list is saved via a call to this method, and the |
| * returned wrapper object contains a List object. |
| * <p> |
| * If the object implements StateHolder then the object's saveState is called immediately, and a wrapper is returned |
| * which contains both this saved state and the original class name. However in the case where the |
| * StateHolder.isTransient method returns true, null is returned instead. |
| * <p> |
| * If the object implements java.io.Serializable then the object is simply returned immediately; standard java |
| * serialization will later be used to store this object. |
| * <p> |
| * In all other cases, a wrapper is returned which simply stores the type of the provided object. When deserialized, |
| * a default instance of that type will be recreated. |
| */ |
| public static Object saveAttachedState(FacesContext context, Object attachedObject) |
| { |
| if (context == null) |
| { |
| throw new NullPointerException ("context"); |
| } |
| |
| if (attachedObject == null) |
| { |
| return null; |
| } |
| // StateHolder interface should take precedence over |
| // List children |
| if (attachedObject instanceof StateHolder) |
| { |
| StateHolder holder = (StateHolder) attachedObject; |
| if (holder.isTransient()) |
| { |
| return null; |
| } |
| |
| return new _AttachedStateWrapper(attachedObject.getClass(), holder.saveState(context)); |
| } |
| else if (attachedObject instanceof Collection) |
| { |
| if (ArrayList.class.equals(attachedObject.getClass())) |
| { |
| ArrayList<?> list = (ArrayList<?>) attachedObject; |
| int size = list.size(); |
| List<Object> lst = new ArrayList<Object>(size); |
| for (int i = 0; i < size; i++) |
| { |
| Object item = list.get(i); |
| if (item != null) |
| { |
| lst.add(saveAttachedState(context, item)); |
| } |
| } |
| return new _AttachedListStateWrapper(lst); |
| } |
| else |
| { |
| List<Object> lst = new ArrayList<>(((Collection<?>) attachedObject).size()); |
| for (Object item : (Collection<?>) attachedObject) |
| { |
| if (item != null) |
| { |
| lst.add(saveAttachedState(context, item)); |
| } |
| } |
| return new _AttachedCollectionStateWrapper(attachedObject.getClass(), lst); |
| } |
| } |
| else if (attachedObject instanceof Serializable) |
| { |
| return attachedObject; |
| } |
| else |
| { |
| return new _AttachedStateWrapper(attachedObject.getClass(), null); |
| } |
| } |
| |
| public static Object restoreAttachedState(FacesContext context, Object stateObj) throws IllegalStateException |
| { |
| if (context == null) |
| { |
| throw new NullPointerException("context"); |
| } |
| if (stateObj == null) |
| { |
| return null; |
| } |
| if (stateObj instanceof _AttachedListStateWrapper) |
| { |
| // perf: getWrappedStateList in _AttachedListStateWrapper is always ArrayList: see saveAttachedState |
| ArrayList<Object> lst = (ArrayList<Object>) ((_AttachedListStateWrapper) stateObj).getWrappedStateList(); |
| List<Object> restoredList = new ArrayList<Object>(lst.size()); |
| for (int i = 0, size = lst.size(); i < size; i++) |
| { |
| Object item = lst.get(i); |
| restoredList.add(restoreAttachedState(context, item)); |
| } |
| return restoredList; |
| } |
| else if (stateObj instanceof _AttachedCollectionStateWrapper) |
| { |
| _AttachedCollectionStateWrapper wrappedState = (_AttachedCollectionStateWrapper) stateObj; |
| Class<?> clazz = wrappedState.getClazz(); |
| List<Object> lst = wrappedState.getWrappedStateList(); |
| Collection restoredList; |
| try |
| { |
| restoredList = (Collection) clazz.newInstance(); |
| } |
| catch (InstantiationException e) |
| { |
| throw new RuntimeException("Could not restore StateHolder of type " + clazz.getName() |
| + " (missing no-args constructor?)", e); |
| } |
| catch (IllegalAccessException e) |
| { |
| throw new RuntimeException(e); |
| } |
| |
| for (int i = 0; i < lst.size(); i++) |
| { |
| Object item = lst.get(i); |
| restoredList.add(restoreAttachedState(context, item)); |
| } |
| return restoredList; |
| |
| } |
| else if (stateObj instanceof _AttachedStateWrapper) |
| { |
| Class<?> clazz = ((_AttachedStateWrapper) stateObj).getClazz(); |
| Object restoredObject; |
| try |
| { |
| restoredObject = clazz.newInstance(); |
| } |
| catch (InstantiationException e) |
| { |
| throw new RuntimeException("Could not restore StateHolder of type " + clazz.getName() |
| + " (missing no-args constructor?)", e); |
| } |
| catch (IllegalAccessException e) |
| { |
| throw new RuntimeException(e); |
| } |
| if (restoredObject instanceof StateHolder) |
| { |
| _AttachedStateWrapper wrapper = (_AttachedStateWrapper) stateObj; |
| Object wrappedState = wrapper.getWrappedStateObject(); |
| |
| StateHolder holder = (StateHolder) restoredObject; |
| holder.restoreState(context, wrappedState); |
| } |
| return restoredObject; |
| } |
| else |
| { |
| return stateObj; |
| } |
| } |
| |
| private static final int FULL_STATE_ARRAY_SIZE = 10; |
| |
| /** |
| * Invoked after the render phase has completed, this method returns an object which can be passed to the |
| * restoreState of some other instance of UIComponentBase to reset that object's state to the same values as this |
| * object currently has. |
| */ |
| @Override |
| public Object saveState(FacesContext context) |
| { |
| if (context == null) |
| { |
| throw new NullPointerException ("context"); |
| } |
| |
| if (context.getViewRoot() != null) |
| { |
| if (context.getViewRoot().getResetSaveStateMode() == RESET_MODE_SOFT) |
| { |
| // Force FacesContext cleanup to prevent leak it. |
| setCachedFacesContext(null); |
| // Reset state to recalculate state first. |
| StateHelper stateHelper = getStateHelper(false); |
| if (stateHelper != null) |
| { |
| ((_DeltaStateHelper)stateHelper).resetSoftState(context); |
| } |
| } |
| if (context.getViewRoot().getResetSaveStateMode() == RESET_MODE_HARD) |
| { |
| // Force FacesContext cleanup to prevent leak it. |
| setCachedFacesContext(null); |
| // Reset state to recalculate state first. |
| StateHelper stateHelper = getStateHelper(false); |
| if (stateHelper != null) |
| { |
| ((_DeltaStateHelper)stateHelper).resetHardState(context); |
| } |
| } |
| } |
| if (initialStateMarked()) |
| { |
| //Delta |
| //_id and _clientId was already restored from template |
| //and never changes during component life. |
| Object facesListenersSaved = saveFacesListenersList(context); |
| Object behaviorsMapSaved = saveBehaviorsMap(context); |
| Object systemEventListenerClassMapSaved = saveSystemEventListenerClassMap(context); |
| Object stateHelperSaved = null; |
| StateHelper stateHelper = getStateHelper(false); |
| if (stateHelper != null) |
| { |
| stateHelperSaved = stateHelper.saveState(context); |
| } |
| |
| if (facesListenersSaved == null && stateHelperSaved == null && |
| behaviorsMapSaved == null && systemEventListenerClassMapSaved == null && |
| !((_capabilities & FLAG_IS_RENDERER_TYPE_SET) != 0)) |
| { |
| return null; |
| } |
| |
| Object transientState = null; |
| if (context.getCurrentPhaseId() != null && |
| !PhaseId.RENDER_RESPONSE.equals(context.getCurrentPhaseId())) |
| { |
| transientState = saveTransientState(context); |
| } |
| |
| if (transientState != null) |
| { |
| if ((_capabilities & FLAG_IS_RENDERER_TYPE_SET) != 0) |
| { |
| return new Object[] {facesListenersSaved, stateHelperSaved, behaviorsMapSaved, |
| systemEventListenerClassMapSaved, transientState, |
| _rendererType}; |
| } |
| else |
| { |
| return new Object[] {facesListenersSaved, stateHelperSaved, behaviorsMapSaved, |
| systemEventListenerClassMapSaved, transientState}; |
| } |
| } |
| else |
| { |
| if ((_capabilities & FLAG_IS_RENDERER_TYPE_SET) != 0) |
| { |
| return new Object[] {facesListenersSaved, stateHelperSaved, behaviorsMapSaved, |
| systemEventListenerClassMapSaved, null, |
| _rendererType}; |
| } |
| else |
| { |
| return new Object[] {facesListenersSaved, stateHelperSaved, behaviorsMapSaved, |
| systemEventListenerClassMapSaved}; |
| } |
| } |
| } |
| else |
| { |
| //Full |
| Object values[] = new Object[FULL_STATE_ARRAY_SIZE]; |
| values[0] = saveFacesListenersList(context); |
| StateHelper stateHelper = getStateHelper(false); |
| if (stateHelper != null) |
| { |
| values[1] = stateHelper.saveState(context); |
| } |
| values[2] = saveBehaviorsMap(context); |
| values[3] = saveSystemEventListenerClassMap(context); |
| values[4] = _id; |
| values[5] = _clientId; |
| values[6] = _markCreated; |
| values[7] = _rendererType; |
| values[8] = _capabilities; |
| if (context.getCurrentPhaseId() != null && |
| !PhaseId.RENDER_RESPONSE.equals(context.getCurrentPhaseId())) |
| { |
| values[9] = saveTransientState(context); |
| } |
| |
| return values; |
| } |
| } |
| |
| /** |
| * Invoked in the "restore view" phase, this initialises this object's members from the values saved previously into |
| * the provided state object. |
| * <p> |
| * |
| * @param state |
| * is an object previously returned by the saveState method of this class. |
| */ |
| @SuppressWarnings("unchecked") |
| @Override |
| public void restoreState(FacesContext context, Object state) |
| { |
| if (context == null) |
| { |
| throw new NullPointerException ("context"); |
| } |
| |
| if (state == null) |
| { |
| //Only happens if initialStateMarked return true |
| |
| if (initialStateMarked()) |
| { |
| return; |
| } |
| |
| throw new NullPointerException ("state"); |
| } |
| |
| Object values[] = (Object[]) state; |
| |
| if ( values.length == FULL_STATE_ARRAY_SIZE && initialStateMarked()) |
| { |
| //Delta mode is active, but we are restoring a full state. |
| //we need to clear the initial state, to restore state without |
| //take into account delta. |
| clearInitialState(); |
| } |
| |
| if (values[0] instanceof _AttachedDeltaWrapper) |
| { |
| //Delta: check for null is not necessary since _facesListener field |
| //is only set once and never reset |
| ((StateHolder)_facesListeners).restoreState(context, |
| ((_AttachedDeltaWrapper) values[0]).getWrappedStateObject()); |
| } |
| else if (values[0] != null || (values.length == FULL_STATE_ARRAY_SIZE)) |
| { |
| //Full |
| _facesListeners = (_DeltaList<FacesListener>) |
| restoreAttachedState(context,values[0]); |
| } |
| // Note that if values[0] == null && initialStateMarked(), |
| // means delta is null, not that _facesListeners == null. |
| // We can do this here because _facesListeners instance once |
| // is created is never replaced or set to null. |
| |
| getStateHelper().restoreState(context, values[1]); |
| |
| if (values.length == FULL_STATE_ARRAY_SIZE) |
| { |
| _id = (String) values[4]; |
| _clientId = (String) values[5]; |
| _markCreated = (String) values[6]; |
| _rendererType = (String) values[7]; |
| _capabilities = (Integer) values[8]; |
| } |
| else if (values.length == 6) |
| { |
| restoreTransientState(context, values[4]); |
| _rendererType = (String) values[5]; |
| _capabilities |= FLAG_IS_RENDERER_TYPE_SET; |
| } |
| else if (values.length == 5) |
| { |
| restoreTransientState(context, values[4]); |
| } |
| |
| |
| // rendererType needs to be restored before SystemEventListener, |
| // otherwise UIComponent.getCurrentComponent(context).getRenderer(context) |
| // will not work correctly |
| if (values.length == FULL_STATE_ARRAY_SIZE) |
| { |
| //Full restore |
| restoreFullBehaviorsMap(context, values[2]); |
| restoreFullSystemEventListenerClassMap(context, values[3]); |
| restoreTransientState(context, values[9]); |
| } |
| else |
| { |
| //Delta restore |
| restoreDeltaBehaviorsMap(context, values[2]); |
| restoreDeltaSystemEventListenerClassMap(context, values[3]); |
| } |
| } |
| |
| private Object saveFacesListenersList(FacesContext facesContext) |
| { |
| PartialStateHolder holder = (PartialStateHolder) _facesListeners; |
| if (initialStateMarked() && _facesListeners != null && holder.initialStateMarked()) |
| { |
| Object attachedState = holder.saveState(facesContext); |
| if (attachedState != null) |
| { |
| return new _AttachedDeltaWrapper(_facesListeners.getClass(), attachedState); |
| } |
| //_facesListeners instances once is created never changes, we can return null |
| return null; |
| } |
| else |
| { |
| return saveAttachedState(facesContext,_facesListeners); |
| } |
| } |
| |
| @SuppressWarnings("unchecked") |
| private void restoreFullBehaviorsMap(FacesContext facesContext, Object stateObj) |
| { |
| if (stateObj != null) |
| { |
| Map<String, Object> stateMap = (Map<String, Object>) stateObj; |
| _behaviorsMap = new HashMap<>(stateMap.size(), 1f); |
| _unmodifiableBehaviorsMap = null; |
| for (Map.Entry<String, Object> entry : stateMap.entrySet()) |
| { |
| _behaviorsMap.put(entry.getKey(), |
| (List<ClientBehavior>) restoreAttachedState(facesContext, entry.getValue())); |
| } |
| } |
| else |
| { |
| _behaviorsMap = null; |
| _unmodifiableBehaviorsMap = null; |
| } |
| } |
| |
| @SuppressWarnings("unchecked") |
| private void restoreDeltaBehaviorsMap(FacesContext facesContext, Object stateObj) |
| { |
| if (stateObj != null) |
| { |
| _unmodifiableBehaviorsMap = null; |
| Map<String, Object> stateMap = (Map<String, Object>) stateObj; |
| if (_behaviorsMap == null) |
| { |
| _behaviorsMap = new HashMap<>(stateMap.size(), 1f); |
| } |
| for (Map.Entry<String, Object> entry : stateMap.entrySet()) |
| { |
| Object savedObject = entry.getValue(); |
| if (savedObject instanceof _AttachedDeltaWrapper) |
| { |
| StateHolder holderList = (StateHolder) _behaviorsMap.get(entry.getKey()); |
| holderList.restoreState(facesContext, |
| ((_AttachedDeltaWrapper) savedObject).getWrappedStateObject()); |
| } |
| else |
| { |
| _behaviorsMap.put(entry.getKey(), |
| (List<ClientBehavior>) restoreAttachedState(facesContext, savedObject)); |
| } |
| } |
| } |
| } |
| |
| private Object saveBehaviorsMap(FacesContext facesContext) |
| { |
| if (_behaviorsMap != null) |
| { |
| if (initialStateMarked()) |
| { |
| HashMap<String, Object> stateMap = new HashMap<>(_behaviorsMap.size(), 1); |
| boolean nullDelta = true; |
| for (Map.Entry<String, List<ClientBehavior> > entry : _behaviorsMap.entrySet()) |
| { |
| // The list is always an instance of _DeltaList so we can cast to |
| // PartialStateHolder |
| PartialStateHolder holder = (PartialStateHolder) entry.getValue(); |
| if (holder.initialStateMarked()) |
| { |
| Object attachedState = holder.saveState(facesContext); |
| if (attachedState != null) |
| { |
| stateMap.put(entry.getKey(), new _AttachedDeltaWrapper(_behaviorsMap.getClass(), |
| attachedState)); |
| nullDelta = false; |
| } |
| } |
| else |
| { |
| stateMap.put(entry.getKey(), saveAttachedState(facesContext, holder)); |
| nullDelta = false; |
| } |
| } |
| if (nullDelta) |
| { |
| return null; |
| } |
| return stateMap; |
| } |
| else |
| { |
| //Save it in the traditional way |
| HashMap<String, Object> stateMap = new HashMap<>(_behaviorsMap.size(), 1); |
| for (Map.Entry<String, List<ClientBehavior> > entry : _behaviorsMap.entrySet()) |
| { |
| stateMap.put(entry.getKey(), saveAttachedState(facesContext, entry.getValue())); |
| } |
| return stateMap; |
| } |
| } |
| else |
| { |
| return null; |
| } |
| } |
| |
| @SuppressWarnings("unchecked") |
| private void restoreFullSystemEventListenerClassMap(FacesContext facesContext, Object stateObj) |
| { |
| if (stateObj != null) |
| { |
| Map<Class<? extends SystemEvent>, Object> stateMap = (Map<Class<? extends SystemEvent>, Object>) stateObj; |
| _systemEventListenerClassMap = new HashMap<>(stateMap.size(), 1f); |
| for (Map.Entry<Class<? extends SystemEvent>, Object> entry : stateMap.entrySet()) |
| { |
| _systemEventListenerClassMap.put(entry.getKey(), |
| (List<SystemEventListener>) restoreAttachedState(facesContext, entry.getValue())); |
| } |
| } |
| else |
| { |
| _systemEventListenerClassMap = null; |
| } |
| } |
| |
| @SuppressWarnings("unchecked") |
| private void restoreDeltaSystemEventListenerClassMap(FacesContext facesContext, Object stateObj) |
| { |
| if (stateObj != null) |
| { |
| Map<Class<? extends SystemEvent>, Object> stateMap = (Map<Class<? extends SystemEvent>, Object>) stateObj; |
| if (_systemEventListenerClassMap == null) |
| { |
| _systemEventListenerClassMap = new HashMap<>(stateMap.size(), 1f); |
| } |
| for (Map.Entry<Class<? extends SystemEvent>, Object> entry : stateMap.entrySet()) |
| { |
| Object savedObject = entry.getValue(); |
| if (savedObject instanceof _AttachedDeltaWrapper) |
| { |
| StateHolder holderList = (StateHolder) _systemEventListenerClassMap.get(entry.getKey()); |
| holderList.restoreState(facesContext, |
| ((_AttachedDeltaWrapper) savedObject).getWrappedStateObject()); |
| } |
| else |
| { |
| _systemEventListenerClassMap.put(entry.getKey(), |
| (List<SystemEventListener>) restoreAttachedState(facesContext, savedObject)); |
| } |
| } |
| } |
| } |
| |
| private Object saveSystemEventListenerClassMap(FacesContext facesContext) |
| { |
| if (_systemEventListenerClassMap != null) |
| { |
| if (initialStateMarked()) |
| { |
| HashMap<Class<? extends SystemEvent>, Object> stateMap |
| = new HashMap<>(_systemEventListenerClassMap.size(), 1); |
| boolean nullDelta = true; |
| for (Map.Entry<Class<? extends SystemEvent>, List<SystemEventListener> > entry |
| : _systemEventListenerClassMap.entrySet()) |
| { |
| // The list is always an instance of _DeltaList so we can cast to |
| // PartialStateHolder |
| PartialStateHolder holder = (PartialStateHolder) entry.getValue(); |
| if (holder.initialStateMarked()) |
| { |
| Object attachedState = holder.saveState(facesContext); |
| if (attachedState != null) |
| { |
| stateMap.put(entry.getKey(), |
| new _AttachedDeltaWrapper(_systemEventListenerClassMap.getClass(), attachedState)); |
| nullDelta = false; |
| } |
| } |
| else |
| { |
| stateMap.put(entry.getKey(), saveAttachedState(facesContext, holder)); |
| nullDelta = false; |
| } |
| } |
| if (nullDelta) |
| { |
| return null; |
| } |
| return stateMap; |
| } |
| else |
| { |
| //Save it in the traditional way |
| HashMap<Class<? extends SystemEvent>, Object> stateMap = |
| new HashMap<>(_systemEventListenerClassMap.size(), 1); |
| for (Map.Entry<Class<? extends SystemEvent>, List<SystemEventListener>> entry |
| : _systemEventListenerClassMap.entrySet()) |
| { |
| stateMap.put(entry.getKey(), saveAttachedState(facesContext, entry.getValue())); |
| } |
| return stateMap; |
| } |
| } |
| else |
| { |
| return null; |
| } |
| } |
| |
| /** |
| * @param string |
| * the component id, that should be a vaild one. |
| */ |
| private void isIdValid(String string) |
| { |
| // is there any component identifier ? |
| if (string == null) |
| { |
| return; |
| } |
| |
| // Component identifiers must obey the following syntax restrictions: |
| // 1. Must not be a zero-length String. |
| if (string.length() == 0) |
| { |
| throw new IllegalArgumentException("component identifier must not be a zero-length String"); |
| } |
| |
| // If new id is the same as old it must be valid |
| if (string.equals(_id)) |
| { |
| return; |
| } |
| |
| // 2. First character must be a letter or an underscore ('_'). |
| char firstChar = string.charAt(0); |
| if (!Character.isLetter(firstChar) && firstChar != '_') |
| { |
| throw new IllegalArgumentException("component identifier's first character must be a letter " |
| + "or an underscore ('_')! But it is \"" |
| + firstChar + '"'); |
| } |
| for (int i = 1; i < string.length(); i++) |
| { |
| char c = string.charAt(i); |
| // 3. Subsequent characters must be a letter, a digit, an underscore ('_'), or a dash ('-'). |
| if (!Character.isLetterOrDigit(c) && c != '-' && c != '_') |
| { |
| throw new IllegalArgumentException("Subsequent characters of component identifier must be a letter, " |
| + "a digit, an underscore ('_'), or a dash ('-')! " |
| + "But component identifier \"" + string + "\" contains \"" |
| + c + '"'); |
| } |
| } |
| } |
| |
| private boolean _isPhaseExecutable(FacesContext context) |
| { |
| if (context == null) |
| { |
| throw new NullPointerException("context"); |
| } |
| |
| // If the rendered property of this UIComponent is false, skip further processing. |
| return isRendered(); |
| } |
| |
| @Override |
| boolean isCachedFacesContext() |
| { |
| return _facesContext != null; |
| } |
| |
| @Override |
| void setCachedFacesContext(FacesContext facesContext) |
| { |
| _facesContext = facesContext; |
| } |
| |
| Renderer getCachedRenderer() |
| { |
| return _cachedRenderer; |
| } |
| |
| void setCachedRenderer(Renderer renderer) |
| { |
| _cachedRenderer = renderer; |
| } |
| |
| Boolean isCachedIsRendered() |
| { |
| return _cachedIsRendered; |
| } |
| |
| void setCachedIsRendered(Boolean rendered) |
| { |
| _cachedIsRendered = rendered; |
| } |
| |
| void setOamVfMarkCreated(String markCreated) |
| { |
| _markCreated = markCreated; |
| } |
| |
| String getOamVfMarkCreated() |
| { |
| return _markCreated; |
| } |
| |
| String getOamVfFacetName() |
| { |
| return _facetName; |
| } |
| |
| void setOamVfFacetName(String facetName) |
| { |
| _facetName = facetName; |
| } |
| |
| boolean isOamVfAddedByHandler() |
| { |
| return (_capabilities & FLAG_ADDED_BY_HANDLER) != 0; |
| } |
| |
| void setOamVfAddedByHandler(boolean addedByHandler) |
| { |
| if (addedByHandler) |
| { |
| _capabilities |= FLAG_ADDED_BY_HANDLER; |
| } |
| else |
| { |
| _capabilities &= ~(FLAG_ADDED_BY_HANDLER); |
| } |
| } |
| |
| boolean isOamVfFacetCreatedUIPanel() |
| { |
| return (_capabilities & FLAG_FACET_CREATED_UIPANEL) != 0; |
| } |
| |
| void setOamVfFacetCreatedUIPanel(boolean facetCreatedUIPanel) |
| { |
| if (facetCreatedUIPanel) |
| { |
| _capabilities |= FLAG_FACET_CREATED_UIPANEL; |
| } |
| else |
| { |
| _capabilities &= ~(FLAG_FACET_CREATED_UIPANEL); |
| } |
| } |
| |
| /** |
| * <p> |
| * This gets a single FacesContext-local shared stringbuilder instance, each time you call |
| * _getSharedStringBuilder it sets the length of the stringBuilder instance to 0. |
| * </p><p> |
| * This allows you to use the same StringBuilder instance over and over. |
| * You must call toString on the instance before calling _getSharedStringBuilder again. |
| * </p> |
| * Example that works |
| * <pre><code> |
| * StringBuilder sb1 = _getSharedStringBuilder(); |
| * sb1.append(a).append(b); |
| * String c = sb1.toString(); |
| * |
| * StringBuilder sb2 = _getSharedStringBuilder(); |
| * sb2.append(b).append(a); |
| * String d = sb2.toString(); |
| * </code></pre> |
| * <br><br> |
| * Example that doesn't work, you must call toString on sb1 before |
| * calling _getSharedStringBuilder again. |
| * <pre><code> |
| * StringBuilder sb1 = _getSharedStringBuilder(); |
| * StringBuilder sb2 = _getSharedStringBuilder(); |
| * |
| * sb1.append(a).append(b); |
| * String c = sb1.toString(); |
| * |
| * sb2.append(b).append(a); |
| * String d = sb2.toString(); |
| * </code></pre> |
| * |
| * @param facesContext |
| */ |
| static StringBuilder _getSharedStringBuilder(FacesContext facesContext) |
| { |
| Map<Object, Object> attributes = facesContext.getAttributes(); |
| |
| StringBuilder sb = (StringBuilder) attributes.get(_STRING_BUILDER_KEY); |
| |
| if (sb == null) |
| { |
| sb = new StringBuilder(); |
| attributes.put(_STRING_BUILDER_KEY, sb); |
| } |
| else |
| { |
| // clear out the stringBuilder by setting the length to 0 |
| sb.setLength(0); |
| } |
| |
| return sb; |
| } |
| |
| // ------------------ GENERATED CODE BEGIN (do not modify!) -------------------- |
| |
| private static final Boolean DEFAULT_RENDERED = Boolean.TRUE; |
| |
| @Override |
| public void setRendered(boolean rendered) |
| { |
| getStateHelper().put(PropertyKeys.rendered, rendered ); |
| setCachedIsRendered(null); |
| } |
| |
| @Override |
| public void setRendererType(String rendererType) |
| { |
| this._rendererType = rendererType; |
| if (initialStateMarked()) |
| { |
| //This flag just indicates the rendererType |
| //should be included on the delta |
| _capabilities |= FLAG_IS_RENDERER_TYPE_SET; |
| } |
| setCachedRenderer(null); |
| } |
| |
| // ------------------ GENERATED CODE END --------------------------------------- |
| |
| private Map<String, List<ClientBehavior>> wrapBehaviorsMap() |
| { |
| if (_unmodifiableBehaviorsMap == null) |
| { |
| _unmodifiableBehaviorsMap = Collections.unmodifiableMap(_behaviorsMap); |
| } |
| return _unmodifiableBehaviorsMap; |
| } |
| } |