Print Page | Close Window

Cross-Type Verifiers

Printed From: IdeaBlade
Category: DevForce
Forum Name: DevForce 2010
Forum Discription: For .NET 4.0
URL: http://www.ideablade.com/forum/forum_posts.asp?TID=3001
Printed Date: 22-Jan-2026 at 9:44am


Topic: Cross-Type Verifiers
Posted By: jbelci
Subject: Cross-Type Verifiers
Date Posted: 10-Oct-2011 at 7:44pm
Hi Guys

I have been trying to implement cross type verifiers, followng the examples from http://drc.ideablade.com/xwiki/bin/view/Documentation/validation%2Dcreate%2Dcustom%2Dverifier.  My first try worked fine, but i am now having some issues with a second object structure i am trying to implement it on.

I have 2 object types in my graph, these are Person and PersonPosition. The person position is a collection of positions the person held while employed by a company, each of these has a start and end date.

i,e,
Person
      PersonPositions (enumerable list of person position)
           StartDate (propery of person position)
           EndDate (propery of person position)

The business rule i am trying to implement is that none of the person positions' dates can overlap with other positions. I can do this in the person position object and it works reasonably well (shows that the position i just edited has an error), however when one of the dates is chaged, i want all the person positions to run validation to check against the other positions. This is so i can show the user all positions that have overlapping dates.

I tried to implement this at the person object level using the code below. it compiles and runs fine, but cant seem to get the triggers to fire. I am hoping its something small i am doing wrong.

///<summary>Get the PersonPosition Verifier.</summary>
            private static Verifier GetPersonPositionVerifier()
            {
                string description =
                  "Position dates must not overlap";
                DelegateVerifier<Person> v = new DelegateVerifier<Person>(description, PersonPositionValidCondition);

                v.VerifierOptions.ExecutionModes =VerifierExecutionModes.InstanceAndOnAfterSetTriggers;

                TriggerItem startDateTriggerItem = new TriggerItem(typeof(PersonPosition), PersonPosition.PathFor(e => e.StartDate));
                TriggerLink startDateTriggerLink = new TriggerLink(startDateTriggerItem, GetPositionsAssociatedWithPerson, true);
                v.AddTrigger(startDateTriggerLink);

                TriggerItem endDateTriggerItem = new TriggerItem(typeof(PersonPosition), PersonPosition.PathFor(e => e.EndDate));
                TriggerLink endDateTriggerLink = new TriggerLink(endDateTriggerItem, GetPositionsAssociatedWithPerson, true);

                v.AddTrigger(endDateTriggerLink);

                return v;
            }

            public static IEnumerable<PersonPosition> GetPositionsAssociatedWithPerson(Object person)
            {
                var aPerson = (Person)person;
                return aPerson.PersonPositions;
            }

private static VerifierResult PersonPositionValidCondition(
              Person pTarget, TriggerContext pTriggerContext,
              VerifierContext pVerifierContext)
            {

               //Do validation stuff here
            }


Any help would be greatly appriciated

regards
Jason
         



Replies:
Posted By: DenisK
Date Posted: 12-Oct-2011 at 1:04pm
Hi Jason;

I want to make sure I understand your business rule.

You have a Person and it has PersonPosition collections. Each PersonPosition has a StartDate and EndDate. You want to make sure that the dates do not overlap with the other PersonPosition, in other words, a Person should only hold at most 1 position (PersonPosition) at any given time within a company.

This means that you're only comparing between a Person.PersonPositions collection. This is not exactly cross type verifiers as you're only verifying one type of object, the PersonPosition type.

One suggestion is to implement something similar to this.

private static Verifier GetPersonPositionVerifier()
{
     string description = "Position dates must not overlap";
     DelegateVerifier<PersonPosition> v = 
             new DelegateVerifier<PersonPosition>(description, PersonPositionValidCondition);

     v.VerifierOptions.ExecutionModes =VerifierExecutionModes.InstanceAndOnAfterSetTriggers;
     v.AddTrigger(PersonPosition.PathFor(p => p.StartDate));
     v.AddTrigger(PersonPosition.PathFor(p => p.EndDate));                

     return v;
}

private static VerifierResult PersonPositionValidCondition
    (PersonPosition pTarget, TriggerContext pTriggerContext, VerifierContext pVerifierContext)
{

   var allPositions = pTarget.Person.PersonPositions;
   bool isOk = true;
   foreach(var aPosition in allPositions)
   {
        //insert logic to check against all other positions here
   }
   
   return VerifierResult(isOk);
}

I hope I'm on the right track here. Please do let me know if I'm not.



Posted By: jbelci
Date Posted: 12-Oct-2011 at 5:47pm
That is exactly correct, and I have written that code above (close enough anyway) and it works fine.

The issue is that I want all overlapping PersonPosition objects to raise verification alerts when this happens, not just the one that was just edited.

Cheers
Jason



Posted By: DenisK
Date Posted: 13-Oct-2011 at 11:53am
Ah I see. Then let's see if the following works. I've tested this on my machine (with Employee.Orders in NorthwindIB model) so it should.

You're actually quite close with a few changes.

 private static Verifier GetPersonPositionVerifier()
            {
                string description =
                  "Position dates must not overlap";
                DelegateVerifier<PersonPosition> v = new DelegateVerifier<
PersonPosition>(description, PersonPositionValidCondition);

                v.VerifierOptions.ExecutionModes =VerifierExecutionModes.InstanceAndOnAfterSetTriggers;

                TriggerItem startDateTriggerItem = new TriggerItem(typeof(PersonPosition), PersonPosition.PathFor(e => e.StartDate));
                TriggerLink startDateTriggerLink = new TriggerLink(startDateTriggerItem, GetPositionsAssociatedWithPerson, true);
                v.AddTrigger(startDateTriggerLink);

                TriggerItem endDateTriggerItem = new TriggerItem(typeof(PersonPosition), PersonPosition.PathFor(e => e.EndDate));
                TriggerLink endDateTriggerLink = new TriggerLink(endDateTriggerItem, GetPositionsAssociatedWithPerson, true);

                v.AddTrigger(endDateTriggerLink);

                return v;
            }

            public static IEnumerable<PersonPosition> GetPositionsAssociatedWithPerson(Object personPos)
            {
                var aPerson = ((PersonPosition)personPos).Person;
                return aPerson.PersonPositions;
            }


Posted By: jbelci
Date Posted: 13-Oct-2011 at 7:49pm
Thank you, That worked a treat.

I was sure i tried something like that. I must have just stuffed up something somewhere.

Once again, thanks for the help and the quick responses

Jason



Print Page | Close Window