Skip to content

Commit

Permalink
improved eager validation
Browse files Browse the repository at this point in the history
  • Loading branch information
mstahv committed Jul 15, 2014
1 parent b849fb2 commit 58e7931
Show file tree
Hide file tree
Showing 3 changed files with 166 additions and 35 deletions.
7 changes: 7 additions & 0 deletions pom.xml
Expand Up @@ -37,6 +37,13 @@
<system>GitHub</system>
<url>https://github.com/mstahv/maddon/issues</url>
</issueManagement>

<distributionManagement>
<repository>
<id>v4</id>
<url>sftp://v4.tahvonen.fi/home/dev/maven2/</url>
</repository>
</distributionManagement>

<licenses>
<license>
Expand Down
28 changes: 12 additions & 16 deletions src/main/java/org/vaadin/maddon/MBeanFieldGroup.java
Expand Up @@ -19,16 +19,16 @@
import com.vaadin.data.fieldgroup.BeanFieldGroup;
import com.vaadin.event.FieldEvents;
import com.vaadin.ui.AbstractComponent;
import com.vaadin.ui.AbstractTextField;
import com.vaadin.ui.Field;
import org.vaadin.maddon.fields.MTextField;

/**
*
* @author mattitahvonenitmill
* @param <T>
*/
public class MBeanFieldGroup<T> extends BeanFieldGroup<T> implements
Property.ValueChangeListener {
Property.ValueChangeListener, FieldEvents.TextChangeListener {

public interface FieldGroupListener<T> {

Expand All @@ -39,11 +39,16 @@ public interface FieldGroupListener<T> {
@Override
public void valueChange(Property.ValueChangeEvent event) {
setBeanModified(true);
if(listener != null) {
if (listener != null) {
listener.onFieldGroupChange(this);
}
}

@Override
public void textChange(FieldEvents.TextChangeEvent event) {
valueChange(null);
}

private boolean beanModified = false;
private FieldGroupListener<T> listener;

Expand Down Expand Up @@ -83,19 +88,10 @@ public MBeanFieldGroup<T> withEagarValidation(FieldGroupListener<T> listener) {
for (Field<?> field : getFields()) {
((AbstractComponent) field).setImmediate(true);
field.addValueChangeListener(this);
if (field instanceof AbstractTextField) {
final AbstractTextField abstractTextField = (AbstractTextField) field;
abstractTextField.addTextChangeListener(
new FieldEvents.TextChangeListener() {

@Override
public void textChange(
FieldEvents.TextChangeEvent event) {
// Set eagerly as value to trigger validation
abstractTextField.setValue(event.
getText());
}
});
if (field instanceof MTextField) {
final MTextField abstractTextField = (MTextField) field;
abstractTextField.setEagerValidation(true);
abstractTextField.addTextChangeListener(this);
}
}
return this;
Expand Down
166 changes: 147 additions & 19 deletions src/main/java/org/vaadin/maddon/fields/MTextField.java
Expand Up @@ -13,20 +13,29 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.vaadin.maddon.fields;

import com.vaadin.data.Property;
import com.vaadin.data.Validator;
import com.vaadin.data.util.converter.Converter;
import com.vaadin.event.FieldEvents.TextChangeEvent;
import com.vaadin.server.AbstractErrorMessage;
import com.vaadin.server.CompositeErrorMessage;
import com.vaadin.server.ErrorMessage;
import com.vaadin.ui.TextField;
import java.util.EventObject;

/**
*
* @author mattitahvonenitmill
*/
public class MTextField extends TextField {

private boolean eagerValidation = false;
private boolean eagerValidationStatus;
private String lastKnownTextChangeValue;
private Validator.InvalidValueException eagerValidationError;

public MTextField() {
configureMaddonStuff();
}
Expand Down Expand Up @@ -54,6 +63,39 @@ public MTextField(String caption, String value) {
super(caption, value);
}

@Override
protected void setValue(String newFieldValue, boolean repaintIsNotNeeded) throws ReadOnlyException, Converter.ConversionException, Validator.InvalidValueException {
lastKnownTextChangeValue = null;
eagerValidationError = null;
super.setValue(newFieldValue, repaintIsNotNeeded);
}

public boolean isEagerValidation() {
return eagerValidation;
}

public void setEagerValidation(boolean eagerValidation) {
this.eagerValidation = eagerValidation;
}

@Override
protected void fireEvent(EventObject event) {
if (isEagerValidation() && event instanceof TextChangeEvent) {
lastKnownTextChangeValue = ((TextChangeEvent) event).getText();
doEagerValidation();
}
super.fireEvent(event);
}

/**
*
* @return the value of the field or if a text change event have sent a
* value to the server since last value changes, then that.
*/
public String getLastKnownTextContent() {
return lastKnownTextChangeValue;
}

@Override
public void addValueChangeListener(ValueChangeListener listener) {
super.addValueChangeListener(listener);
Expand All @@ -62,47 +104,133 @@ public void addValueChangeListener(ValueChangeListener listener) {
}

public MTextField withConversionError(String message) {
setImmediate(true);
setConversionError(message);
return this;
setImmediate(true);
setConversionError(message);
return this;
}

public MTextField withConverter(Converter<String, ?> converter) {
setImmediate(true);
setConverter(converter);
setImmediate(true);
setConverter(converter);
return this;
}

public MTextField withFullWidth() {
setWidth("100%");
return this;
setWidth("100%");
return this;
}

public MTextField withInputPrompt(String inputPrompt) {
setInputPrompt(inputPrompt);
return this;
}

public MTextField withReadOnly(boolean readOnly) {
setReadOnly(readOnly);
return this;
setReadOnly(readOnly);
return this;
}


public MTextField withValidator(Validator validator) {
setImmediate(true);
addValidator(validator);
return this;
setImmediate(true);
addValidator(validator);
return this;
}

public MTextField withWidth(float width, Unit unit) {
setWidth(width,unit);
setWidth(width, unit);
return this;
}

public MTextField withWidth(String width) {
setWidth(width);
return this;
}


@Override
public ErrorMessage getErrorMessage() {

Validator.InvalidValueException validationError = getValidationError();

final ErrorMessage superError = getComponentError();

if (superError == null && validationError == null
&& getCurrentBufferedSourceException() == null) {
return null;
}
// Throw combination of the error types
return new CompositeErrorMessage(
new ErrorMessage[] {
superError,
AbstractErrorMessage
.getErrorMessageForException(validationError),
AbstractErrorMessage
.getErrorMessageForException(getCurrentBufferedSourceException()) });
}

protected Validator.InvalidValueException getValidationError() {
if(isEagerValidation() && lastKnownTextChangeValue != null) {
return eagerValidationError;
}
/*
* Check validation errors only if automatic validation is enabled.
* Empty, required fields will generate a validation error containing
* the requiredError string. For these fields the exclamation mark will
* be hidden but the error must still be sent to the client.
*/
Validator.InvalidValueException validationError = null;
if (isValidationVisible()) {
try {
validate();
} catch (Validator.InvalidValueException e) {
if (!e.isInvisible()) {
validationError = e;
}
}
}
return validationError;
}


protected void doEagerValidation() {
final boolean wasvalid = eagerValidationStatus;
eagerValidationStatus = true;
eagerValidationError = null;
try {
if (isRequired() && getLastKnownTextContent().isEmpty()) {
throw new Validator.EmptyValueException(getRequiredError());
}
validate(getLastKnownTextContent());
if(!wasvalid) {
markAsDirty();
}
} catch (Validator.InvalidValueException e) {
eagerValidationError = e;
eagerValidationStatus = false;
markAsDirty();
}
}

@Override
public boolean isValid() {
if (isEagerValidation() && lastKnownTextChangeValue != null) {
return eagerValidationStatus;
} else {
return super.isValid();
}
}

@Override
public void validate() throws Validator.InvalidValueException {
if (isEagerValidation() && lastKnownTextChangeValue != null) {
// This is most likely not executed, unless someone, for some weird
// reason calls this explicitly
if (isRequired() && getLastKnownTextContent().isEmpty()) {
throw new Validator.EmptyValueException(getRequiredError());
}
validate(getLastKnownTextContent());
} else {
super.validate();
}
}

}

0 comments on commit 58e7931

Please sign in to comment.