Thursday, May 7, 2009

Customizing the code of CCNet : add validation

It is nice if you can inform a user that certain settings are not guaranteed to work. For example the project name : CompanyFramework that will pose no problems, but a name like my funky project in C# for scraping http://www.google.com could be a problem. Now I know this name WILL pose a problem, since the project name is also used for file names, folder names, links, ... as you can see the character / is not allowed in a file nor folder name. So how to solve this?
Options :
  • do nothing, let the program crash
  • replace invalid chars with valid ones, underscore or so
  • throw an exception, so the user must change the invalid name
  • inform the user that the name might cause problems

Option 1 : a no-go, problems must be fixed.
Option 2 : introduces other problems, because for one you have the possibility of 'renaming' a project into another existing one, and the user does not know.
Option 3 : that is a possible approach, but who decides what is a bad character? in 1990 a space was invalid for a file name (yep, I'm THAT old) and now it is not anymore
Option 4 : I think this is the best, you inform the user that a certain setting could pose a problem, but let the program continue. If it is a problem the user knows what to do to make it work, or should now ;-)

Now from version 1.5 onwards, CCNet has a neat validation system. It allows to set certain conditions as an error (throw exception type), or set as warning (just inform the user). And it shows in the log AND in the CCNetValidator program. How to use this neat system ? read on ...

I'll take the publisher from my previous posts as an example, and update it with the validation. Now this is a very basic publisher, but is perfect as a basic example.

The only thing needed to do is implement IConfigurationValidation which can be found in the config namespace : ThoughtWorks.CruiseControl.Core.Config.IConfigurationValidation
This will add a procedure :
public void Validate(IConfiguration configuration, object parent, Core.Config.IConfigurationErrorProcesser errorProcesser)
{

}

For showing a warning use : errorProcesser.ProcessWarning("This is a warning");
For showing an error, and prevent starting ccnet : errorProcesser.ProcessError("This is an error");
Very easy ! A bit more meaningful :

public void Validate(IConfiguration configuration, object parent, Core.Config.IConfigurationErrorProcesser errorProcesser)
{
long MB = 1000000;

if (System.IO.DriveInfo.GetDrives()[0].AvailableFreeSpace < 50 * MB)
errorProcesser.ProcessWarning("drive is getting low on space");
}


An even better idea for a validation is the following :

public virtual void Validate(IConfiguration configuration, object parent, IConfigurationErrorProcesser errorProcesser)
{
if (parent is Project)
{
Project parentProject = parent as Project;

// Attempt to find this publisher in the publishers section
bool isPublisher = false;
foreach (ITask task in parentProject.Publishers)
{
if (task == this)
{
isPublisher = true;
break;
}
}

// If not found then throw a validation exception
if (!isPublisher)
{
errorProcesser.ProcessWarning("This publishers is best placed in the publishers section of the configuration");
}
}
else
{
errorProcesser.ProcessError(
new CruiseControlException("This publisher can only belong to a project"));
}
}

No comments:

Post a Comment