001    package org.apache.myfaces.tobago.ajax.api;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one or more
005     * contributor license agreements.  See the NOTICE file distributed with
006     * this work for additional information regarding copyright ownership.
007     * The ASF licenses this file to You under the Apache License, Version 2.0
008     * (the "License"); you may not use this file except in compliance with
009     * the License.  You may obtain a copy of the License at
010     *
011     *      http://www.apache.org/licenses/LICENSE-2.0
012     *
013     * Unless required by applicable law or agreed to in writing, software
014     * distributed under the License is distributed on an "AS IS" BASIS,
015     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016     * See the License for the specific language governing permissions and
017     * limitations under the License.
018     */
019    
020    import org.apache.commons.logging.Log;
021    import org.apache.commons.logging.LogFactory;
022    import org.apache.myfaces.tobago.component.ComponentUtil;
023    import org.apache.myfaces.tobago.component.UIViewRoot;
024    
025    import javax.faces.component.UIComponent;
026    import javax.faces.context.FacesContext;
027    import javax.faces.event.PhaseId;
028    import javax.faces.render.Renderer;
029    import java.io.IOException;
030    import java.util.Iterator;
031    import java.util.Map;
032    import java.util.StringTokenizer;
033    import java.util.HashMap;
034    
035    /*
036     * Created by IntelliJ IDEA.
037     * User: weber
038     * Date: 12.10.2005
039     * Time: 13:11:05
040     */
041    public class AjaxUtils {
042    
043      private static final Log LOG = LogFactory.getLog(AjaxUtils.class);
044    
045      public static final String AJAX_COMPONENTS = AjaxUtils.class.getName() + ".AJAX_COMPONENTS";
046    
047      public static void checkParamValidity(FacesContext facesContext, UIComponent uiComponent, Class compClass) {
048        if (facesContext == null) {
049          throw new NullPointerException("facesContext may not be null");
050        }
051        if (uiComponent == null) {
052          throw new NullPointerException("uiComponent may not be null");
053        }
054        //if (compClass != null && !(compClass.isAssignableFrom(uiComponent.getClass())))
055        // why isAssignableFrom with additional getClass method call if isInstance does the same?
056        if (compClass != null && !(compClass.isInstance(uiComponent))) {
057          throw new IllegalArgumentException("uiComponent : "
058              + uiComponent.getClass().getName() + " is not instance of "
059              + compClass.getName() + " as it should be");
060        }
061      }
062    
063    
064    
065    
066      public static void encodeAjaxComponent(FacesContext facesContext, UIComponent component) throws IOException {
067        if (facesContext == null) {
068          throw new NullPointerException("facesContext");
069        }
070        if (!component.isRendered()) {
071          return;
072        }
073        Renderer renderer = ComponentUtil.getRenderer(facesContext, component);
074        if (renderer != null && renderer instanceof AjaxRenderer) {
075          ((AjaxRenderer) renderer).encodeAjax(facesContext, component);
076        }
077      }
078    
079    
080      public static void processAjax(FacesContext facesContext, UIComponent component)
081          throws IOException {
082        if (component instanceof AjaxComponent) {
083          ((AjaxComponent) component).processAjax(facesContext);
084        } else {
085          processAjaxOnChildren(facesContext, component);
086        }
087      }
088    
089      public static void processActiveAjaxComponent(FacesContext facesContext,
090                                                    UIComponent component)
091          throws IOException {
092    
093        if (component instanceof AjaxComponent) {
094          final UIViewRoot viewRoot = (UIViewRoot) facesContext.getViewRoot();
095    
096          // TODO: handle phaseListeners ??
097    
098          if (!facesContext.getRenderResponse()) {
099            component.processValidators(facesContext);
100            viewRoot.broadcastEventsForPhase(facesContext, PhaseId.PROCESS_VALIDATIONS);
101          } else if (LOG.isDebugEnabled()) {
102            LOG.debug("Skipping validate");
103          }
104    
105          if (!facesContext.getRenderResponse()) {
106            component.processUpdates(facesContext);
107            viewRoot.broadcastEventsForPhase(facesContext, PhaseId.UPDATE_MODEL_VALUES);
108          } else if (LOG.isDebugEnabled()) {
109            LOG.debug("Skipping updates");
110          }
111    
112          if (!facesContext.getRenderResponse()) {
113            viewRoot.processApplication(facesContext);
114          } else if (LOG.isDebugEnabled()) {
115            LOG.debug("Skipping application");
116          }
117    
118          ((AjaxComponent) component).encodeAjax(facesContext);
119        } else {
120          LOG.error("Can't process non AjaxComponent : \""
121              + component.getClientId(facesContext) + "\" = "
122              + component.getClass().getName());
123        }
124      }
125    
126      public static void processAjaxOnChildren(FacesContext facesContext,
127          UIComponent component) throws IOException {
128    
129        final Iterator<UIComponent> facetsAndChildren = component.getFacetsAndChildren();
130        while (facetsAndChildren.hasNext() && !facesContext.getResponseComplete()) {
131          AjaxUtils.processAjax(facesContext, facetsAndChildren.next());
132        }
133      }
134    
135      public static Map<String, UIComponent> parseAndStoreComponents(FacesContext facesContext) {
136        Map parameterMap = facesContext.getExternalContext().getRequestParameterMap();
137        String ajaxComponentIds = (String) parameterMap.get(AjaxPhaseListener.AJAX_COMPONENT_ID);
138        if (ajaxComponentIds != null) {
139          LOG.info("ajaxComponentIds = \"" + ajaxComponentIds + "\"");
140          StringTokenizer tokenizer = new StringTokenizer(ajaxComponentIds, ",");
141          Map<String, UIComponent> ajaxComponents = new HashMap<String, UIComponent>(tokenizer.countTokens());
142          //noinspection unchecked
143          facesContext.getExternalContext().getRequestMap().put(AJAX_COMPONENTS, ajaxComponents);
144          javax.faces.component.UIViewRoot viewRoot = facesContext.getViewRoot();
145          while (tokenizer.hasMoreTokens()) {
146            String ajaxId = tokenizer.nextToken();
147            UIComponent ajaxComponent = viewRoot.findComponent(ajaxId);
148            if (ajaxComponent != null) {
149              LOG.info("ajaxComponent for \"" + ajaxId + "\" = \"" + ajaxComponent + "\"");
150              ajaxComponents.put(ajaxId, ajaxComponent);
151            }
152          }
153          return ajaxComponents;
154        }
155        return null;
156      }
157    
158      public static Map<String, UIComponent> getAjaxComponents(FacesContext facesContext) {
159        //noinspection unchecked
160        return (Map<String, UIComponent>)
161            facesContext.getExternalContext().getRequestMap().get(AJAX_COMPONENTS);
162      }
163    
164      public static void ensureDecoded(FacesContext facesContext, String clientId) {
165        ensureDecoded(facesContext, facesContext.getViewRoot().findComponent(clientId));
166      }
167    
168      public static void ensureDecoded(FacesContext facesContext, UIComponent component) {
169        Map<String, UIComponent> ajaxComponents = getAjaxComponents(facesContext);
170        if (ajaxComponents != null) {
171          for (UIComponent uiComponent : ajaxComponents.values()) {
172            UIComponent currentComponent = component;
173            while (currentComponent != null) {
174              if (component == uiComponent) {
175                return;
176              }
177              currentComponent = currentComponent.getParent();
178            }
179          }
180          component.processDecodes(facesContext);
181        }
182      }
183    }