/*
* Sample program for use with the Product
* Licensed Materials  - Property of IBM
* 5724-I66
* (c) Copyright IBM Corp.  2006, 2009
*   
*/


package com.ibm.wbit.tel.client.jsf.component;

import java.util.ArrayList;
import java.util.HashMap;

import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.component.html.HtmlPanelGroup;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.servlet.http.HttpServletRequest;



/**
 * Implementation of PanelGroup to wrap all UIInput fields in messages sub views. 
 */
public class PanelGroup extends HtmlPanelGroup {

	 
	private PanelGroup instance; 
		
	private ArrayList<UIInput> required = new ArrayList<UIInput>();

	private HashMap<UIInput, Converter> converter = new HashMap<UIInput, Converter>();
	
	/**
	 * Factory method to get an instance. 
	 * 
	 * @return instance of PanelGroupvb
	 */
	public PanelGroup getInstance() {
		return instance == null ? new PanelGroup() : instance;
	}

	/**
	 * Setter necessary for JSF to restore view. 
	 * 
	 * @param instance of PanelGroup
	 */
	public void setInstance(PanelGroup instance) {
		this.instance = instance;
	}	
	
	/**
	 * Overwrite processValidators to suppress temporarily required flag 
	 * and converter if a certain key is passed via request. 
	 */
	public void processValidators(FacesContext ctx) {
		
		HttpServletRequest request = (HttpServletRequest) ctx.getExternalContext().getRequest();
		
		if ( request.getAttribute(CommandLink.COMMAND_LINK_KEY) != null ) {
			suppress(this);
			super.processValidators(ctx);
			restore();
		} else {
			super.processValidators(ctx);
		}
	}
		
	/**
	 * Restore required flag and converter for next request.
	 */
	private void restore() {
			
		for (UIInput reqInput : required ) {
			reqInput.setRequired(true);
		}
		required.clear();
				
		for (UIInput convInput : converter.keySet()) {
			convInput.setConverter( converter.get(convInput) );
		}
		converter.clear();
	}
	
	/**
	 * Suppress required flag and converter for components of type UIInput
	 * 
	 * @param parent component
	 */
	private void suppress(UIComponent parent) {
		UIInput uiInput; 				
		
		for (UIComponent child : parent.getChildren()) {
			if (child instanceof UIInput) {
				uiInput = (UIInput) child;
				
				converter.put(uiInput, uiInput.getConverter());
				uiInput.setConverter(null);
								
				if (uiInput.isRequired()) {
					uiInput.setRequired(false);
					required.add(uiInput);
				} 
			} else {
				suppress(child);	
			}
		}
	}

}
