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

org.primefaces.component.behavior.ajax.AjaxBehaviorHandler Maven / Gradle / Ivy

There is a newer version: 14.0.0-RC3
Show newest version
/*
 * Copyright 2009-2013 PrimeTek.
 *
 * Licensed 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.primefaces.component.behavior.ajax;

import java.beans.BeanDescriptor;
import java.beans.BeanInfo;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.el.MethodExpression;
import javax.faces.application.Application;
import javax.faces.component.UIComponent;
import javax.faces.component.behavior.ClientBehaviorHolder;
import javax.faces.context.FacesContext;
import javax.faces.event.AjaxBehaviorEvent;
import javax.faces.view.AttachedObjectHandler;
import javax.faces.view.AttachedObjectTarget;
import javax.faces.view.BehaviorHolderAttachedObjectHandler;
import javax.faces.view.BehaviorHolderAttachedObjectTarget;
import javax.faces.view.facelets.BehaviorConfig;
import javax.faces.view.facelets.ComponentHandler;
import javax.faces.view.facelets.FaceletContext;
import javax.faces.view.facelets.TagAttribute;
import javax.faces.view.facelets.TagException;
import javax.faces.view.facelets.TagHandler;

public class AjaxBehaviorHandler extends TagHandler implements BehaviorHolderAttachedObjectHandler  {

    private static Method MYFACES_GET_COMPOSITION_CONTEXT_INSTANCE;
    private static Method MYFACES_ADD_ATTACHED_OBJECT_HANDLER;
	
    private final TagAttribute event;
    private final TagAttribute process;
    private final TagAttribute update;
    private final TagAttribute onstart;
    private final TagAttribute onerror;
    private final TagAttribute onsuccess;
    private final TagAttribute oncomplete;
    private final TagAttribute disabled;
    private final TagAttribute immediate;
    private final TagAttribute listener;
    private final TagAttribute global;
    private final TagAttribute async;
    private final TagAttribute partialSubmit;
    private final TagAttribute resetValues;
    private final TagAttribute ignoreAutoUpdate;
    
    public AjaxBehaviorHandler(BehaviorConfig config) {
        super(config);
        this.event = this.getAttribute("event");
        this.process = this.getAttribute("process");
        this.update = this.getAttribute("update");
        this.onstart = this.getAttribute("onstart");
        this.onerror = this.getAttribute("onerror");
        this.onsuccess = this.getAttribute("onsuccess");
        this.oncomplete = this.getAttribute("oncomplete");
        this.disabled = this.getAttribute("disabled");
        this.immediate = this.getAttribute("immediate");
        this.listener = this.getAttribute("listener");
        this.global = this.getAttribute("global");
        this.async = this.getAttribute("async");
        this.partialSubmit = this.getAttribute("partialSubmit");
        this.resetValues = this.getAttribute("resetValues");
        this.ignoreAutoUpdate = this.getAttribute("ignoreAutoUpdate");
    }
    
    public void apply(FaceletContext ctx, UIComponent parent) throws IOException {
        if(!ComponentHandler.isNew(parent)) {
            return;
        }
                
        String eventName = getEventName();
        
        if(UIComponent.isCompositeComponent(parent)) {
            boolean tagApplied = false;
            if(parent instanceof ClientBehaviorHolder) {
                applyAttachedObject(ctx, parent, eventName);
                tagApplied = true;
            }
            
            BeanInfo componentBeanInfo = (BeanInfo) parent.getAttributes().get(UIComponent.BEANINFO_KEY);
            if(null == componentBeanInfo) {
                throw new TagException(tag, "Composite component does not have BeanInfo attribute");
            }
            
            BeanDescriptor componentDescriptor = componentBeanInfo.getBeanDescriptor();
            if(null == componentDescriptor) {
                throw new TagException(tag, "Composite component BeanInfo does not have BeanDescriptor");
            }
            
            List targetList = (List)componentDescriptor.getValue(AttachedObjectTarget.ATTACHED_OBJECT_TARGETS_KEY);
            if(null == targetList && !tagApplied) {
                throw new TagException(tag, "Composite component does not support behavior events");
            }
            
            boolean supportedEvent = false;
            for(AttachedObjectTarget target : targetList) {
                if(target instanceof BehaviorHolderAttachedObjectTarget) {
                    BehaviorHolderAttachedObjectTarget behaviorTarget = (BehaviorHolderAttachedObjectTarget) target;
                    if((null != eventName && eventName.equals(behaviorTarget.getName()))
                        || (null == eventName && behaviorTarget.isDefaultEvent())) {
                        supportedEvent = true;
                        break;
                    }
                }
            }
            
            if(supportedEvent) {
                //Workaround to implementation specific composite component handlers
                FacesContext context = FacesContext.getCurrentInstance();
                if(context.getExternalContext().getApplicationMap().containsKey("com.sun.faces.ApplicationAssociate")) {
                    getAttachedObjectHandlers(parent).add(this);
                } 
                else {
                    try {
                    	if (MYFACES_GET_COMPOSITION_CONTEXT_INSTANCE == null || MYFACES_ADD_ATTACHED_OBJECT_HANDLER == null) {
                    		Class clazz = Class.forName("org.apache.myfaces.view.facelets.FaceletCompositionContext");
                    		MYFACES_GET_COMPOSITION_CONTEXT_INSTANCE = clazz.getDeclaredMethod("getCurrentInstance", FaceletContext.class);
                    		MYFACES_ADD_ATTACHED_OBJECT_HANDLER = clazz.getDeclaredMethod("addAttachedObjectHandler", UIComponent.class, AttachedObjectHandler.class);;
                    	}

                        Object faceletCompositionContextInstance = MYFACES_GET_COMPOSITION_CONTEXT_INSTANCE.invoke(null, ctx);
                        MYFACES_ADD_ATTACHED_OBJECT_HANDLER.invoke(faceletCompositionContextInstance, parent, this);
                    } 
                    catch (Exception ex) {
                        Logger.getLogger(AjaxBehaviorHandler.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    
                }
            } 
            else {
                if(!tagApplied) {
                    throw new TagException(tag, "Composite component does not support event " + eventName);
                }
            }
        }
        else if(parent instanceof ClientBehaviorHolder) {
            applyAttachedObject(ctx, parent, eventName);
        } 
        else {
            throw new TagException(this.tag, "Unable to attach  to non-ClientBehaviorHolder parent");
        }
    }

    public String getEventName() {
        return (this.event != null) ? this.event.getValue() : null;
    }

    public void applyAttachedObject(FaceletContext context, UIComponent component, String eventName) {                
        ClientBehaviorHolder holder = (ClientBehaviorHolder) component;

        if(null == eventName) {
            eventName = holder.getDefaultEventName();
            if (null == eventName) {
                throw new TagException(this.tag, "Event attribute could not be determined: "  + eventName);
            }
        } else {
            Collection eventNames = holder.getEventNames();
            if (!eventNames.contains(eventName)) {
                throw new TagException(this.tag,  "Event:" + eventName + " is not supported.");
            }
        }

        AjaxBehavior ajaxBehavior = createAjaxBehavior(context, eventName);
        holder.addClientBehavior(eventName, ajaxBehavior);
    }
    
    // Construct our AjaxBehavior from tag parameters.
    private AjaxBehavior createAjaxBehavior(FaceletContext ctx, String eventName) {
        Application application = ctx.getFacesContext().getApplication();
        AjaxBehavior behavior = (AjaxBehavior)application.createBehavior(AjaxBehavior.BEHAVIOR_ID);

        setBehaviorAttribute(ctx, behavior, this.process, String.class);
        setBehaviorAttribute(ctx, behavior, this.update, String.class);
        setBehaviorAttribute(ctx, behavior, this.onstart, String.class);
        setBehaviorAttribute(ctx, behavior, this.onerror, String.class);
        setBehaviorAttribute(ctx, behavior, this.onsuccess, String.class);
        setBehaviorAttribute(ctx, behavior, this.oncomplete, String.class);
        setBehaviorAttribute(ctx, behavior, this.disabled, Boolean.class);
        setBehaviorAttribute(ctx, behavior, this.immediate, Boolean.class);
        setBehaviorAttribute(ctx, behavior, this.global, Boolean.class);
        setBehaviorAttribute(ctx, behavior, this.async, Boolean.class);
        setBehaviorAttribute(ctx, behavior, this.partialSubmit, Boolean.class);
        setBehaviorAttribute(ctx, behavior, this.listener, MethodExpression.class);
        setBehaviorAttribute(ctx, behavior, this.resetValues, Boolean.class);
        setBehaviorAttribute(ctx, behavior, this.ignoreAutoUpdate, Boolean.class);
        
        if(listener != null) {
            behavior.addAjaxBehaviorListener(new AjaxBehaviorListenerImpl(
                this.listener.getMethodExpression(ctx, Object.class, new Class[] {}) ,
                this.listener.getMethodExpression(ctx, Object.class, new Class[] {AjaxBehaviorEvent.class})));
        }
        
        return behavior;
    }

    public String getFor() {
        return null;
    }

    public void applyAttachedObject(FacesContext context, UIComponent parent) {
        FaceletContext ctx = getFaceletContext(context);
        
        applyAttachedObject(ctx, parent, getEventName());
    }
    
    private void setBehaviorAttribute(FaceletContext ctx, AjaxBehavior behavior, TagAttribute attr, Class type) {
    	if(attr != null) {
            behavior.setValueExpression(attr.getLocalName(), attr.getValueExpression(ctx, type));
        }    
    }
    
    public List getAttachedObjectHandlers(UIComponent component) {
        return getAttachedObjectHandlers(component, true);
    }
    
    public List getAttachedObjectHandlers(UIComponent component, boolean create) {
        Map attrs = component.getAttributes();
        List result = (List) attrs.get("javax.faces.RetargetableHandlers");

        if (result == null) {
            if (create) {
                result = new ArrayList();
                attrs.put("javax.faces.RetargetableHandlers", result);
            } else {
                result = Collections.emptyList();
            }
        }
        return result;
    }
    
    private FaceletContext getFaceletContext(FacesContext context) {
        FaceletContext faceletContext = (FaceletContext) context.getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);
        if(faceletContext == null) {
            faceletContext = (FaceletContext) context.getAttributes().get("com.sun.faces.facelets.FACELET_CONTEXT");
        }
        
        return faceletContext;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy