Dashboard > RIFE > ... > Tips and Tricks > Custom constraints and validation cheatsheet
RIFE Log In   View a printable version of the current page.
Custom constraints and validation cheatsheet


Added by Stéphane Meslin-Weber, last edited by Joshua Hansen on Aug 15, 2008  (view change) show comment
Labels: 
(None)

A quick cheat-sheet for custom constraints and validation

Keeping beans and their constraint metadata separate in source:
http://rifers.org/wiki/display/RIFE/Meta+data+merging

Adding constraints:
http://rifers.org/wiki/display/RIFE/Constraints

Validating:
http://rifers.org/wiki/display/RIFE/Validation

Adding custom constraints:
http://rifers.org/docs/api/com/uwyn/rife/site/ConstrainedProperty.html#constraint(java.lang.String,%20java.lang.Object)

And validating them (use/implement/extend as necessary):
http://rifers.org/docs/api/com/uwyn/rife/site/ValidationRule.html

Interfaces that may be interesting
http://rifers.org/docs/api/com/uwyn/rife/site/Validated.html
http://rifers.org/docs/api/com/uwyn/rife/site/ValidatedConstrained.html

A Custom Constraint and Validation Example

The following is an example bean and MetaData class using a custom validation rule. Our validation rule simply gives an error whenever an indicated field is the text "balrog".

Creature.java (the bean class)
package com.upbear.rife.creature;

public class Creature {
	private int id = -1;
	private String type = null;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}
	
}
CreatureMetaData.java (the MetaData class)
package com.upbear.rife.creature;

import com.uwyn.rife.site.AbstractTextualIdentifierGenerator;
import com.uwyn.rife.site.ConstrainedBean;
import com.uwyn.rife.site.ConstrainedProperty;
import com.uwyn.rife.site.MetaData;
 
public class CreatureMetaData extends MetaData {

	public CreatureMetaData() { }

	public void activateMetaData()
	{
		addConstraint(new ConstrainedBean()
			.defaultOrder("type", ConstrainedBean.ASC)
			.textualIdentifier(new AbstractTextualIdentifierGenerator<Creature>() {
    			public String generateIdentifier() {
    				return mBean.getType();
    			}
			})
		);

		// Constraints declarations
		addConstraint(new ConstrainedProperty("id").editable(false).identifier(true));
		addConstraint(new ConstrainedProperty("type").notNull(true).notEmpty(true).listed(true).maxLength(50));
        
		// Our custom rule: Keep out the balrogs.
		addRule(new ValidationRuleNotBalrog("type"));

	}
}

Note the use of Validated.addRule() above to have our custom validation rule check the property "type".

ValidationRuleNotBalrog.java (the custom validation rule)
package com.upbear.rife.creature;

import java.lang.reflect.Array;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.uwyn.rife.site.ConstrainedProperty;
import com.uwyn.rife.site.ConstrainedUtils;
import com.uwyn.rife.site.PropertyValidationRule;
import com.uwyn.rife.site.ValidationError;
import com.uwyn.rife.tools.BeanUtils;
import com.uwyn.rife.tools.exceptions.BeanUtilsException;

public class ValidationRuleNotBalrog extends PropertyValidationRule {
	Logger logger = Logger.getLogger(this.getClass().getName());
	
	public ValidationRuleNotBalrog(String propertyName) {
		super(propertyName);
	}
	
	public boolean validate()
	{
		Object value;
		try
		{
			value = BeanUtils.getPropertyValue(getBean(), getPropertyName());
		}
		catch (BeanUtilsException e)
		{
			// an error occurred when obtaining the value of the property
			// just consider it valid to skip over it
			//logger.log(Level.INFO, "PropertyValidationRule ["
			//	+getPropertyName()+"] exception while obtaining value. "+e.getMessage(), e );
			return true;
		}
		
		if (null == value)
		{
			return true;
		}
		
		//
		// We need constrained_property in case there is any special formatting
		// for the property.
		ConstrainedProperty constrained_property = ConstrainedUtils.getConstrainedProperty(getBean(), getPropertyName());
		
		if (value.getClass().isArray())
		{
			// If this particular property is an array, check each element of the array
			int length = Array.getLength(value);
			for (int i = 0; i < length; i++)
			{
				if (isBalrog(BeanUtils.formatPropertyValue(Array.get(value, i), constrained_property)))
				{
					return false;
				}
			}
			
			return true;
		}
		else
		{
			return !isBalrog(BeanUtils.formatPropertyValue(value, constrained_property));
		}
	}

	public ValidationError getError()
	{
		//return new ValidationError.INVALID(getSubject());
		ValidationError error = new ValidationError("BALROG", getSubject()) {};
		return error;
	}
	
	private boolean isBalrog(String type) {
		if( type != null && type.trim().toLowerCase().equals("balrog") ) {
			return true;
		}
		
		return false;
	}
}

Note that this validation rule handles arrays and any specified custom formats. You may not need this level of detail, but it does make the validation rule more generalized and reusable.

Also note our custom error identifier "BALROG". Anywhere you would use another identifier, such as "INVALID", or "MANDATORY", in your templates, you can use "BALROG" to provide feedback on this particular validation error. I've left code in for using "INVALID" if you'd like to reuse one of the existing identifiers.

Finally, note that ValidationError is an abstract class, so we cannot simply instantiate it for a new identifier, we have to subclass it – note the "{}" on the end of the "new ValidationError" statement.

html template blurb
...
	<!--B 'BALROG:type'-->You shall not pass!!<br /><!--/B-->
...

And, there you have it – a custom validation rule with a custom error message!

Using custom validation with RIFE/CRUD

The above metadata and validation rule can be used as is with RIFE/CRUD to indicate errors in a submission. However, if you want to have RIFE/CRUD indicate an error more useful than the text "BALROG:type", then you'll need to override the default RIFE/CRUD template and create a resource properties file.

IMPORTANT: When creating a custom CRUD template, make sure that it is located in your classpath before the rife-crud-resources.jar; otherwise your custom template will never be loaded.

IMPORTANT: Note that the package for the templates is 'crud.common' and not 'templates.crud.common'.

crud/common/error_area.html (the custom error template)
<!--V 'error_area'--><!--/V-->
<!--B 'error_area'-->
	<table summary="overview of errors" width="100%" class="error_table">
	<cols>
		<col width="100%" />
	</cols>
	<tr>
		<td class="error_title">
<!--V 'error_title'/--><!--BV 'error_title'--><!--V 'L10N:error_area_title'-->error_area_title<!--/V--><!--/BV--><br>
		</td>
	</tr>
	<tr>
		<td>
			<!--V 'error_content'--><!--/V-->
			<!--B 'error_line'--><!--V 'error_message'--><!--/V--><br /><!--/B-->
		</td>
	</tr>
	</table>
	<br />
<!--/B-->
<!--V 'ERRORS:*'--><!--/V-->
<!--B 'ERRORS:'--><div class="form_error_area"><!--V 'ERRORS'/--></div><!--/B-->
<!--B 'ERRORS:*'--><!--V 'ERRORS'/--><!--/B-->
<!--B 'ERRORMESSAGE:*'--><!--V 'ERRORMESSAGE'/--><br /><!--/B-->
<!--B 'MARK:ERROR'-->form_field_error<!--/B-->

<!--B 'MANDATORY:*'--><!--V 'L10N:error_mandatory'-->error_mandatory<!--/V--><!--/B-->
<!--B 'WRONGLENGTH:*'--><!--V 'L10N:error_wronglength'-->error_wronglength<!--/V--><!--/B-->
<!--B 'NOTSAME:*'--><!--V 'L10N:error_notsame'-->error_notsame<!--/V--><!--/B-->
<!--B 'INVALID:*'--><!--V 'L10N:error_invalid'-->error_invalid<!--/V--><!--/B-->
<!--B 'UNICITY:*'--><!--V 'L10N:error_unicity'-->error_unicity<!--/V--><!--/B-->
<!--B 'NOTNUMERIC:*'--><!--V 'L10N:error_notnumeric'-->error_notnumeric<!--/V--><!--/B-->
<!--B 'BALROG:*'--><!--V 'L10N:error_balrog'-->error_balrog<!--/V--><!--/B-->
<!--B 'UNEXPECTED_ERROR'--><!--V 'L10N:error_unexpected'-->error_unexpected<!--/V--><!--/B-->

The only modification to the default error_area.html template is the addition of the 'BALROG' line.

l10n/crud/admin_en.properties (the properties file for the error messages)
error_area_title = The following errors occured
error_mandatory = Required 
error_wronglength = Wrong length
error_notsame = Not the same
error_invalid = Invalid
error_unicity = Already exists
error_notnumeric = Not numeric
error_unexpected = Unexpected error
error_balrog = You shall not pass!!



Are you enjoying Confluence? Please consider purchasing it today.
Powered by Atlassian Confluence, the Enterprise Wiki. (Version: 2.2.1a Build:#515 May 19, 2006) - Bug/feature request - Contact Administrators