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.List;
034    import java.util.ArrayList;
035    
036    /*
037     * Created by IntelliJ IDEA.
038     * User: weber
039     * Date: 12.10.2005
040     * Time: 13:11:05
041     */
042    public class AjaxUtils {
043    
044      private static final Log LOG = LogFactory.getLog(AjaxUtils.class);
045    
046      public static final String AJAX_COMPONENTS = AjaxUtils.class.getName() + ".AJAX_COMPONENTS";
047    
048      public static void checkParamValidity(FacesContext facesContext, UIComponent uiComponent, Class compClass) {
049        if (facesContext == null) {
050          throw new NullPointerException("facesContext may not be null");
051        }
052        if (uiComponent == null) {
053          throw new NullPointerException("uiComponent may not be null");
054        }
055        //if (compClass != null && !(compClass.isAssignableFrom(uiComponent.getClass())))
056        // why isAssignableFrom with additional getClass method call if isInstance does the same?
057        if (compClass != null && !(compClass.isInstance(uiComponent))) {
058          throw new IllegalArgumentException("uiComponent : "
059              + uiComponent.getClass().getName() + " is not instance of "
060              + compClass.getName() + " as it should be");
061        }
062      }
063    
064    
065    
066    
067      public static void encodeAjaxComponent(FacesContext facesContext, UIComponent component) throws IOException {
068        if (facesContext == null) {
069          throw new NullPointerException("facesContext");
070        }
071        if (!component.isRendered()) {
072          return;
073        }
074        Renderer renderer = ComponentUtil.getRenderer(facesContext, component);
075        if (renderer != null && renderer instanceof AjaxRenderer) {
076          ((AjaxRenderer) renderer).encodeAjax(facesContext, component);
077        }
078      }
079    
080    
081      public static void processAjax(FacesContext facesContext, UIComponent component)
082          throws IOException {
083        if (component instanceof AjaxComponent) {
084          ((AjaxComponent) component).processAjax(facesContext);
085        } else {
086          processAjaxOnChildren(facesContext, component);
087        }
088      }
089    
090      public static void processActiveAjaxComponent(FacesContext facesContext,
091                                                    UIComponent component)
092          throws IOException {
093    
094        if (component instanceof AjaxComponent) {
095          final UIViewRoot viewRoot = (UIViewRoot) facesContext.getViewRoot();
096    
097          // TODO: handle phaseListeners ??
098    
099          if (!facesContext.getRenderResponse()) {
100            component.processValidators(facesContext);
101            viewRoot.broadcastEventsForPhase(facesContext, PhaseId.PROCESS_VALIDATIONS);
102          } else if (LOG.isDebugEnabled()) {
103            LOG.debug("Skipping validate");
104          }
105    
106          if (!facesContext.getRenderResponse()) {
107            component.processUpdates(facesContext);
108            viewRoot.broadcastEventsForPhase(facesContext, PhaseId.UPDATE_MODEL_VALUES);
109          } else if (LOG.isDebugEnabled()) {
110            LOG.debug("Skipping updates");
111          }
112    
113          if (!facesContext.getRenderResponse()) {
114            viewRoot.processApplication(facesContext);
115          } else if (LOG.isDebugEnabled()) {
116            LOG.debug("Skipping application");
117          }
118    
119          ((AjaxComponent) component).encodeAjax(facesContext);
120        } else {
121          LOG.error("Can't process non AjaxComponent : \""
122              + component.getClientId(facesContext) + "\" = "
123              + component.getClass().getName());
124        }
125      }
126    
127      public static void processAjaxOnChildren(FacesContext facesContext,
128          UIComponent component) throws IOException {
129    
130        final Iterator<UIComponent> facetsAndChildren = component.getFacetsAndChildren();
131        while (facetsAndChildren.hasNext() && !facesContext.getResponseComplete()) {
132          AjaxUtils.processAjax(facesContext, facetsAndChildren.next());
133        }
134      }
135    
136      public static ArrayList<UIComponent> parseAndStoreComponents(FacesContext facesContext) {
137        Map parameterMap = facesContext.getExternalContext().getRequestParameterMap();
138        String ajaxComponentIds = (String) parameterMap.get(AjaxPhaseListener.AJAX_COMPONENT_ID);
139        if (ajaxComponentIds != null) {
140          LOG.info("ajaxComponentIds = \"" + ajaxComponentIds + "\"");
141          StringTokenizer tokenizer = new StringTokenizer(ajaxComponentIds, ",");
142          ArrayList<UIComponent> ajaxComponents = new ArrayList<UIComponent>(tokenizer.countTokens());
143          //noinspection unchecked
144          facesContext.getExternalContext().getRequestMap().put(AJAX_COMPONENTS, ajaxComponents);
145          javax.faces.component.UIViewRoot viewRoot = facesContext.getViewRoot();
146          while (tokenizer.hasMoreTokens()) {
147            String ajaxId = tokenizer.nextToken();
148            UIComponent ajaxComponent = viewRoot.findComponent(ajaxId);
149            if (ajaxComponent != null) {
150              LOG.info("ajaxComponent = \"" + ajaxComponent + "\"");
151              ajaxComponents.add(ajaxComponent);
152            }
153          }
154          return ajaxComponents;
155        }
156        return null;
157      }
158    
159      public static List<UIComponent> getAjaxComponents(FacesContext facesContext) {
160        //noinspection unchecked
161        return (List<UIComponent>)
162            facesContext.getExternalContext().getRequestMap().get(AJAX_COMPONENTS);
163      }
164    
165      public static void ensureDecoded(FacesContext facesContext, String clientId) {
166        ensureDecoded(facesContext, facesContext.getViewRoot().findComponent(clientId));
167      }
168    
169      public static void ensureDecoded(FacesContext facesContext, UIComponent component) {
170        List<UIComponent> ajaxComponents = getAjaxComponents(facesContext);
171        if (ajaxComponents != null) {
172          for (UIComponent uiComponent : ajaxComponents) {
173            UIComponent currentComponent = component;
174            while (currentComponent != null) {
175              if (component == uiComponent) {
176                return;
177              }
178              currentComponent = currentComponent.getParent();
179            }
180          }
181          component.processDecodes(facesContext);
182        }
183      }
184    }