Try fast search NHibernate

31 October 2009

Validation through persistence: not synchronized

In this series you saw mostly the configuration of NHibernate.Validator through Loquacious (our configuration based on fluent-interface).

What is the ValidationDef<T> ?

If you are using the Satisfier (validation through lambdas) the ValidationDef become the class whose responsibility is validate a instance of T.

If you need some validation, involving the persistence, and you want do it through NHV, which is the best candidate class where implement the validation ?

Let me show you how much easy is it:

public class BlogPostSofValidation : ValidationDef<BlogPost>
{
private readonly ISessionFactory factory;

public BlogPostSofValidation(ISessionFactory sessionFactory)
{
factory = sessionFactory;
ValidateInstance.By((bp, c) => !Exists(bp));
}

private bool Exists(BlogPost post)
{
if (ReferenceEquals(post, null))
{
return true;
}
using (var session = factory.OpenStatelessSession())
{
var criteria = session.CreateCriteria(typeof(BlogPost));
criteria.Add(Restrictions.Eq("Title", post.Title));
criteria.Add(Restrictions.Eq("Date", post.Date));
return criteria.UniqueResult() != null;
}
}
}

Here I’m showing only the part involving the persistence but you know… there you can define the validation of any other property as usual.

To register this definition the work to do is very easy:

var veConfig = new FluentConfiguration();
veConfig.Register(new BlogPostSofValidation(sessionFactory))
.SetDefaultValidatorMode(ValidatorMode.UseExternal);
validatorEngine = new ValidatorEngine();
validatorEngine.Configure(veConfig);

and that it’s all (the usage is identical of the previous post).

30 October 2009

Validation through persistence: synchronized

This post is about one possible answer to the question mememem ask me in this post (ah… nice nick).

The task is create a validator to validate the uniqueness, of an entity instance, using some properties’ values instead its POID (Persistence Object ID).

The implementation

public class BlogPost
{
public string Title { get; set; }
public DateTime Date { get; set; }
public string Content { get; set; }
}

we want check the uniqueness using the value of Title and the value of Date obviously without use both properties as composite-PK; so, we can’t have two posts with the same title in the same day.

Since NHibernate2.1.0GA we can instruct NH about our concept of uniqueness in a very explicit, self documented, and nice way:

<class name="BlogPost">
<
id type="guid">
<
generator class="guid.comb"/>
</
id>
<
natural-id mutable="true">
<
property name="Title"/>
<
property name="Date" type="Date"/>
</
natural-id>
<
property name="Content" type="string(10000)"/>
</
class>

clear no ? we are defining explicitly which is our natural-id, that mean we want a unique key with Title and Date. The result DDL is:

create table BlogPost (
id UNIQUEIDENTIFIER not null,
Title NVARCHAR(255) null,
Date DATETIME null,
Content NVARCHAR(MAX) null,
primary key (id),
unique (Title, Date)
)

We having NHibernate and the DataBase synchronized with the same rule and now we want create a validator to use with NHibernate.Validator to synchronize even our business logic (and prevent ADO.NET exceptions).

First the attribute to “mark” my classes:

[AttributeUsage(AttributeTargets.Class)]
[ValidatorClass(typeof(NaturalIdUniquenessValidator))]
public class NaturalIdUniquenessAttribute : Attribute, IRuleArgs
{
public string Message { get; set; }
}

then the validator implementation with NHibernate integration. In this implementation I’m using the Stateless-Session but you can use, a new statefull session or factory.GetCurrentSessionContext or whatever you have as session-provider. The matter is not from where you get the session but how create the query in a generic way that can be used for any entity without need any kind of “invasion” in my existing implementation.

Note: this is a classic usage of the stateless-session but take care with the BestGuessEntityName method.

public class NaturalIdUniquenessValidator : IValidator
{
private readonly ISessionFactory factory;

public NaturalIdUniquenessValidator(ISessionFactory sessionFactory)
{
factory = sessionFactory;
}

public bool IsValid(object value, IConstraintValidatorContext constraintContext)
{
if (ReferenceEquals(value, null))
{
return true;
}
using (var session = factory.OpenStatelessSession())
{
var entityName = ((ISessionImplementor) session).BestGuessEntityName(value);
var meta = factory.GetClassMetadata(entityName);
if (ReferenceEquals(meta, null) || !meta.HasNaturalIdentifier)
{
return true;
}
var propsValues = meta.GetPropertyValues(value, EntityMode.Poco);
var propsNames = meta.PropertyNames;
var criteria = session.CreateCriteria(entityName);
foreach (var propIdx in meta.NaturalIdentifierProperties)
{
criteria.Add(Restrictions.Eq(propsNames[propIdx], propsValues[propIdx]));
}
return criteria.UniqueResult() == null;
}
}
}

In the implementation I’m using some NHibernate advanced information to create a ICriteria with the properties defined as natural-id; the implementation is working with any entity of your domain. The strange thing, there, is another: the validator does not have a default constructor… where is the trick ?

Well… first the implementation with an home-made-2-minutes-IoC:

public class ConstraintValidatorFactory : DefaultConstraintValidatorFactory
{
public override IValidator GetInstance(Type type)
{
var persistenceCtor = type.GetConstructor(new[] {typeof (ISessionFactory)});
if(persistenceCtor != null)
{
return (IValidator)
persistenceCtor.Invoke(new object[] { NHibernateStaticContainer.Factory });
}
return base.GetInstance(type);
}
}

The IConstraintValidatorFactory is the factory for classes implementing IValidator and you can inject the concrete implementation through NHV configuration.

var nhvConfig = new FluentConfiguration();
nhvConfig.SetConstraintValidatorFactory<ConstraintValidatorFactory>();

Another, more generic, implementation of the IConstraintValidatorFactory could be:

public class ServiceLocatorValidatorFactory : DefaultConstraintValidatorFactory
{
#region Implementation of IConstraintValidatorFactory

public override IValidator GetInstance(Type type)
{
ConstructorInfo defaultConstructorInfo = type.GetConstructor(new Type[0]);
if (defaultConstructorInfo == null)
{
return (IValidator) ServiceLocator.Current.GetInstance(type);
}
return base.GetInstance(type);
}

#endregion
}

here you can use your preferred IoC framework as the factory/container of validators instances (take care with statefull validators).

The usage

Well… it is completely transparent, you can use this entity-validator as you are using any other.

the definition

public class BlogPostValidation: ValidationDef<BlogPost>
{
public BlogPostValidation()
{
ValidateInstance.Using(new NaturalIdUniquenessAttribute());
}
}

a simple test

var blogPost = new BlogPost
{
Title = "something new",
Date = DateTime.Today,
Content = "there is something new to say."
};

validatorEngine.IsValid(blogPost).Should().Be.True();

using (var s = sessionFactory.OpenSession())
using (var tx = s.BeginTransaction())
{
s.Save(blogPost);
tx.Commit();
}

var otherBlogPost = new BlogPost
{
Title = "something new",
Date = DateTime.Today,
Content = "bha?!?."
};

validatorEngine.IsValid(otherBlogPost).Should().Be.False();

otherBlogPost.Title = "very new";

validatorEngine.IsValid(otherBlogPost).Should().Be.True();

Conclusion

The implementation of the entity BlogPost was NEVER TOUCHED (I did it my way)… now :

  • go to your system
  • copy&paste the implementation of NaturalIdUniquenessAttribute and NaturalIdUniquenessValidator
  • change the implementation of the ConstraintValidatorFactory according to your system
  • change the mapping defining your natural-id in the entities where needed
  • Enjoy NHibernate.Validator, its flexibility, its injectability and its easy integration with NHibernate.

Tomorrow, perhaps, the no synchronized implementation.

29 October 2009

NHibernate visual Class and mapping generator integrated with VisualStudio2010

Do you remember this post ?

Now Microsoft gave us a step-by-step guide : POCO Templates for the Entity Framework

Fantastic!!!

Now we need a good soul starting the integration with NHibernate to generate POCO and mappings.

There will be a little difference:

The POCO template generates Entities that supports change notification.

NHibernate.Validator & NHibernate

The validation is defined as a classic cross cutting concern… well… if we are talking about that we need to validate something everywhere I can agree with that definition, but if we are talking about the validation of domain entities I don’t agree.

The validation of a domain-entity shouldn’t happen in the persistence-layer nor in the presentation-layer and even less in the persistence itself.

Validate something in the DB (persistence) is too late and you will have some unneeded round-trips, by the way, in some very special cases is acceptable and even inevitable (read it as optimistic-lock for example).

Validate in the persistent-layer can be useful if you want a “short-cut” where put the validation (for example if you modify an entity instance, somewhere, and you don't exactly know where put the validation of the new state).

Validate in the UI, well… there you can validate only what you are showing.

The natural place for the entities-validation is the service-layer (service in DDD meaning).

If I think so, why I like NHibernate.Validator so much ?

The matter is that, in the service-layer, I’m needing to validate entities-instances provided by NHibernate and I need a validation system that know how NHibernate work with entities (perhaps, soon, somebody will realize it for EF4).

warnIf you are using something else, than NHV, to validate complex-entities-graph (with valid associations, valid collections and so on), be careful and have a look to what is happening with SQL-Queries (activating log4Net for the SQL, or testing NH-Statistics, or using NHProf, or whatever).

That said I can begin explaining some integration points leaving you the choice of its usage.

The “integrator”

The class you must use to perform the integration is NHibernate.Validator.Cfg.ValidatorInitializer.

In the ValidatorInitializer there are only two extension-methods and before write this post I wrote the documentation of both methods; now you can read it there.

A full integration may look like:

var nhvConfiguration = new FluentConfiguration();
nhvConfiguration
.SetDefaultValidatorMode(ValidatorMode.UseExternal)
.Register(Assembly.Load("Dll.Where.ValidationDefAre")
.ValidationDefinitions())
.IntegrateWithNHibernate
.ApplyingDDLConstraints()
.And
.RegisteringListeners();

var nhibernateConfig = new Configuration().Configure();

validatorEngine = new ValidatorEngine();
validatorEngine.Configure(nhvConfiguration);

nhibernateConfig.Initialize(validatorEngine);

About the ValidatorEngine and the Shared-Engine-Provider you can read in: Diving in NHibernate.Validator.

Events integration

The integration of events is basically the registration of a IPreInsertEventListener and a IPreUpdateEventListener. If you, or the NHibernate’s auto-flush, are going to save or update an invalid instance you will receive an InvalidStateException (there is happening something else, but don’t worry).

DDL integration

The DDL integration is more DBA oriented than everything else… yes DBA oriented… even to make happy the DBA in yourself (I mean some old-school DBA).

In practice, having something like this:

public class Entity
{
public int Value { get; set; }
public string Description { get; set; }
}

public class EntityValidation : ValidationDef<Entity>
{
public EntityValidation()
{
Define(e => e.Value).IncludedBetween(10, 99);
Define(e => e.Description).NotNullableAndNotEmpty().And.MaxLength(50);
}
}

with a poor persistence mapping like this

<class name="Entity">
<
id type="int"/>
<
property name="Value"/>
<
property name="Description"/>
</
class>

if you will create the schema, using NHibernate’s SchemaExport, the script will be:

create table Entity (
id INT not null,
Value INT null check( Value>=10 and Value<=99) ,
Description NVARCHAR(50) not null,
primary key (id)
)

as you can see you have a perfect tuning, like in a concert, with the DataBase, even for the CHECK-CONSTRAINT of the property Value, and, if you want, you can even create some special Trigger (your old-school DBA will be euphoric with that).

What is wrong there ?

First of all, now you have transformed a very nice and flexible software validation in something written in the stone (now somebody should maintain the constraints, even in the DB, when you will need to change the range of allowed values).

Second, and perhaps even more catastrophic… in the past week I saw a NHibernate’s user euphoric because he found a way to integrate DataAnnotations, with NHibernate, through Fluent-NHibernate; his example was using the RequiredAttribute (NotNullable in NHV)… very cool!!! no ? well… now try to apply it in a graph mapped with table-per-class-hierarchy, where some subclass have a not-nullable property, and let me know which will be the result (only for this reason we should have a SoftNotNullableAttribute).

The matter is that, for the same reason you are not using stored-procedures to do everything, you shouldn’t integrate your nice software validation with the underling DDL of your RDBMS.


The Fashion

The fashion/elegant part, of the integration, is that you can start defining your domain model with POCOs then externally map the persistence, then externally map the validation integrated with persistence, and, as a kind of magic, your POCOs will checked before persist anything; all without any kind of invasion in your existing code.

but it’s only a kind of magic, I’m not so sure that it’s so beautiful.

28 October 2009

NHibernate.Validator : Customizing messages (Message Interpolator)

The message interpolator is the responsible of the messages translation/composition. In the coming soon version (NHV-1.2.0) we had increase its power (and refactorized its implementation).

Has default NHV has two implementations: DefaultMessageInterpolatorAggregator and DefaultMessageInterpolator.

What is the usual you have seen in NHibernate’s eco-system ? Yes, you are right: Injectability!!!

So far the injectability in NHV is not so extreme as in NHibernate but we are closer…very closer ;)

If you only need to override some behavior you can inherit from DefaultMessageInterpolator. If you want implement a completely different way to create/translate/composite messages you can implements your own IMessageInterpolator.

In this post I will write about another case: the composition of your own behavior with the default behavior.

The needs

As you saw, in the previous post, we have solved the problem of magic-strings so and so…but was only for yesterday. Today I would manage all messages through my convention, and composite it only in the strings-resource-file, for all cases where possible.

The possible convention
  • The key for a class name will be : friendly.class.<TypeName> (ex.: friendly.class.Employee)
  • The key for a property name will be : friendly.property.<PropertyName> (ex: friendly.property.Salary) ; note: two properties with the same name should have the same meaning no matter which is the owner class (IMO).
  • The key for the message of a entity-validator (validate the instance) will be: validator.<TypeName>
  • The key for the message of a property-validator will be: validator.<TypeName>.<PropertyName>
  • The key for the message of a validator will be: validator.<ValidatorName>

For <ValidatorName> I mean the class name of the validator without the post-fix “Validator” (that is the convention used inside NHV).

There is a special case for the <ValidatorName> (as any good convention); using lambdas the implementation of the validator is ever the same so, in this case, the <TypeName> will be the type where the validation was specified.

Note: all reusable validators, using the Satisfier or not, should define its key.

Messages redefinition

In NHV the default message for the constraint NotNullNotEmpty is:

key: validator.notNullNotEmpty

value: may not be null or empty

what I would like is:

The [here the friendly name of the property] of the [here the friendly name of the entity] is mandatory.

The custom IMessageInterpolator

First I must define the syntax to use in my interpolator; there are three possible variables: [EntityName], [PropertyName], [PropertyValue]. In practice in my strings-resource-file I will have this:

CustomInterResource1

and in case I need a sub-property I would have something like this

CustomInterResource2

The implementation

public class ConventionMessageInterpolator : IMessageInterpolator
{
private const string EntityValidatorConvention = "{{validator.{0}}}";
private const string EntityPropertyValidatorConvention = "{{validator.{0}.{1}}}";
private const string EntityNameConvention = "{{friendly.class.{0}}}";
private const string PropertyNameConvention = "{{friendly.property.{0}}}";
private const string PropertyValueTagSubstitutor = "${{{0}{1}}}";
private static readonly int PropertyValueTagLength = "PropertyValue".Length;

private readonly Regex substitutions =
new Regex(@"\[EntityName\]|\[PropertyName\]|(\[PropertyValue([.][A-Za-z_][A-Za-z_0-9]*)*\])"
, RegexOptions.Compiled);

#region IMessageInterpolator Members

public string Interpolate(InterpolationInfo info)
{
string result = info.Message;
if(string.IsNullOrEmpty(result))
{
result = CreateDefaultMessage(info);
}
do
{
info.Message = Replace(result, info.Entity, info.PropertyName);
result = info.DefaultInterpolator.Interpolate(info);
}
while (!Equals(result, info.Message));
return result;
}

#endregion

public string
CreateDefaultMessage(InterpolationInfo info)
{
return string.IsNullOrEmpty(info.PropertyName) ?
string.Format(EntityValidatorConvention, GetEntityValidatorName(info))
:
string.Format(EntityPropertyValidatorConvention, info.Entity.Name, info.PropertyName);
}

private string GetEntityValidatorName(InterpolationInfo info)
{
var entityValidatorName = info.Entity.Name;
var validatorType = info.Validator.GetType();
if (validatorType.IsGenericType)
{
entityValidatorName = validatorType.GetGenericArguments().First().Name;
}
entityValidatorName = CleanValidatorPostfix(entityValidatorName);
return entityValidatorName;
}

private string CleanValidatorPostfix(string entityValidatorName)
{
var i = entityValidatorName.LastIndexOf("Validator");
return i > 0 ? entityValidatorName.Substring(0, i) : entityValidatorName;
}

public string Replace(string originalMessage, Type entity, string propName)
{
return substitutions.Replace(originalMessage, match =>
{
if ("[EntityName]".Equals(match.Value))
{
return string.Format(EntityNameConvention, entity.Name);
}
else if (!string.IsNullOrEmpty(propName) && "[PropertyName]".Equals(match.Value))
{
return string.Format(PropertyNameConvention, propName);
}
else if (!string.IsNullOrEmpty(propName) && match.Value.StartsWith("[PropertyValue"))
{
return string.Format(PropertyValueTagSubstitutor, propName,
match.Value.Trim('[', ']').Substring(PropertyValueTagLength));
}
return match.Value;
});
}
}

The configuration

To use both, my custom interpolator and my custom strings-resource-file the Loquacious configuration is:

var configure = new FluentConfiguration();
configure
.SetMessageInterpolator<ConventionMessageInterpolator>()
.SetCustomResourceManager("YourProd.Properties.ValidationMessagesConv", Assembly.Load("YourProd"))
.SetDefaultValidatorMode(ValidatorMode.UseExternal);

Results

Having a chunk of strings-resource-file as this

CustomInterResource3

I can write a clean definition like

public class AddressValidation: ValidationDef<IAddress>
{
public AddressValidation()
{
Define(a => a.Street).NotNullableAndNotEmpty();
Define(a => a.Number).GreaterThanOrEqualTo(1);
}
}

public class EntreCallesValidation : ValidationDef<IEntreCalles>
{
public EntreCallesValidation()
{
ValidateInstance.By(IsValid);
}

public bool IsValid(IEntreCalles subject, IConstraintValidatorContext context)
{
if(subject == null)
{
return true;
}
var calleA = subject.CalleA == null ? string.Empty : subject.CalleA.Trim();
var calleB = subject.CalleB == null ? string.Empty : subject.CalleB.Trim();
return !(string.Empty.Equals(calleA) ^ string.Empty.Equals(calleB));
}
}

public class DireccionArgentinaValidation: ValidationDef<DireccionArgentina>
{
public DireccionArgentinaValidation()
{
Define(da => da.CodigoPostal)
.MatchWith("[A-Z][0-9]{4}[A-Z]{3}")
.WithMessage("No es un codigo postal Argentino.");
}
}

public class EmployeePositionValidation : ValidationDefEx<EmployeePosition>
{
public EmployeePositionValidation()
{
const decimal avgSalary = 4000m;
const decimal salaryGap = 1500m;

Define(e => e.Description).NotNullableAndNotEmpty();
Define(ep => ep.Salary)
.IsValid()
.And
.NotEmpty()
.And
.GapLessThanOrEqualTo(salaryGap)
.And
.Include(avgSalary);
}
}

public class StandUpMeetingValidation : ValidationDefEx<StandUpMeeting>
{
public StandUpMeetingValidation()
{
TimeSpan meetingTime = TimeSpan.FromMinutes(20);

Define(m => m.Lapse)
.IsValid()
.And
.NotEmpty()
.And
.Satisfy(
r => (new Range<DateTime>
{
LowLimit = r.LowLimit.Date.AddHours(9),
HighLimit = r.LowLimit.Date.AddHours(17).AddMinutes(30)
}).Includes(r)
)
.WithMessage("{validator.StandUpMeeting.Lapse.WorkingTime}")
.And
.GapLessThanOrEqualTo(meetingTime);
}
}

public class EmployeeValidation : ValidationDef<Employee>
{
public EmployeeValidation()
{
Define(e => e.Name).NotNullableAndNotEmpty()
.And
.LengthBetween(2, 30);

Define(e => e.Salary).GreaterThanOrEqualTo(1000m);
}
}

to have invalid messages as:

Must specify both streets or none.
No es un codigo postal Argentino.
The street of the address is mandatory.
The number must be greater than or equal to 1

The description of the employee position is mandatory.
The rage salary should include:4000

The meeting should happen in working time.
The duration of standup-meeting was too long. Expected less than :00:20:00

with all advantages a strings-resource-file, give me.

27 October 2009

NHibernate.Validator : Customizing messages (bases)

One of the most powerful feature of NHibernate.Validator is its way to manage messages.

In this post are the bases of the massage customization.

The Price

In the last moth this blog was visited from 101 countries but NHibernate.Validator has only 8 translations. The available cultures are: en, es, it, fr, de, nl, lv, pl. Are you seeing the translation in your language ? you don’t ? What you are waiting for ?!!?!!?

From now on, feel in debt with us if you never sent the patch with the translation for your country. Now you can continue reading… ;)

The Message

The message represent what you want show to the user for an invalid value. For example:

public class EmployeeValidation : ValidationDef<Employee>
{
public EmployeeValidation()
{
Define(e => e.Name).NotNullableAndNotEmpty()
.WithMessage("The name of the employee is mandatory.")
.And
.LengthBetween(2,30)
.WithMessage("The length of the name of the employee should be between 2 and 30.");

Define(e => e.Salary).GreaterThanOrEqualTo(1000m)
.WithMessage("The salary should be greater than $1000.");
}
}

Without talk about multi-languages applications let me analyze these messages.

  1. First of all we have three beautiful magic-strings.
  2. If I want be more clear and instead print “name” I want “full name” I must remember to do it in the message of NotNullableAndNotEmpty and in the message of LengthBetween.
  3. If I want print “is mandatory” for any other NotNullableAndNotEmpty usage I must repeat it everywhere.
  4. If I need to change the limits in the LengthBetween constraint and in the GreaterThanOrEqualTo I must remember to change it even in the message.
  5. And if I want to print the actual length of the Name property in the message of LengthBetween constraint ? what should I do ?

The Message definition syntax

To make it short any valid string is a valid message and there are two special cases:

<EmbeddedValue> ::= ‘{’ <Identifier> ‘}’

<PropertyValue> ::= ‘$’‘{’ <PropertyPath> ‘}’

Embedded Value: The embedded value syntax is to solve some of above problems (p1, p2, p3, p4).

Property Value: The property value syntax is to solve p4.

Our RegEx, to recognize valid tokens, is: (?<![#])[$]?{(\w|[._0-9])*}

The Message composition

To solve the p2 and p3 : "The {friendly.property.name} of the employee {validator.NotNullableAndNotEmpty}."

Defined as is, NHV will look in a strings-resource-file (example below) for the value which key is “friendly.property.name” and then for for a value which key is “validator.NotNullableAndNotEmpty”.

If in the strings-resource-file we have :

CustomResource1


The translated message will be: The full name of the employee is mandatory.

To solve p4: "The length of the {friendly.property.name} of the employee should be between {Min} and {Max} characters."

If we look at the Attribute, linked to LengthBetween constraint, we will find that it has two public properties named exactly:

public int Min { get; set; }
public int Max
{
get { return max; }
set { max = value; }
}

So, defined as is, NHV will look in a strings-resource-file for the value which key is “friendly.property.name” and then will look to the public properties of the Attribute, linked to the constraint, to find the value of the property named Min and the property named Max.

Having the above entries, in our strings-resource-file, and giving Min=2 and Max=30 the translated message will be: The length of the full name of the employee should be between 2 and 30 characters.

To solve the p1: this point, perhaps, is more useful if you are developing a multi language application by the way…

Having

CustomResource2

your definition may look as:

public EmployeeValidation()
{
Define(e => e.Name).NotNullableAndNotEmpty()
.WithMessage("{message.employee.name.NotNullableAndNotEmpty}")

Note that the value of “message.employee.name.NotNullableAndNotEmpty” is composed by others variables and NHV will resolve everything recursively.

To solve p5: well… at this point you can imagine that what we need is only use the PropertyValue syntax… but a property of what ?

The property represent a full-property-path starting from the object under validation; that mean that giving a definition as:

.LengthBetween(2,30)
.WithMessage("{message.employee.name.length}");

and a strings-resource-file as

CustomResource3

running

var employee = new Employee {Name = new string('A',31) };
var iv = validatorEngine.Validate(employee);

the message of the invalid value will be:

The full name of the employee should have length between 2 and 30 characters but is 31.

The Resource bundle

How create a strings-resource-file (for mono/multi language applications) is outside the scope of this post; you can find more information starting from this link.

After create the file I have only one recommendation : immediately remove the auto-generated Resource.cs and then clean the property “Custom Tool” from the properties of the file (F4).

To configure your own strings-resource-file you can use

var configure = new FluentConfiguration();
configure.SetCustomResourceManager("YourAssmbly.Properties.ValidationMessages", Assembly.LoadFrom("YourAssembly"))

or

<property name='resource_manager'>
YourFullNameSpace.TheBaseNameOfTheResourceFileWithoutExtensionNorCulture, YourAssembly
</property>
The rules are the same of the ResourceManager class.

Conclusion

Perhaps you think we haven’t solved the problem of magic-strings, but is because define a good convention for message-naming is in your charge.

Perhaps you think “Man!! if I don’t need multi-language I want avoid all those ‘message.class.prop.constraint’ and I prefer to write the message directly.”

Perhaps you think “Man!! I need multi-language but all those ‘message.class.prop.constraint’ really annoys me.”

take it easy ;-)… the story does not end here…

26 October 2009

NHibernate.Validator : Extending ValidationDef

In various applications I’m using my implementation of Range.

public interface IRange<T> : IEquatable<IRange<T>> where T : IComparable<T>
{
T LowLimit { get; }
T HighLimit { get; }
bool IsEmpty { get; }
bool Includes(T value);
bool Includes(IRange<T> other);
bool Overlaps(IRange<T> other);
}

As you can imagine I’m using it to represent various kind of ranges and in each usage I need to validate the range in various ways. Two simply examples:

public class EmployeePosition
{
public string Description { get; set; }
public IRange<decimal> Salary { get; set; }
}

public class StandUpMeeting
{
public ICollection<Employee> Employees { get; set; }
public IRange<DateTime> Lapse { get; set; }
}

To validate IRange<T> properties, through NHV-loquacious-configuration, I can’t extend some NHV’s interfaces because NHV doesn’t know my type (IRange<T>) and a simple entity-validator (as showed here) is not enough because I need to validate various situation of the range; the way to go is create my own set of constraints.

Custom constraints (extending ValidationDef)

public interface IRangeConstraints<T> : ISatisfier<IRange<T>, IRangeConstraints<T>>
where T : IComparable<T>
{
IChainableConstraint<IRangeConstraints<T>> IsValid();
IChainableConstraint<IRangeConstraints<T>> NotEmpty();
IChainableConstraint<IRangeConstraints<T>> Include(T value);
IChainableConstraint<IRangeConstraints<T>> Include(IRange<T> range);
IChainableConstraint<IRangeConstraints<T>> Overlaps(IRange<T> range);
}

Defined the interface I need an entry point to integrate it with the Loquacious configuration. The “natural” extension-point seems the class ValidationDef<T>. There are various way to extend the ValidationDef<T> but in my opinion the most clear, the most useful and the most easy is a simple inheritance.

public class ValidationDefEx<T> : ValidationDef<T> where T : class
{
public IRangeConstraints<decimal> Define(Expression<Func<T, IRange<decimal>>> property)
{
return null;
}

public IRangeConstraints<DateTime> Define(Expression<Func<T, IRange<DateTime>>> property)
{
return null;
}
}

Now I’m ready to check the API.

public class EmployeePositionValidation : ValidationDefEx<EmployeePosition>
{
public EmployeePositionValidation()
{
const decimal avgSalary = 4000m;

Define(e => e.Description).NotNullableAndNotEmpty();
Define(ep => ep.Salary)
.IsValid()
.WithMessage("The {property.salary} should be valid but was ${Salary}.")
.And
.NotEmpty()
.And
.Include(avgSalary)
.WithMessage("The {property.salary} should be around " + avgSalary);
}
}

public class StandUpMeetingValidation : ValidationDefEx<StandUpMeeting>
{
public StandUpMeetingValidation()
{
Define(m => m.Lapse)
.IsValid()
.WithMessage("The {property.lapse} should be valid but was ${Lapse}.")
.And
.NotEmpty();
}
}

The base API work fine; I can go to tests and implementation.

public class RangeConstraints<TR> : BaseConstraints<IRangeConstraints<TR>>, IRangeConstraints<TR>
where TR : IComparable<TR>
{
#region Implementation of IRangeConstraints<TR>

public RangeConstraints(IConstraintAggregator parent, MemberInfo member) : base(parent, member) {}

public IChainableConstraint<IRangeConstraints<TR>> IsValid()
{
return Satisfy(r => r.LowLimit.CompareTo(r.HighLimit) <= 0)
.WithMessage("{validator.range.IsValid}");
}

public IChainableConstraint<IRangeConstraints<TR>> NotEmpty()
{
return Satisfy(r => !r.IsEmpty)
.WithMessage("{validator.range.NotEmpty}");
}

public IChainableConstraint<IRangeConstraints<TR>> Include(TR value)
{
return Satisfy(r => r.Includes(value))
.WithMessage("{validator.range.Include}" + value);
}

public IChainableConstraint<IRangeConstraints<TR>> Include(IRange<TR> range)
{
return Satisfy(r => r.Includes(range))
.WithMessage("{validator.range.Include}" + range);
}

public IChainableConstraint<IRangeConstraints<TR>> Overlaps(IRange<TR> range)
{
return Satisfy(r => r.Overlaps(range))
.WithMessage("{validator.range.Overlaps}" + range);
}

#endregion

#region
Implementation of ISatisfier<IRange<TR>,IRangeConstraints<TR>>

public IChainableConstraint<IRangeConstraints<TR>> Satisfy(Func<IRange<TR>, IConstraintValidatorContext, bool> isValidDelegate)
{
var attribute = new DelegatedValidatorAttribute(new DelegatedConstraint<IRange<TR>>(isValidDelegate));
return AddWithConstraintsChain(attribute);
}

public IChainableConstraint<IRangeConstraints<TR>> Satisfy(Func<IRange<TR>, bool> isValidDelegate)
{
var attribute = new DelegatedValidatorAttribute(new DelegatedSimpleConstraint<IRange<TR>>(isValidDelegate));
return AddWithConstraintsChain(attribute);
}

#endregion
}

and the my validation definition extension look like

public class ValidationDefEx<T> : ValidationDef<T> where T : class
{
public IRangeConstraints<decimal> Define(Expression<Func<T, IRange<decimal>>> property)
{
return new RangeConstraints<decimal>(this, TypeUtils.DecodeMemberAccessExpression(property));
}

public IRangeConstraints<DateTime> Define(Expression<Func<T, IRange<DateTime>>> property)
{
return new RangeConstraints<DateTime>(this, TypeUtils.DecodeMemberAccessExpression(property));
}
}

Work done!! Now I have my own set of constraints for my IRange<T> and I can use it with NHV.

Ups!!! … new request: I must validate the gap of the Salary and the time of the standup-meeting.

Extending the Extension

public static class RangeConstraintsExtensions
{
public static IChainableConstraint<IRangeConstraints<decimal>>
GapLessThanOrEqualTo(this IRangeConstraints<decimal> definition, decimal value)
{
return
definition.Satisfy(r => r.HighLimit - r.LowLimit <= value)
.WithMessage("{validator.range.GapLessThanOrEqualTo}" + value);
}

public static IChainableConstraint<IRangeConstraints<decimal>>
GapGreaterThanOrEqualTo(this IRangeConstraints<decimal> definition, decimal value)
{
return
definition.Satisfy(r => r.HighLimit - r.LowLimit >= value)
.WithMessage("{validator.range.GapGreaterThanOrEqualTo}" + value);
}

public static IChainableConstraint<IRangeConstraints<DateTime>>
GapLessThanOrEqualTo(this IRangeConstraints<DateTime> definition, TimeSpan value)
{
return
definition.Satisfy(r => r.HighLimit - r.LowLimit <= value)
.WithMessage("{validator.TimeRange.GapLessThanOrEqualTo}" + value);
}

public static IChainableConstraint<IRangeConstraints<DateTime>>
GapGreaterThanOrEqualTo(this IRangeConstraints<DateTime> definition, TimeSpan value)
{
return
definition.Satisfy(r => r.HighLimit - r.LowLimit >= value)
.WithMessage("{validator.TimeRange.GapGreaterThanOrEqualTo}" + value);
}
}

And now my two definitions can look like

public class EmployeePositionValidation : ValidationDefEx<EmployeePosition>
{
public EmployeePositionValidation()
{
const decimal avgSalary = 4000m;
const decimal salaryGap = 1500m;

Define(e => e.Description).NotNullableAndNotEmpty();
Define(ep => ep.Salary)
.IsValid()
.WithMessage("The {property.salary} should be valid but was ${Salary}.")
.And
.NotEmpty()
.And
.GapLessThanOrEqualTo(salaryGap)
.WithMessage("The gap of {property.salary} should be " + salaryGap)
.And
.Include(avgSalary)
.WithMessage("The {property.salary} should be around " + avgSalary);
}
}

public class StandUpMeetingValidation : ValidationDefEx<StandUpMeeting>
{
public StandUpMeetingValidation()
{
TimeSpan meetingTime = TimeSpan.FromMinutes(20);

Define(m => m.Lapse)
.IsValid()
.WithMessage("The {property.lapse} should be valid but was ${Lapse}.")
.And
.NotEmpty()
.And
.Satisfy(
r =>(new Range<DateTime>
{
LowLimit = r.LowLimit.Date.AddHours(9),
HighLimit = r.LowLimit.Date.AddHours(17).AddMinutes(30)
}).Includes(r)
)
.WithMessage("The meeting should happen during working time")
.And
.GapLessThanOrEqualTo(meetingTime)
.WithMessage("The {entity.StandUpMeeting} was too long.");
}
}

Conclusion

Now you know one reason because NHibernate.Validator is part of my Gum-Architecture: it is compressible, extensible, ball-able, cube-able, flat-able… ;) and the story does not end here...

24 October 2009

NHibernate.Validator : The “Satisfy” way of custom Validators

The Satisfy (perhaps it sound familiar to some SharpTestsEx users ;) ).

To show how it work the example is a constraint for Person.Name: a Name is significant when it has more than three characters, is composed by letters and the first letter is in uppercase.

To create a that validator, in the classic way, we should create an Attribute implementing IRuleArgs and then a class implementing IValidator, or combine some existing validators for strings (in this case min-length and regex or only a regex).

Using the Satisfier the work to do is so hard as write a lambda:

public class PersonValidation: ValidationDef<Person>
{
public PersonValidation()
{
Define(p => p.Name)
.Satisfy(name => name != null && name.Length >= 3 && Regex.IsMatch(name,"[A-Z][a-z]*"))
.WithMessage("The Name is not significant.");
}
}
The Satisfier is available for those property-types where we consider it has sense.

Implemented as is the Satisfier appear as not reusable; if we want use the same, identical, validation for a pet's name we should rewrite the lambda in the validation definition for our Pet class. hmmm… perhaps we shouldn’t.

We can extend Loquacious:

public static IChainableConstraint<IStringConstraints> Significant(this IStringConstraints definition)
{
return definition.Satisfy(s => s != null && s.Length >= 3 && Regex.IsMatch(s, "[A-Z][a-z]*"));
}

Now we can use the extension in this way:

public class PersonValidation: ValidationDef<Person>
{
public PersonValidation()
{
Define(p => p.Name).Significant()
.WithMessage("The Name is not significant.");
}
}

public class PetValidation : ValidationDef<Pet>
{
public PetValidation()
{
Define(p => p.Name).Significant()
.WithMessage("The Name is not significant.");
}
}

Note: Don’t take care about the duplication of the massage, that will be matter of another post.

If you want make the Significant constraint a little bit more flexible, you can simply use parameters as:

public static IChainableConstraint<IStringConstraints> Significant(
this IStringConstraints definition,
int minLength)
{
return definition.Satisfy(
s => s != null && s.Length >= minLength && Regex.IsMatch(s, "[A-Z][a-z]*"));
}

and use it as

public class PersonValidation: ValidationDef<Person>
{
public PersonValidation()
{
const int minNameLength = 3;
Define(p => p.Name).Significant(3)
.WithMessage(
string.Format("The Name is not significant (min length {0}).", minNameLength));
}
}

public class PetValidation : ValidationDef<Pet>
{
public PetValidation()
{
const int minNameLength = 4;
Define(p => p.Name).Significant(minNameLength)
.WithMessage(
string.Format("The Name is not significant (min length {0}).",minNameLength));
}
}

As you can see, define a custom-reusable Validator with NHibernate.Validator, is a piece of cake.

23 October 2009

NHibernate.Validator : Fine grained and polymorphic validation

If you know that you can define constraints for classes, properties and even for field, what mean “Fine grained validation” ?

In NHV, when you define a validator you are defining a validator for a System.Type… well… for real you can define a validator for various types but let me simplify the concept a little bit (parafrasando lo psico nano: “mi consenta”).

In OOP the Type can be polymorphic and we know it.

A classic example

AnimalsDiagramIn this schema you can define validators for each Type. The Animal may have its validation, Mammal may have its validation and so on.

A Cat is a Mammal and is a Animal but is not a Reptile… clear, no?

Each time you will register a Type in the ValidatorEngine NHV will investigate the Type graph and will register the validator of each Type in the graph as part of the validation of the Type you are register.

For the above diagram this mean:

Because a Cat is a Mammal it must satisfy the same rules defined for Mammal and because a Mammal is a Animal it must satisfy the same rules defined for Animal.

Because a Reptile is a Animal it must satisfy the same rules defined for Animal.

Because a Dog is a Mammal it must satisfy the same rules defined for Mammal and because a Mammal is a Animal it must satisfy the same rules defined for Animal. Because a Dog is not a Cat it shouldn't satisfy the rules defined for a Cat.

Composition through interfaces

The domain:

public interface IAdress
{
string Street { get; }
int Number { get; }
}

public interface IEntreCalles
{
string CalleA { get; }
string CalleB { get; }
}

public class DireccionArgentina: IAdress, IEntreCalles
{
public string Street { get; set; }
public int Number { get; set; }
public string CalleA { get; set; }
public string CalleB { get; set; }
public string CodigoPostal { get; set; }
}

IAddress is a generic interface to define an address. IEntreCalle (that mean “between streets”) is another generic interface for some south-America countries. DireccionArgentina define an address for Argentina with its Postal-Code and, as you can see, it implements the others two interfaces.

As I done with domain classes, I would define my generic constraints for each Type.

public class AddressValidation: ValidationDef<IAdress>
{
public AddressValidation()
{
Define(a => a.Street).NotNullableAndNotEmpty();
Define(a => a.Number).GreaterThanOrEqualTo(1);
}
}

public class EntreCallesValidation : ValidationDef<IEntreCalles>
{
public EntreCallesValidation()
{
ValidateInstance.By(IsValid)
.WithMessage("Debe especificar ambas calles o ninguna.");
}

public bool IsValid(IEntreCalles subject, IConstraintValidatorContext context)
{
if(subject == null)
{
return true;
}
var calleA = subject.CalleA == null ? string.Empty : subject.CalleA.Trim();
var calleB = subject.CalleB == null ? string.Empty : subject.CalleB.Trim();
return !(string.Empty.Equals(calleA) ^ string.Empty.Equals(calleB));
}
}

public class DireccionArgentinaValidation: ValidationDef<DireccionArgentina>
{
public DireccionArgentinaValidation()
{
Define(da => da.CodigoPostal)
.MatchWith("[A-Z][0-9]{4}[A-Z]{3}")
.WithMessage("No es un codigo postal Argentino.");
}
}

Each Type has its own specific constraints and the follow test has green-field:

var configure = new FluentConfiguration();
configure.Register(new[]
{
typeof(AddressValidation),
typeof(EntreCallesValidation),
typeof(DireccionArgentinaValidation)
})
.SetDefaultValidatorMode(ValidatorMode.UseExternal);
var ve = new ValidatorEngine();

ve.Configure(configure);
var valid = new DireccionArgentina
{
Street = "Cabildo",
Number = 2450,
CalleA = "Monroe",
CalleB = "Blanco Encalada",
CodigoPostal = "C1428AAT"
};
ve.IsValid(valid).Should().Be.True();

var notValidBecauseStreetNull = new DireccionArgentina
{
Number = 2450,
CalleA = "Monroe",
CalleB = "Blanco Encalada",
CodigoPostal = "C1428AAT"
};
ve.IsValid(notValidBecauseStreetNull).Should().Be.False();

var notValidBecauseCalleAEmpty = new DireccionArgentina
{
Street = "Cabildo",
Number = 2450,
CalleA = " ",
CalleB = "Blanco Encalada",
CodigoPostal = "C1428AAT"
};
ve.IsValid(notValidBecauseCalleAEmpty).Should().Be.False();

var notValidBecauseWrongCodigoPostal = new DireccionArgentina
{
Street = "Cabildo",
Number = 2450,
CalleA = "Monroe",
CalleB = "Blanco Encalada",
CodigoPostal = "1428"
};
ve.IsValid(notValidBecauseWrongCodigoPostal).Should().Be.False();

Which is the trick ?

A DireccionArgentina "is a" IAddress and "is a" IEntreCalle.

The Rule

As you can see the rule to follow is simple and is: "is a" no matter if the Type is a concrete class, an abstract class or an interface.

22 October 2009

NHibernate.Validator : Extending Loquacious configuration

The needs to extend the configuration come when you having some custom and reusable validators.

For this post I will use a constraint to solve : if a string property is null or empty it is valid, but if it is not empty it must satisfy the minimal required number of characters.

Creating the Validator

The first step is create a class to hold the information needed during validation; in this case the minimal length required.

In NHV this class must inherits from System.Attribute and implements IRuleArgs.

[Serializable]
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class OptionMinLengthAttribute: Attribute, IRuleArgs
{
private string message = "the length must be greater than, or equal to, {MinLength}";

public OptionMinLengthAttribute(int minLength)
{
MinLength = minLength;
}

public int MinLength { get; set; }

#region IRuleArgs Members

public string Message
{
get { return message; }
set { message = value; }
}

#endregion
}

The Attribute is not completed because we need to specify the related validator but first we must implements it (with a test obviously):

[Serializable]
public class OptionMinLengthValidator : IInitializableValidator<OptionMinLengthAttribute>
{
public int MinLength { get; set; }

#region Implementation of IValidator

public void Initialize(OptionMinLengthAttribute parameters)
{
MinLength = parameters.MinLength;
}

public bool IsValid(object value, IConstraintValidatorContext context)
{
if (!ReferenceEquals(null, value) && !(value is string))
{
return false;
}
if (ReferenceEquals(null, value))
{
return true;
}
int realLength = ((string) value).Trim().Length;
return realLength == 0 || realLength >= MinLength;
}

#endregion
}

Note: the validator implements IInitializableValidator<OptionMinLengthAttribute> because we need a way to configure the variable MinLength in the validator-instance.

Now we can go back to the attribute and wire it to its related validator:

  [Serializable]
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
[ValidatorClass(typeof(OptionMinLengthValidator))]
public class OptionMinLengthAttribute : Attribute, IRuleArgs

Extending Loquacious

Our new validator is ready to be used as attribute (ValidatorMode.UseAttribute) or even using XML, but if we are using the Loquacious configuration, and we want reuse the definition, the next step is extend NHV’s definitions.

Considerations about our validator:
  1. It is working only for string so the candidate for the extension is IStringConstraints.
  2. It is chainable with others string constraints.
public static class StringConstraintsExtensions
{
public static IChainableConstraint<IStringConstraints> IfNotEmptyMinLength(this IStringConstraints definition,
int minLength)
{
var ruleArgs = new OptionMinLengthAttribute(minLength);
((IConstraints)definition).AddRuleArg(ruleArgs);
return new ChainableConstraint<IStringConstraints>(definition, ruleArgs);
}
}

What will happen will be:

ShowExtension

and we can chain the constraint with others as

public class AddressValidation: ValidationDef<Address>
{
public AddressValidation()
{
Define(a => a.AdditionalInfo).IfNotEmptyMinLength(5).And.MaxLength(80);
}
}
and reuse and reuse and reuse our new constraint.