blob: c65a61465680d29a92fa2d10b8372d0ca2fde981 [file] [log] [blame]
/*
* 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;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.faces.FactoryFinder;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.component.UniqueIdVendor;
import javax.faces.component.visit.VisitContextFactory;
import javax.faces.context.FacesContext;
import javax.faces.view.AttachedObjectHandler;
import javax.faces.view.EditableValueHolderAttachedObjectHandler;
import javax.faces.view.facelets.FaceletContext;
/**
* @since 2.0.1
* @author Leonardo Uribe (latest modification by $Author$)
* @version $Revision$ $Date$
*/
abstract public class FaceletCompositionContext
{
static protected final String FACELET_COMPOSITION_CONTEXT_KEY = "oam.facelets.FACELET_COMPOSITION_CONTEXT";
protected FaceletCompositionContext()
{
}
static public FaceletCompositionContext getCurrentInstance()
{
return (FaceletCompositionContext)
FacesContext.getCurrentInstance().getAttributes().get(FACELET_COMPOSITION_CONTEXT_KEY);
}
static public FaceletCompositionContext getCurrentInstance(FaceletContext ctx)
{
if (ctx instanceof AbstractFaceletContext)
{
return ((AbstractFaceletContext)ctx).getFaceletCompositionContext();
}
else
{
// Here we have two choices: retrieve it throught ThreadLocal var
// or use the attribute value on FacesContext, but it seems better
// use the FacesContext attribute map.
return (FaceletCompositionContext)
ctx.getFacesContext().getAttributes().get(FACELET_COMPOSITION_CONTEXT_KEY);
}
}
static public FaceletCompositionContext getCurrentInstance(FacesContext ctx)
{
return (FaceletCompositionContext) ctx.getAttributes().get(FACELET_COMPOSITION_CONTEXT_KEY);
}
public void init(FacesContext facesContext)
{
facesContext.getAttributes().put(
FaceletCompositionContext.FACELET_COMPOSITION_CONTEXT_KEY, this);
}
/**
* Releases the MyFaceletContext object. This method must only
* be called by the code that created the MyFaceletContext.
*/
public void release(FacesContext facesContext)
{
facesContext.getAttributes().remove(FACELET_COMPOSITION_CONTEXT_KEY);
}
public abstract FaceletFactory getFaceletFactory();
/**
* Return the composite component being applied on the current facelet.
*
* Note this is different to UIComponent.getCurrentCompositeComponent, because a composite
* component is added to the stack each time a composite:implementation tag handler is applied.
*
* This could be used by InsertChildrenHandler and InsertFacetHandler to retrieve the current
* composite component to be applied.
*
* @since 2.0.1
* @return
*/
public abstract UIComponent getCompositeComponentFromStack();
/**
* @since 2.0.1
* @param parent
*/
public abstract void pushCompositeComponentToStack(UIComponent parent);
/**
* @since 2.0.1
*/
public abstract void popCompositeComponentToStack();
/**
* Return the latest UniqueIdVendor created from stack. The reason why we need to keep
* a UniqueIdVendor stack is because we need to look the closest one in ComponentTagHandlerDelegate.
* Note that facelets tree is built from leafs to root, that means use UIComponent.getParent() does not
* always return parent components.
*
* @since 2.0.1
* @return
*/
public abstract UniqueIdVendor getUniqueIdVendorFromStack();
/**
* @since 2.0.1
* @param parent
*/
public abstract void pushUniqueIdVendorToStack(UniqueIdVendor parent);
/**
* @since 2.0.1
*/
public abstract void popUniqueIdVendorToStack();
/**
* Removes top of stack.
* @since 2.0.1
*/
public abstract void popEnclosingValidatorIdToStack();
/**
* Pushes validatorId to the stack of all enclosing validatorIds.
*
* @param validatorId
* @param attachedObjectHandler
* @since 2.0.10
*/
public abstract void pushEnclosingValidatorIdToStack(String validatorId,
EditableValueHolderAttachedObjectHandler attachedObjectHandler);
/**
* Gets all validationIds with its associated EditableValueHolderAttachedObjectHandler from the stack.
*
* @return
* @since 2.0.10
*/
public abstract Iterator<Map.Entry<String, EditableValueHolderAttachedObjectHandler>>
getEnclosingValidatorIdsAndHandlers();
/**
*
* @param id
* @return
* @since 2.0.10
*/
public abstract boolean containsEnclosingValidatorId(String id);
/**
* Check if this build is being refreshed, adding transient components
* and adding/removing components under c:if or c:forEach or not.
*
* @return
* @since 2.0.1
*/
public abstract boolean isRefreshingTransientBuild();
/**
* Check if this build should be marked as initial state. In other words,
* all components must call UIComponent.markInitialState.
*
* @return
* @since 2.0.1
*/
public abstract boolean isMarkInitialState();
public void setMarkInitialState(boolean value)
{
}
/**
* Check if the current view will be refreshed with partial state saving.
*
* This param is used in two posible events:
*
* 1. To notify UIInstruction instances to look for instances moved by
* cc:insertChildren or cc:insertFacet.
* 2. To do proper actions when a tag that could change tree structure is applied
* (c:if, c:forEach...)
*
* @return
* @since 2.0.1
*/
public abstract boolean isRefreshTransientBuildOnPSS();
/**
*
* @since 2.0.12, 2.1.6
* @return
*/
public boolean isRefreshTransientBuildOnPSSPreserveState()
{
return false;
}
/**
* Check if we are using partial state saving on this view
*
* @return
* @since 2.0.1
*/
public abstract boolean isUsingPSSOnThisView();
/**
* @since 2.0.1
* @return
*/
public abstract boolean isMarkInitialStateAndIsRefreshTransientBuildOnPSS();
/**
* Add to the composite component parent this handler, so it will be processed later when
* ViewDeclarationLanguage.retargetAttachedObjects is called.
*
* Tag Handlers exposing attached objects should call this method to expose them when the
* parent to be applied is a composite components.
*
* @since 2.0.2
* @param compositeComponentParent
* @param handler
*/
public abstract void addAttachedObjectHandler(UIComponent compositeComponentParent, AttachedObjectHandler handler);
/**
* Remove from the composite component parent the list of attached handlers.
*
* @since 2.0.2
* @param compositeComponentParent
*/
public abstract void removeAttachedObjectHandlers(UIComponent compositeComponentParent);
/**
* Retrieve the list of object handlers attached to a composite component parent.
*
* @since 2.0.2
* @param compositeComponentParent
*/
public abstract List<AttachedObjectHandler> getAttachedObjectHandlers(UIComponent compositeComponentParent);
/**
* Marks all direct children and Facets with an attribute for deletion.
*
* @since 2.0.2
* @see #finalizeForDeletion(UIComponent)
* @param component
* UIComponent to mark
*/
public abstract void markForDeletion(UIComponent component);
/**
* Used in conjunction with markForDeletion where any UIComponent marked will be removed.
*
* @since 2.0.2
* @param component
* UIComponent to finalize
*/
public abstract void finalizeForDeletion(UIComponent component);
public void removeComponentForDeletion(UIComponent component)
{
}
/**
* Marks the given resource for deletion. Is to be used for relocatable
* components instead of {@link #markForDeletion(UIComponent)}.
*
* @since 2.0.17 2.1.11
* @param component
* UIComponent to finalize
*/
public void markRelocatableResourceForDeletion(UIComponent component)
{
}
/**
* Used to clean up all unused relocatable components on the root component.
*
* @since 2.0.17 2.1.11
* @param root
* UIComponent to finalize (root component)
*/
public void finalizeRelocatableResourcesForDeletion(UIViewRoot root)
{
}
/**
* Add a method expression as targeted for the provided composite component
*
* @since 2.0.3
* @param targetedComponent
* @param attributeName
* @param backingValue A value that could be useful to revert its effects.
*/
public abstract void addMethodExpressionTargeted(UIComponent targetedComponent, String attributeName,
Object backingValue);
/**
* Check if the MethodExpression attribute has been applied using vdl.retargetMethodExpression
*
* @since 2.0.3
* @param compositeComponentParent
* @param attributeName
* @return
*/
public abstract boolean isMethodExpressionAttributeApplied(UIComponent compositeComponentParent,
String attributeName);
/**
* Mark the MethodExpression attribute as applied using vdl.retargetMethodExpression
*
* @since 2.0.3
* @param compositeComponentParent
* @param attributeName
*/
public abstract void markMethodExpressionAttribute(UIComponent compositeComponentParent, String attributeName);
/**
* Clear the MethodExpression attribute to call vdl.retargetMethodExpression again
*
* @since 2.0.3
* @param compositeComponentParent
* @param attributeName
*/
public abstract void clearMethodExpressionAttribute(UIComponent compositeComponentParent, String attributeName);
/**
* Remove a method expression as targeted for the provided composite component
*
* @since 2.0.3
* @param targetedComponent
* @param attributeName
* @return A value that could be useful to revert its effects.
*/
public abstract Object removeMethodExpressionTargeted(UIComponent targetedComponent, String attributeName);
/**
* Indicates if a EL Expression can be or not cached by facelets vdl.
*
* @since 2.0.8
* @return
*/
public ELExpressionCacheMode getELExpressionCacheMode()
{
return ELExpressionCacheMode.noCache;
}
/**
*
* @since 2.0.9
* @return
*/
public boolean isWrapTagExceptionsAsContextAware()
{
return true;
}
/**
* Start a new unique id section, which means a new counter is used to
* generate unique ids to components
*
* @since 2.0.10, 2.1.4
* @return
*/
public String startComponentUniqueIdSection()
{
return null;
}
/**
* Start a new unique id section, which means a new counter is used to
* generate unique ids to components, but appending a base to the
* new counter.
*
* @since 2.2.0
* @return
*/
public String startComponentUniqueIdSection(String base)
{
return null;
}
/**
* @since 2.2.0
* @param base
*/
public void endComponentUniqueIdSection(String base)
{
}
/**
* Generate a unique id that will be used later to derive a unique id per tag
* by FaceletContext.generateUniqueId(). This generator ensures uniqueness per
* view but FaceletContext.generateUniqueId() ensures uniqueness per view and
* per facelet hierarchy, so different included facelets will generate different
* ids.
*
* @return
*/
public String generateUniqueId()
{
return null;
}
public void generateUniqueId(StringBuilder builderToAdd)
{
}
/**
* Generate a unique id for component instances.
*
* @return
*/
public String generateUniqueComponentId()
{
return null;
}
/**
* Ends the current unique id section, so the previous counter will be used
* to generate unique ids to components.
*/
public void endComponentUniqueIdSection()
{
}
/**
* Set the iterator used to retrieve unique ids.
*
* since 2.1.7, 2.0.13
* @param uniqueIdsIterator
*/
public void setUniqueIdsIterator(Iterator<String> uniqueIdsIterator)
{
}
/**
* Activater record unique id mode, so an structure will be
* used to hold those values.
*
* since 2.1.7, 2.0.13
*/
public void initUniqueIdRecording()
{
}
/**
* Add an unique id to the list if recording is enabled,
* if recording is not enabled it has no effect.
*
* since 2.1.7, 2.0.13
* @param uniqueId
*/
public void addUniqueId(String uniqueId)
{
}
/**
* Return the unique id from the iterator if applies
*
* since 2.1.7, 2.0.13
* @return
*/
public String getUniqueIdFromIterator()
{
return null;
}
/**
* Return the list of unique ids
*
* since 2.1.7, 2.0.13
* @return
*/
public List<String> getUniqueIdList()
{
return null;
}
/**
* Increment the unique id without construct it.
*
* since 2.1.7, 2.0.13
*/
public void incrementUniqueId()
{
}
/**
* Check if the facelet is building view metadata
*
* since 2.1.7, 2.0.13
* @return
*/
public boolean isBuildingViewMetadata()
{
return FaceletViewDeclarationLanguage.isBuildingViewMetadata(
FacesContext.getCurrentInstance());
}
/**
* Call this method to indicate a f:metadata section is about to be processed
*
* since 2.1.7, 2.0.13
*/
public void startMetadataSection()
{
}
/**
* Call this method to indicate f:metadata section has been already processed
*
* since 2.1.7, 2.0.13
*/
public void endMetadataSection()
{
}
/**
* Check if the component is created inside f:metadata section
*
* since 2.1.7, 2.0.13
* @return
*/
public boolean isInMetadataSection()
{
return false;
}
/**
* Check if the section to be processed is being refreshed.
*
* since 2.1.7, 2.0.13
* @return
*/
public boolean isRefreshingSection()
{
return isRefreshingTransientBuild() || (!isBuildingViewMetadata() && isInMetadataSection());
}
/**
*
* @since 2.1.8, 2.0.14
*/
public void incrementUniqueComponentId()
{
}
public StringBuilder getSharedStringBuilder()
{
return new StringBuilder();
}
/**
* Returns the current nesting level of composite components found. If
* no composite component has been used returns 0.
*
* @since 2.1.9, 2.0.15
*/
public int getCompositeComponentLevel()
{
return 0;
}
public boolean isDynamicCompositeComponentHandler()
{
return false;
}
public void setDynamicCompositeComponentHandler(boolean value)
{
}
public void pushDynamicComponentSection(String baseKey)
{
}
public void popDynamicComponentSection()
{
}
/**
* Check if the algorithm is applying a dynamic component and the current component
* is the top level one. This is necessary to avoid remove/add the component under
* a refresh and in that way change the position of the component in the tree. Remember
* facelets algorithm removes/add components to sort the components under a refresh, but
* in this case, it is up to the user to put the component in the tree, so the idea is
* do not make interference with the user's code. Note if the dynamic content is wrapped
* by a generated panel, the top level component is the wrapper itself, which has no
* attached tag handler.
*
* @since 2.2
* @return
*/
public boolean isDynamicComponentTopLevel()
{
return false;
}
public void setDynamicComponentTopLevel(boolean value)
{
}
/**
* Indicate if the current facelet section is a dynamic component section,
* which means it was added to the component tree using vdl.createComponent(...);
*
* @since 2.2
* @return
*/
public boolean isDynamicComponentSection()
{
return false;
}
public UIViewRoot getViewRoot(FacesContext facesContext)
{
return facesContext.getViewRoot();
}
public void setViewRoot(UIViewRoot root)
{
}
public VisitContextFactory getVisitContextFactory()
{
return (VisitContextFactory)FactoryFinder.getFactory(FactoryFinder.VISIT_CONTEXT_FACTORY);
}
}