<commit_before>/*
 * DomUI Java User Interface library
 * Copyright (c) 2010 by <NAME>, Itris B.V.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * See the "sponsors" file for a list of supporters.
 *
 * The latest version of DomUI and related code, support and documentation
 * can be found at http://www.domui.org/
 * The contact for the project is <NAME> <<EMAIL>>.
 */
package to.etc.domui.dom.html;

import javax.annotation.*;

import to.etc.domui.component.meta.*;
import to.etc.domui.dom.errors.*;
import to.etc.domui.trouble.*;
import to.etc.domui.util.*;
import to.etc.util.*;

public class TextArea extends InputNodeContainer implements INativeChangeListener, IControl<String>, IHasModifiedIndication, IHtmlInput {
	/** Hint to use in property meta data to select this component. */
	static public final String HINT = "textarea";

	private int m_cols = -1;

	private int m_rows = -1;

	/**
	 * This flag gets T if the validate method has been called on the current
	 * input for a control. It gets reset when a control receives a new value
	 * that differs from it's previous value (raw).
	 */
	private boolean m_validated;

	/** If validated this contains the last validation result. */
	private UIException m_validationResult;

	private String m_value;

	private boolean m_disabled;

	/** Indication if the contents of this thing has been altered by the user. This merely compares any incoming value with the present value and goes "true" when those are not equal. */
	private boolean m_modifiedByUser;

	public TextArea() {
		super("textarea");
	}

	public TextArea(int cols, int rows) {
		this();
		m_cols = cols;
		m_rows = rows;
	}


	@Override
	public void visit(INodeVisitor v) throws Exception {
		v.visitTextArea(this);
	}

	public int getCols() {
		return m_cols;
	}

	public void setCols(int cols) {
		if(m_cols == cols)
			return;
		changed();
		m_cols = cols;
	}

	public int getRows() {
		return m_rows;
	}

	public void setRows(int rows) {
		if(m_rows == rows)
			return;
		changed();
		m_rows = rows;
	}

	/**
	 * Bind-capable version of getValue(). If called (usually from binding) this will act as follows:
	 * <ul>
	 * 	<li>If this component has an input error: throw the ValidationException for that error</li>
	 * 	<li>On no error this returns the value.</li>
	 * </ul>
	 * @return
	 */
	public String getBindValue() {
		validate();												// Validate, and throw exception without UI change on trouble.
		return m_value;
	}

	public void setBindValue(@Nullable String value) {
		if(MetaManager.areObjectsEqual(m_value, value)) {
			return;
		}
		setValue(value);
	}

	public void validate() {

		UIException result = m_validationResult;
		if(m_validated) {
			if(null == result)
				return;
			throw result;
		}
		try {
			m_validated = true;

			if(StringTool.isBlank(m_value)) {
				if(isMandatory()) {
					throw new ValidationException(Msgs.MANDATORY);
				}
			}
			UIMessage msg = getMessage();
			if(result != null && msg != null) {
				//-- Moving from invalid -> valid -check message.
				if(result.getCode().equals(msg.getCode())) { // && result.getBundle().equals(msg.getBundle())) { // INCO Urgent: BundleRef needs equals, defining package+file as key.
					setMessage(null);
				}
			}
			m_validationResult = null;
		} catch(ValidationException vx) {
			m_validationResult = vx;
			throw vx;
		}
	}

	/**
	 * @see to.etc.domui.dom.html.IControl#getValue()
	 */
	@Override
	public String getValue() {
		try {
			validate();
			return m_value;
		} catch(ValidationException x) {
			handleValidationException(x);
			throw x;
		}
	}

	private void handleValidationException(@Nullable ValidationException x) {
		UIMessage message = null;
		if(null != x) {
			message = UIMessage.error(x);
		}
		setMessage(message);
	}

	/**
	 * @see to.etc.domui.dom.html.IControl#getValueSafe()
	 */
	@Override
	public String getValueSafe() {
		return DomUtil.getValueSafe(this);
	}

	/**
	 * @see to.etc.domui.dom.html.IControl#hasError()
	 */
	@Override
	public boolean hasError() {
		getValueSafe();
		return super.hasError();
	}


	public String getRawValue() {
		return m_value;
	}

	@Override
	public boolean isDisabled() {
		return m_disabled;
	}

	@Override
	public void setDisabled(boolean disabled) {
		if(m_disabled == disabled)
			return;
		changed();
		m_disabled = disabled;
		fireModified("disabled", Boolean.valueOf(!disabled), Boolean.valueOf(disabled));
	}

	@Override
	public void setValue(@Nullable String v) {
		String value = m_value;
		if(DomUtil.isEqual(v, value))
			return;
		m_value = v;
		setText(v);
		m_validated = false;
		fireModified("value", value, v);
	}

	@Override
	public boolean acceptRequestParameter(@Nonnull String[] values) throws Exception {
		String nw = (values == null || values.length != 1) ? null : values[0];
		//fixes problem when no data is entered on form and modified flag is raised
		if(nw != null && nw.length() == 0)
			nw = null;
		String cur = m_value != null && m_value.length() == 0 ? null : m_value; // Treat empty string and null the same

		//vmijic 20091124 - some existing entries have \r\n, but after client request roundtrip nw get values with \n instead. Prevent differences being raised because of this.
		if(cur != null) {
			cur = cur.replaceAll("\r\n", "\n");
		}
		//vmijic 20091126 - now IE returns \r\n, but FF returns \n... So, both nw and cur have to be compared with "\r\n" replaced by "\n"...
		String flattenLineBreaksNw = (nw != null) ? nw.replaceAll("\r\n", "\n") : null;

		//vmijic 20101117 - it is discovered (call 28340) that from some reason first \n is not rendered in TextArea on client side in initial page render. That cause that same \n is missing from unchanged text area input that comes through client request roundtrip and cause modified flag to be set... So as dirty fix we have to compare without that starting \n too...
		if(flattenLineBreaksNw != null && cur != null && cur.startsWith("\n") && !flattenLineBreaksNw.startsWith("\n")) {
			cur = cur.substring(1);
		}

		if(DomUtil.isEqual(flattenLineBreaksNw, cur))
			return false;

		setValue(nw);
		DomUtil.setModifiedFlag(this);
		return true;
	}

	/*--------------------------------------------------------------*/
	/*	CODING:	IHasModifiedIndication impl							*/
	/*--------------------------------------------------------------*/
	/**
	 * Returns the modified-by-user flag.
	 * @see to.etc.domui.dom.html.IHasModifiedIndication#isModified()
	 */
	@Override
	public boolean isModified() {
		return m_modifiedByUser;
	}

	/**
	 * Set or clear the modified by user flag.
	 * @see to.etc.domui.dom.html.IHasModifiedIndication#setModified(boolean)
	 */
	@Override
	public void setModified(boolean as) {
		m_modifiedByUser = as;
	}

	@Nonnull
	static public TextArea create(@Nonnull PropertyMetaModel< ? > pmm) {
		TextArea ta = new TextArea();
		String cth = pmm.getComponentTypeHint();
		if(cth != null) {
			String hint = cth.toLowerCase();
			ta.setCols(MetaUtils.parseIntParam(hint, MetaUtils.COL, 80));
			ta.setRows(MetaUtils.parseIntParam(hint, MetaUtils.ROW, 4));
		}
		if(pmm.isRequired())
			ta.setMandatory(true);
		String s = pmm.getDefaultHint();
		if(s != null)
			ta.setTitle(s);
		return ta;
	}
}
<commit_msg>DE400 : problems with validation solved.<commit_after>/*
 * DomUI Java User Interface library
 * Copyright (c) 2010 by <NAME>, Itris B.V.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * See the "sponsors" file for a list of supporters.
 *
 * The latest version of DomUI and related code, support and documentation
 * can be found at http://www.domui.org/
 * The contact for the project is <NAME> <<EMAIL>>.
 */
package to.etc.domui.dom.html;

import javax.annotation.*;

import to.etc.domui.component.meta.*;
import to.etc.domui.dom.errors.*;
import to.etc.domui.trouble.*;
import to.etc.domui.util.*;
import to.etc.util.*;

public class TextArea extends InputNodeContainer implements INativeChangeListener, IControl<String>, IHasModifiedIndication, IHtmlInput {
	/** Hint to use in property meta data to select this component. */
	static public final String HINT = "textarea";

	private int m_cols = -1;

	private int m_rows = -1;

	/**
	 * This flag gets T if the validate method has been called on the current
	 * input for a control. It gets reset when a control receives a new value
	 * that differs from it's previous value (raw).
	 */
	private boolean m_validated;

	/** If validated this contains the last validation result. */
	private UIException m_validationResult;

	private String m_value;

	private boolean m_disabled;

	/** Indication if the contents of this thing has been altered by the user. This merely compares any incoming value with the present value and goes "true" when those are not equal. */
	private boolean m_modifiedByUser;

	public TextArea() {
		super("textarea");
	}

	public TextArea(int cols, int rows) {
		this();
		m_cols = cols;
		m_rows = rows;
	}


	@Override
	public void visit(INodeVisitor v) throws Exception {
		v.visitTextArea(this);
	}

	public int getCols() {
		return m_cols;
	}

	public void setCols(int cols) {
		if(m_cols == cols)
			return;
		changed();
		m_cols = cols;
	}

	public int getRows() {
		return m_rows;
	}

	public void setRows(int rows) {
		if(m_rows == rows)
			return;
		changed();
		m_rows = rows;
	}

	/**
	 * Bind-capable version of getValue(). If called (usually from binding) this will act as follows:
	 * <ul>
	 * 	<li>If this component has an input error: throw the ValidationException for that error</li>
	 * 	<li>On no error this returns the value.</li>
	 * </ul>
	 * @return
	 */
	public String getBindValue() {
		validate();												// Validate, and throw exception without UI change on trouble.
		return m_value;
	}

	public void setBindValue(@Nullable String value) {
		if(MetaManager.areObjectsEqual(m_value, value)) {
			return;
		}
		setValue(value);
	}

	private void validate() {

		UIException result = m_validationResult;
		if(m_validated) {
			if(null == result)
				return;
			throw result;
		}
		try {
			m_validated = true;

			if(StringTool.isBlank(m_value)) {
				if(isMandatory()) {
					throw new ValidationException(Msgs.MANDATORY);
				}
			}
			UIMessage msg = getMessage();
			if(result != null && msg != null) {
				//-- Moving from invalid -> valid -check message.
				if(result.getCode().equals(msg.getCode())) { // && result.getBundle().equals(msg.getBundle())) { // INCO Urgent: BundleRef needs equals, defining package+file as key.
					setMessage(null);
				}
			}
			m_validationResult = null;
		} catch(ValidationException vx) {
			m_validationResult = vx;
			throw vx;
		}
	}

	/**
	 * @see to.etc.domui.dom.html.IControl#getValue()
	 */
	@Override
	public String getValue() {
		try {
			validate();
			return m_value;
		} catch(ValidationException x) {
			handleValidationException(x);
			throw x;
		}
	}

	private void handleValidationException(@Nullable ValidationException x) {
		UIMessage message = null;
		if(null != x) {
			message = UIMessage.error(x);
		}
		setMessage(message);
	}

	/**
	 * @see to.etc.domui.dom.html.IControl#getValueSafe()
	 */
	@Override
	public String getValueSafe() {
		return DomUtil.getValueSafe(this);
	}

	/**
	 * @see to.etc.domui.dom.html.IControl#hasError()
	 */
	@Override
	public boolean hasError() {
		getValueSafe();
		return super.hasError();
	}


	public String getRawValue() {
		return m_value;
	}

	@Override
	public boolean isDisabled() {
		return m_disabled;
	}

	@Override
	public void setDisabled(boolean disabled) {
		if(m_disabled == disabled)
			return;
		changed();
		m_disabled = disabled;
		fireModified("disabled", Boolean.valueOf(!disabled), Boolean.valueOf(disabled));
	}

	@Override
	public void setValue(@Nullable String v) {
		String value = m_value;
		if(DomUtil.isEqual(v, value))
			return;
		m_value = v;
		setText(v);
		m_validated = false;
		fireModified("value", value, v);
	}

	@Override
	public boolean acceptRequestParameter(@Nonnull String[] values) throws Exception {
		String nw = (values == null || values.length != 1) ? null : values[0];
		//fixes problem when no data is entered on form and modified flag is raised
		if(nw != null && nw.length() == 0)
			nw = null;
		String cur = m_value != null && m_value.length() == 0 ? null : m_value; // Treat empty string and null the same

		//vmijic 20091124 - some existing entries have \r\n, but after client request roundtrip nw get values with \n instead. Prevent differences being raised because of this.
		if(cur != null) {
			cur = cur.replaceAll("\r\n", "\n");
		}
		//vmijic 20091126 - now IE returns \r\n, but FF returns \n... So, both nw and cur have to be compared with "\r\n" replaced by "\n"...
		String flattenLineBreaksNw = (nw != null) ? nw.replaceAll("\r\n", "\n") : null;

		//vmijic 20101117 - it is discovered (call 28340) that from some reason first \n is not rendered in TextArea on client side in initial page render. That cause that same \n is missing from unchanged text area input that comes through client request roundtrip and cause modified flag to be set... So as dirty fix we have to compare without that starting \n too...
		if(flattenLineBreaksNw != null && cur != null && cur.startsWith("\n") && !flattenLineBreaksNw.startsWith("\n")) {
			cur = cur.substring(1);
		}

		if(DomUtil.isEqual(flattenLineBreaksNw, cur))
			return false;

		setValue(nw);
		DomUtil.setModifiedFlag(this);
		return true;
	}

	/*--------------------------------------------------------------*/
	/*	CODING:	IHasModifiedIndication impl							*/
	/*--------------------------------------------------------------*/
	/**
	 * Returns the modified-by-user flag.
	 * @see to.etc.domui.dom.html.IHasModifiedIndication#isModified()
	 */
	@Override
	public boolean isModified() {
		return m_modifiedByUser;
	}

	/**
	 * Set or clear the modified by user flag.
	 * @see to.etc.domui.dom.html.IHasModifiedIndication#setModified(boolean)
	 */
	@Override
	public void setModified(boolean as) {
		m_modifiedByUser = as;
	}

	@Nonnull
	static public TextArea create(@Nonnull PropertyMetaModel< ? > pmm) {
		TextArea ta = new TextArea();
		String cth = pmm.getComponentTypeHint();
		if(cth != null) {
			String hint = cth.toLowerCase();
			ta.setCols(MetaUtils.parseIntParam(hint, MetaUtils.COL, 80));
			ta.setRows(MetaUtils.parseIntParam(hint, MetaUtils.ROW, 4));
		}
		if(pmm.isRequired())
			ta.setMandatory(true);
		String s = pmm.getDefaultHint();
		if(s != null)
			ta.setTitle(s);
		return ta;
	}
}

{'fraction_non_alphanumeric': 0.12938651855592023, 'fraction_numerical': 0.007258268114112598, 'mean_word_length': 3.3021992940537603, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '2136913', 'n_tokens_mistral': 5455, 'n_tokens_neox': 4880, 'n_words': 1630}