<commit_before>/**
 *  Copyright 2014-2017 <NAME> (TheCoder4.Eu) and <NAME> (http://www.beyondjava.net).
 *
 *  This file is part of BootsFaces.
 *
* 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 net.bootsfaces.component.inputText;

import java.io.IOException;
import java.util.List;
import java.util.logging.Logger;

import javax.el.ValueExpression;
import javax.faces.FacesException;
import javax.faces.component.UIComponent;
import javax.faces.component.ValueHolder;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import javax.faces.render.FacesRenderer;

import net.bootsfaces.C;
import net.bootsfaces.component.ajax.AJAXRenderer;
import net.bootsfaces.component.inputSecret.InputSecret;
import net.bootsfaces.render.CoreRenderer;
import net.bootsfaces.render.H;
import net.bootsfaces.render.R;
import net.bootsfaces.render.Responsive;
import net.bootsfaces.render.Tooltip;

@FacesRenderer(componentFamily = C.BSFCOMPONENT, rendererType = "net.bootsfaces.component.inputText.InputText")
public class InputTextRenderer extends CoreRenderer {
	private static final Logger LOGGER = Logger.getLogger(InputTextRenderer.class.getName());

	@Override
	public void decode(FacesContext context, UIComponent component) {
		decode(context, component, null, null);
	}

    /** 
     * This method is used by RadioButtons and SelectOneMenus to limit the list of legal values. If another value is
     * sent, the input field is considered empty. This comes in useful the the back-end attribute is a primitive
     * type like int, which doesn't support null values.
     * @param context
     * @param component
     * @param legalValues an optional list of legal values. May be null.
     * @param The real attribute name of the request parameter. By default, BootsFaces guesses the attribute name
     * from the client ID or the name attribute of the input field. However, in some cases such as radio buttons,
     * this detection fails.
     */
	public void decode(FacesContext context, UIComponent component, List<String> legalValues, String realEventSourceName) {
		InputText inputText = (InputText) component;

		if (inputText.isDisabled() || inputText.isReadonly()) {
			return;
		}

		decodeBehaviors(context, inputText);

		String clientId = inputText.getClientId(context);
		String name = inputText.getName();
		if (realEventSourceName == null) {
			realEventSourceName = "input_" + clientId;
		}
		
		if (null == name) {
			name = "input_" + clientId;
		}
		String submittedValue = (String) context.getExternalContext().getRequestParameterMap().get(name);
		
		if (null != legalValues && null != submittedValue) {
			boolean found = false;
			for (String option: legalValues) {
				found |= submittedValue.equals(option);
			}
			if (!found) {
				submittedValue = "";
			}
		}

		if (submittedValue != null) {
			inputText.setSubmittedValue(submittedValue);
		}
		new AJAXRenderer().decode(context, component, realEventSourceName);
	}

	/**
	 * This method is called by the JSF framework to get the type-safe value of
	 * the attribute. Do not delete this method.
	 */
	@Override
	public Object getConvertedValue(FacesContext fc, UIComponent c, Object sval) throws ConverterException {
		Converter cnv = resolveConverter(fc, c);

		if (cnv != null) {
			return cnv.getAsObject(fc, c, (String) sval);
		} else {
			return sval;
		}
	}

	protected Converter resolveConverter(FacesContext context, UIComponent c) {
		if (!(c instanceof ValueHolder)) {
			return null;
		}

		Converter cnv = ((ValueHolder) c).getConverter();

		if (cnv != null) {
			return cnv;
		} else {
			ValueExpression ve = c.getValueExpression("value");

			if (ve != null) {
				Class<?> valType = ve.getType(context.getELContext());

				if (valType != null) {
					return context.getApplication().createConverter(valType);
				}
			}

			return null;
		}
	}

	@Override
	public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
		if (!component.isRendered()) {
			return;
		}
		InputText inputText = (InputText) component;
		int numberOfDivs=0;

		ResponseWriter rw = context.getResponseWriter();
		String clientId = inputText.getClientId();
		boolean clientIdHasBeenRendered=false;

		String responsiveLabelClass = null;
		String label = inputText.getLabel();
		{
			if (!inputText.isRenderLabel()) {
				label = null;
			}
		}
		if (null != label) {
			responsiveLabelClass = Responsive.getResponsiveLabelClass(inputText);
		}
		String responsiveStyleClass = Responsive.getResponsiveStyleClass(inputText, false).trim();
		if (responsiveStyleClass.length() > 0 && responsiveLabelClass == null && (!isHorizontalForm(component))) {
			rw.startElement("div", component);
			rw.writeAttribute("class", responsiveStyleClass, "class");
			rw.writeAttribute("id", clientId, "id"); // clientId
			clientIdHasBeenRendered=true;
			Tooltip.generateTooltip(context, inputText, rw);
			numberOfDivs++;
		}

		// "Prepend" facet
		UIComponent prep = inputText.getFacet("prepend");
		// "Append" facet
		UIComponent app = inputText.getFacet("append");
		boolean prepend = (prep != null);
		boolean append = (app != null);

		// Define TYPE ( if null set default = text )
		// support for b:inputSecret
		String t;
		if (component instanceof InputSecret) {
			t = "password";
		} else { // ordinary input fields
			t = inputText.getType();
			if (t == null)
				t = "text";
		}
		boolean visible =  !"hidden".equals(t);

		if (visible) {
			rw.startElement("div", component);
			numberOfDivs++;
			if (null != inputText.getDir()) {
				rw.writeAttribute("dir", inputText.getDir(), "dir");
			}
	
			if (!clientIdHasBeenRendered) {
				rw.writeAttribute("id", clientId, "id");
				Tooltip.generateTooltip(context, inputText, rw);
				clientIdHasBeenRendered=true;
			}
			if (inputText.isInline()) {
				rw.writeAttribute("class", getFormGroupWithFeedback("form-inline", clientId), "class");
				LOGGER.warning("The inline attribute of b:inputText is deprecated and generates faulty HTML code. Please use <b:form inline=\"true\"> instead.");
			} else {
				rw.writeAttribute("class", getFormGroupWithFeedback("form-group", clientId), "class");
			}
		}

		String fieldId = inputText.getFieldId();
		if (null == fieldId) {
			fieldId = "input_" + clientId;
		}

		if (visible && label != null) {<commit_msg>First changes on InputText to comply with the new FormGroup component<commit_after>/**
 *  Copyright 2014-2017 <NAME> (TheCoder4.Eu) and <NAME> (http://www.beyondjava.net).
 *
 *  This file is part of BootsFaces.
 *
* 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 net.bootsfaces.component.inputText;

import java.io.IOException;
import java.util.List;
import java.util.logging.Logger;

import javax.el.ValueExpression;
import javax.faces.FacesException;
import javax.faces.component.UIComponent;
import javax.faces.component.ValueHolder;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import javax.faces.render.FacesRenderer;

import net.bootsfaces.C;
import net.bootsfaces.component.ajax.AJAXRenderer;
import net.bootsfaces.component.formGroup.FormGroup;
import net.bootsfaces.component.inputSecret.InputSecret;
import net.bootsfaces.render.CoreRenderer;
import net.bootsfaces.render.H;
import net.bootsfaces.render.R;
import net.bootsfaces.render.Responsive;
import net.bootsfaces.render.Tooltip;

@FacesRenderer(componentFamily = C.BSFCOMPONENT, rendererType = "net.bootsfaces.component.inputText.InputText")
public class InputTextRenderer extends CoreRenderer {
	private static final Logger LOGGER = Logger.getLogger(InputTextRenderer.class.getName());

	@Override
	public void decode(FacesContext context, UIComponent component) {
		decode(context, component, null, null);
	}

    /** 
     * This method is used by RadioButtons and SelectOneMenus to limit the list of legal values. If another value is
     * sent, the input field is considered empty. This comes in useful the the back-end attribute is a primitive
     * type like int, which doesn't support null values.
     * @param context
     * @param component
     * @param legalValues an optional list of legal values. May be null.
     * @param The real attribute name of the request parameter. By default, BootsFaces guesses the attribute name
     * from the client ID or the name attribute of the input field. However, in some cases such as radio buttons,
     * this detection fails.
     */
	public void decode(FacesContext context, UIComponent component, List<String> legalValues, String realEventSourceName) {
		InputText inputText = (InputText) component;

		if (inputText.isDisabled() || inputText.isReadonly()) {
			return;
		}

		decodeBehaviors(context, inputText);

		String clientId = inputText.getClientId(context);
		String name = inputText.getName();
		if (realEventSourceName == null) {
			realEventSourceName = "input_" + clientId;
		}
		
		if (null == name) {
			name = "input_" + clientId;
		}
		String submittedValue = (String) context.getExternalContext().getRequestParameterMap().get(name);
		
		if (null != legalValues && null != submittedValue) {
			boolean found = false;
			for (String option: legalValues) {
				found |= submittedValue.equals(option);
			}
			if (!found) {
				submittedValue = "";
			}
		}

		if (submittedValue != null) {
			inputText.setSubmittedValue(submittedValue);
		}
		new AJAXRenderer().decode(context, component, realEventSourceName);
	}

	/**
	 * This method is called by the JSF framework to get the type-safe value of
	 * the attribute. Do not delete this method.
	 */
	@Override
	public Object getConvertedValue(FacesContext fc, UIComponent c, Object sval) throws ConverterException {
		Converter cnv = resolveConverter(fc, c);

		if (cnv != null) {
			return cnv.getAsObject(fc, c, (String) sval);
		} else {
			return sval;
		}
	}

	protected Converter resolveConverter(FacesContext context, UIComponent c) {
		if (!(c instanceof ValueHolder)) {
			return null;
		}

		Converter cnv = ((ValueHolder) c).getConverter();

		if (cnv != null) {
			return cnv;
		} else {
			ValueExpression ve = c.getValueExpression("value");

			if (ve != null) {
				Class<?> valType = ve.getType(context.getELContext());

				if (valType != null) {
					return context.getApplication().createConverter(valType);
				}
			}

			return null;
		}
	}

	@Override
	public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
		if (!component.isRendered()) {
			return;
		}
		InputText inputText = (InputText) component;
		int numberOfDivs=0;

		ResponseWriter rw = context.getResponseWriter();
		String clientId = inputText.getClientId();
		boolean clientIdHasBeenRendered=false;

		String responsiveLabelClass = null;
		String label = inputText.getLabel();
		{
			if (!inputText.isRenderLabel()) {
				label = null;
			}
		}
		if (null != label) {
			responsiveLabelClass = Responsive.getResponsiveLabelClass(inputText);
		}
		String responsiveStyleClass = Responsive.getResponsiveStyleClass(inputText, false).trim();
		if (responsiveStyleClass.length() > 0 && responsiveLabelClass == null && (!isHorizontalForm(component))) {
			rw.startElement("div", component);
			rw.writeAttribute("class", responsiveStyleClass, "class");
			rw.writeAttribute("id", clientId, "id"); // clientId
			clientIdHasBeenRendered=true;
			Tooltip.generateTooltip(context, inputText, rw);
			numberOfDivs++;
		}

		// "Prepend" facet
		UIComponent prep = inputText.getFacet("prepend");
		// "Append" facet
		UIComponent app = inputText.getFacet("append");
		boolean prepend = (prep != null);
		boolean append = (app != null);

		// Define TYPE ( if null set default = text )
		// support for b:inputSecret
		String t;
		if (component instanceof InputSecret) {
			t = "password";
		} else { // ordinary input fields
			t = inputText.getType();
			if (t == null)
				t = "text";
		}
		boolean visible =  !"hidden".equals(t);

		if (visible) {
			rw.startElement("div", component);
			numberOfDivs++;
			if (null != inputText.getDir()) {
				rw.writeAttribute("dir", inputText.getDir(), "dir");
			}
	
			if (!clientIdHasBeenRendered) {
				rw.writeAttribute("id", clientId, "id");
				Tooltip.generateTooltip(context, inputText, rw);
				clientIdHasBeenRendered=true;
			}
			if (inputText.isInline()) {
				rw.writeAttribute("class", getFormGroupWithFeedback("form-inline", clientId), "class");
				LOGGER.warning("The inline attribute of b:inputText is deprecated and generates faulty HTML code. Please use <b:form inline=\"true\"> instead.");
			} else {
                            if(!(component.getParent() instanceof FormGroup)) {
				rw.writeAttribute("class", getFormGroupWithFeedback("form-group", clientId), "class");
                            }
			}
		}

		String fieldId = inputText.getFieldId();
		if (null == fieldId) {
			fieldId = "input_" + clientId;
		}

		if (visible && label != null) {
{'fraction_non_alphanumeric': 0.11355727576166466, 'fraction_numerical': 0.0021305305020950216, 'mean_word_length': 4.081919884518224, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '419977', 'n_tokens_mistral': 4593, 'n_tokens_neox': 4140, 'n_words': 1189}