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

org.apache.myfaces.view.facelets.FaceletCompositionContext 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;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import jakarta.faces.FactoryFinder;

import jakarta.faces.component.UIComponent;
import jakarta.faces.component.UIViewRoot;
import jakarta.faces.component.UniqueIdVendor;
import jakarta.faces.component.visit.VisitContextFactory;
import jakarta.faces.context.FacesContext;
import jakarta.faces.view.AttachedObjectHandler;
import jakarta.faces.view.EditableValueHolderAttachedObjectHandler;
import jakarta.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> 
        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 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 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 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);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy