Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider ModelNode.Validate<TDefinition>(Func<TDefinition, bool> callback) method #882

Closed
SubPointSupport opened this issue Sep 4, 2016 · 5 comments

Comments

@SubPointSupport
Copy link
Contributor

SPMeta2 should provide an easy way to validate the model. Something like as following:

var model = SPMeta2Model.NewSiteModel( ... );

model.Validate<FieldDefinition>( field => {
    return field.InternalName.StartsWith("myIntranet_");
});

model.Validate<FieldDefinition>( validationContext => {
    # validationContext object has tons of useful props as per the specs below
    return validationContext.Definition.InternalName.StartsWith("myIntranet_");
});

Model node should have an extension method to plug a custom validation via fun callback with the following criteria:

  • Strong typing override to target particular artifact types
  • Access to parent "model node" so that we would know what's the scope of the artifact is
  • Access to the whole model
  • Access to the collection of all artifacts of the targeted type (checks in unique ID/Name so on)

Most likely, a "validation context" is to be pass to validation callback so that more properties can be added later.

Related to community feedback on ListDefinition validation:
https://www.yammer.com/spmeta2feedback/#/Threads/show?threadId=759523765

@SubPointSupport SubPointSupport added this to the 1.2.90 release milestone Sep 4, 2016
@SubPointSupport SubPointSupport self-assigned this Sep 4, 2016
@SubPointSupport
Copy link
Contributor Author

First draft for the fluent validation API:

 var model = SPMeta2Model.NewSiteModel(site =>
            {
                site
                   .AddField(new FieldDefinition { InternalName = "my_field1" })
                   .AddField(new FieldDefinition { InternalName = "my_field2" })
                   .AddField(new FieldDefinition { InternalName = "my_field3" });
            });

            // all fields have "my_" prefix
            // fieldPrefixValidationResult contains a set of 'validation context' per every model node (definition) in the model
            var fieldPrefixValidationResult = model.Validate<FieldDefinition>(context =>
            {
                // context exposes three pair of props to get current, parent and child model node / definition
                // IsValid and Message is other props for the validation result

                // context.ValidationContext.ChildDefinitions
                // context.ValidationContext.ChildModelNodes

                // context.ValidationContext.CurrentDefinition
                // context.ValidationContext.CurrentModelNode

                // context.ValidationContext.ParentDefinition
                // context.ValidationContext.ParentModelNode

                // context.IsValid
                // context.Message

                context.IsValid = context.ValidationContext.CurrentDefinition.InternalName.StartsWith("my_");
            });

            Assert.IsNotNull(fieldPrefixValidationResult);
            Assert.AreEqual(true, fieldPrefixValidationResult.IsValid);

            // all fields have unique GUID
            var uniqueFieldIdValidationResult = model.Validate<SiteDefinition>(context =>
            {
                var allSiteFields = context.ValidationContext.GetChildDefinitions<FieldDefinition>();

                // all fields have non-default Ids
                // and amount of unique IDs is the same as the amount of fields 
                context.IsValid = allSiteFields.All(f => f.Id != default(Guid))
                               && allSiteFields.Select(f => f.Id).Distinct().Count() == allSiteFields.Count();

                if (!context.IsValid)
                {
                    context.Message = "Either some fields have empty ID or ID is non unique";
                }
            });

            Assert.IsNotNull(uniqueFieldIdValidationResult);

@SubPointSupport SubPointSupport modified the milestones: 1.2.90 release, 2016.10.03, 1.2.90 Sep 27, 2016
SubPointSupport added a commit that referenced this issue Sep 27, 2016
…llback) method #882

+ added DefaultFluentModelValidationService prototype and tests
@SubPointSupport
Copy link
Contributor Author

Implemented as per drafts early, added "Regression.Services.DefaultFluentModelValidationService" tests.

@norvegec
Copy link

norvegec commented Nov 12, 2016

Looks like in the second example (// all fields have unique GUID) enumeration of context.ValidationContext.GetChildDefinitions<FieldDefinition>() does not return any item.
But, if you remove generic constaint from model.Validate(..) method it works as expected.

@norvegec
Copy link

norvegec commented Nov 12, 2016

Here is and improved version of second example (I check for InternalName in this case):

siteFieldsModel.Validate(context =>
{
    var allSiteFields = context.ValidationContext
        .GetChildDefinitions<FieldDefinition>()
        .Select(f => f.InternalName);

    var duplicates = allSiteFields
        .GroupBy(x => x)
        .Where(x => x.Count() > 1)
        .Select(x => x.Key)
        .ToList();

    duplicates.ForEach(d => Console.WriteLine("Duplicate field:" + d));

    Assert.IsTrue(duplicates.Count == 0);
});        

@SubPointSupport
Copy link
Contributor Author

Alright, so that is the issue if any?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants