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

org.apache.myfaces.context.RequestViewContext 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.context;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import jakarta.faces.application.ResourceDependency;
import jakarta.faces.component.UIComponent;
import jakarta.faces.component.UIViewRoot;
import jakarta.faces.component.visit.VisitCallback;
import jakarta.faces.component.visit.VisitContext;
import jakarta.faces.component.visit.VisitResult;
import jakarta.faces.context.FacesContext;
import org.apache.myfaces.component.visit.MyFacesVisitHints;
import org.apache.myfaces.view.facelets.impl.FaceletCompositionContextImpl;

/**
 *
 * @author  Leonardo Uribe (latest modification by $Author$)
 * @version $Revision$ $Date$
 * @since 2.0.2
 */
public class RequestViewContext
{
    public static final String VIEW_CONTEXT_KEY = "oam.VIEW_CONTEXT";
    
    public static final String RESOURCE_DEPENDENCY_INSPECTED_CLASS = "oam.RDClass";

    private RequestViewMetadata requestViewMetadata;
    
    private Map renderTargetMap = null;
    private Map> renderTargetMapComponents = null;
    
    public RequestViewContext()
    {
        this.requestViewMetadata = new RequestViewMetadata();
    }
    
    public RequestViewContext(RequestViewMetadata rvm)
    {
        this.requestViewMetadata = new RequestViewMetadata();
    }

    public static RequestViewContext getCurrentInstance()
    {
        return getCurrentInstance(FacesContext.getCurrentInstance());
    }
    
    public static RequestViewContext getCurrentInstance(FacesContext ctx)
    {
        return getCurrentInstance(ctx, ctx.getViewRoot());
    }
    
    @SuppressWarnings("unchecked")
    public static RequestViewContext getCurrentInstance(FacesContext ctx, UIViewRoot root)
    {
        return getCurrentInstance(ctx, root, true);
    }
    
    public static RequestViewContext getCurrentInstance(FacesContext ctx, UIViewRoot root, boolean create)
    {
        Map map =
                (Map) ctx.getAttributes().get(VIEW_CONTEXT_KEY);
        
        if (create && map == null)
        {
            map = new HashMap<>(5);
            ctx.getAttributes().put(VIEW_CONTEXT_KEY, map);
        }

        if (map != null)
        {
            RequestViewContext rvc = map.get(root); 
            if (create && rvc == null)
            {
                rvc = new RequestViewContext();
                map.put(root, rvc);
            }
            return rvc;
        }

        return null;
    }
    
    public static RequestViewContext newInstance(RequestViewMetadata rvm)
    {
        RequestViewContext clone = new RequestViewContext(rvm.cloneInstance());
        return clone;
    }
    
    public static void setCurrentInstance(FacesContext ctx, UIViewRoot root, RequestViewContext rvc)
    {
        Map map = (Map) ctx.getAttributes()
                .computeIfAbsent(VIEW_CONTEXT_KEY, k -> new HashMap<>());
        map.put(root, rvc);
    }

    public boolean isResourceDependencyAlreadyProcessed(ResourceDependency dependency)
    {
        return requestViewMetadata.isResourceDependencyAlreadyProcessed(dependency);
    }
    
    public void setResourceDependencyAsProcessed(ResourceDependency dependency)
    {
        requestViewMetadata.setResourceDependencyAsProcessed(dependency);
    }

    public boolean isClassAlreadyProcessed(Class inspectedClass)
    {
        return requestViewMetadata.isClassAlreadyProcessed(inspectedClass);
    }

    public void setClassProcessed(Class inspectedClass)
    {
        requestViewMetadata.setClassProcessed(inspectedClass);
    }
    
    public boolean isRenderTarget(String target)
    {
        if (renderTargetMap != null)
        {
            return Boolean.TRUE.equals(renderTargetMap.get(target));
        }
        return false;
    }
    
    public void setRenderTarget(String target, boolean value, UIComponent component)
    {
        if (renderTargetMap == null)
        {
            renderTargetMap = new HashMap<>(8);
        }
        renderTargetMap.put(target, value);

        if (renderTargetMapComponents == null)
        {
            renderTargetMapComponents = new HashMap<>(8);
        }
        
        List componentList = renderTargetMapComponents.computeIfAbsent(target, k -> new ArrayList<>(8));
        if (!componentList.contains(component))
        {
            componentList.add(component);
        }
    }
    
    public List getRenderTargetComponentList(String target)
    {
        if (renderTargetMapComponents == null)
        {
            return Collections.emptyList();
        }
        List list = renderTargetMapComponents.get(target);
        return list != null ? list : Collections.emptyList();
    }
    
    /**
     * Scans UIViewRoot facets with added component resources by the effect of
     * ResourceDependency annotation, and register the associated inspected classes
     * so new component resources will not be added to the component tree again and again.
     * 
     * @param facesContext
     * @param root 
     */
    public void refreshRequestViewContext(FacesContext facesContext, UIViewRoot root)
    {
        RefreshViewContextCallback callback = null;
        
        for (Map.Entry entry : root.getFacets().entrySet())
        {
            UIComponent facet = entry.getValue();
            if (facet.getId() != null
                    && facet.getId().startsWith(FaceletCompositionContextImpl.JAKARTA_FACES_LOCATION_PREFIX))
            {
                try
                {
                    facesContext.getAttributes().put(MyFacesVisitHints.SKIP_ITERATION_HINT, Boolean.TRUE);

                    if (callback == null)
                    {
                        callback = new RefreshViewContextCallback();
                    }

                    VisitContext visitContext = VisitContext.createVisitContext(facesContext,
                            null, MyFacesVisitHints.SET_SKIP_ITERATION);
                    facet.visitTree(visitContext, callback);
                }
                finally
                {
                    // We must remove hint in finally, because an exception can break this phase,
                    // but lifecycle can continue, if custom exception handler swallows the exception
                    facesContext.getAttributes().remove(MyFacesVisitHints.SKIP_ITERATION_HINT);
                }
            }
        }
    }
    
    private class RefreshViewContextCallback implements VisitCallback
    {
        @Override
        public VisitResult visit(VisitContext context, UIComponent target)
        {
            Class inspectedClass = (Class)target.getAttributes().get(RESOURCE_DEPENDENCY_INSPECTED_CLASS);
            if (inspectedClass != null)
            {
                setClassProcessed(inspectedClass);
            }            
            return VisitResult.ACCEPT;
        }
    }
    
    public RequestViewMetadata getRequestViewMetadata()
    {
        return requestViewMetadata;
    }

    public void setRequestViewMetadata(RequestViewMetadata requestViewMetadata)
    {
        this.requestViewMetadata = requestViewMetadata;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy