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

org.ajax4jsf.framework.renderer.AjaxChildrenRenderer Maven / Gradle / Ivy

/**
 * Licensed under the Common Development and Distribution License,
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.sun.com/cddl/
 *   
 * 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.ajax4jsf.framework.renderer;

import java.io.IOException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import javax.faces.component.NamingContainer;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;

import org.ajax4jsf.ajax.UILoadBundle;
import org.ajax4jsf.framework.ajax.AjaxChildrenEncoder;
import org.ajax4jsf.framework.ajax.AjaxOutput;
import org.ajax4jsf.framework.util.message.Messages;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * @author shura
 *
 */
public abstract class AjaxChildrenRenderer extends AjaxComponentRendererBase {
	
	public static final Log log = LogFactory.getLog(AjaxChildrenRenderer.class);

	public static final String[] SPECIAL_COMPONENTS_TYPES = {
				UILoadBundle.COMPONENT_TYPE, "org.apache.myfaces.AliasBean",
				"org.apache.myfaces.AliasBeansScope" };
	private static final String SPECIAL_TYPES_PARAMETER = "org.ajax4jsf.CONTROL_COMPONENTS";

	/**
	 * Iterate over all childs of components. If component id contains in list ,
	 * or, if list is empty, compotents is submitted form - render it. TODO -
	 * Instead of calculate full path for every component, build current Path
	 * for componet and send as parameter.
	 * 
	 * @param context -
	 *            current context
	 * @param component -
	 *            curent faces component.
	 * @param ids -
	 *            list of Id to render.
	 * @throws IOException
	 */
	public void encodeAjaxChild(FacesContext context, UIComponent component, String path, Set ids, Set renderedAreas) throws IOException {
		if (log.isDebugEnabled()) {
			log.debug(Messages.getMessage(Messages.ENCODE_CHILD_AJAX_INFO,
					path, component.getId()));
		}
		String currentPath = path;
		if (component instanceof NamingContainer) {
			currentPath += component.getId() + NamingContainer.SEPARATOR_CHAR;
		}
		for (Iterator it = component.getFacetsAndChildren(); it.hasNext();) {
			boolean found = false;
			UIComponent element = (UIComponent) it.next();
			if (element.isRendered()) { // skip not-rendered components.
				if (!ids.isEmpty()) {
					// list for rendering may contains absolute id ( best ),
					// component Id or client ID
					String elementId = element.getId();
					String absoluteId = currentPath + elementId;
					// String clientId = element.getClientId(context);
					if (ids.contains(absoluteId) || ids.contains(elementId)) {
						if (log.isDebugEnabled()) {
							log
									.debug(Messages.getMessage(
											Messages.RENDER_AJAX_AREA_INFO,
											absoluteId));
						}
						// renderChild(context, element);
						found = true;
					}
				}
				if (element instanceof AjaxOutput) {
					if (((AjaxOutput) element).isAjaxRendered()) {
						// renderChild(context, element);
						found = true;
					}
	
				}
	
				if (!found) {
					if (element instanceof AjaxChildrenEncoder) {
						((AjaxChildrenEncoder) element).encodeAjaxChild(
								context, currentPath, ids, renderedAreas);
					} else {
						// Special case - for control components, not produced
						// html code - such as message bundles loaders,
						// MyFaces aliases etc. we call encodeBegin/end methods
						// even if components not in rendered areas.
						boolean special = isSpecialElement(context, element);
						if (special) {
							element.encodeBegin(context);
						}
						encodeAjaxChild(context, element, currentPath, ids,
								renderedAreas);
						if (special) {
							element.encodeEnd(context);
						}
	
					}
				} else {
					renderedAreas.add(element.getClientId(context));
					renderChild(context, element);
				}
			}
		}
	}

	private Set _specialComponentTypes = null;

	/**
	 * Detect component as special control case - such as messages bundle
	 * loader, alias bean components etc. Type of component get by reflection
	 * from static field COMPONENT_TYPE
	 * 
	 * @param context
	 * @param component
	 * @return true if encode methods must be called for this component even in
	 *         not-rendered parts.
	 */
	private boolean isSpecialElement(FacesContext context, UIComponent component) {
		if (_specialComponentTypes == null) {
			_specialComponentTypes = new HashSet(10);
			for (int i = 0; i < SPECIAL_COMPONENTS_TYPES.length; i++) {
				_specialComponentTypes.add(SPECIAL_COMPONENTS_TYPES[i]);
			}
			String special = context.getExternalContext().getInitParameter(
					SPECIAL_TYPES_PARAMETER);
			if (null != special) {
				String[] split = special.split(",");
				for (int i = 0; i < split.length; i++) {
					_specialComponentTypes.add(split[i]);
				}
			}
		}
		boolean result;
		try {
			String componentType = (String) component.getClass().getField(
					"COMPONENT_TYPE").get(null);
			result = _specialComponentTypes.contains(componentType);
		} catch (Exception e) {
			// exception occurs if component not have accesible COMPONENT_TYPE
			// constant
			// we assume that component not in special types.
			result = false;
		}
		return result;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy