Skip to content
Stephanie Paige edited this page May 6, 2014 · 18 revisions

(WIP)

Authoring schema constraints

A field in a ClothoSchema can declare any number of constraints, in a list, in the constraints field. A constraint should contain a constraintType and values. constraintType should be a string naming a constraint type available to Clotho's validation engine. values should be a map with parameter names as keys and parameter values as values.

In the example below, Pattern is the constraintType. This constraint has one required parameter - regexp, which is set to the value "[ATUCGRYKMSWBDHVN]*", matching any string that contains only characters from the IUPAC nucleic acid code. Additionally, flags, an optional parameter, is set to contain "CASE_INSENSITIVE", allowing lower and uppercase letters to match the regexp.

Currently, the validation engine has the constraints in the standard java validation api and the constraints added by hibernate validator.

Constraints example:

"constraints":[
            {
               "constraintType":"javax.validation.constraints.Pattern",
               "values":{
                  "flags":[
                     "CASE_INSENSITIVE"
                  ],
                  "regexp":"[ATUCGRYKMSWBDHVN]*"
               }
            }
         ],

Example in context:

{
   "id":"org.clothocad.model.SimpleFeature",
   "language":"JSONSCHEMA",
   "schema":"org.clothocad.core.schema.ClothoSchema",
   "name":"SimpleFeature",
   "description":"A simple and sloppy representation of a Feature or other DNA sequence",
   "fields":[
      {
         "name":"sequence",
         "type":"string",
         "example":"ATACCGGA",
         "access":"PUBLIC",
         "constraints":[
            {
               "constraintType":"javax.validation.constraints.Pattern",
               "values":{
                  "flags":[
                     "CASE_INSENSITIVE"
                  ],
                  "regexp":"[ATUCGRYKMSWBDHVN]*"
               }
            }
         ],
         "description":"the sequence of the feature"
      }
   ]
}

Submitting an object for validation

Use the channel validate to send validation requests. data in the request object should be the object to validate, as a JSON object. The object must declare a schema (have a property named schema) so that Clotho knows what schema to use. Validate does not currently use any options.

The response format

The response from the server for a validation request is a list of objects that describe any constraint violations in the submitted object. If the returned list is empty, there were no violations and the object passes validation.

The format of the constraint violation objects is currently a frank translation of javax.violation.ConstraintViolation. Below is a breakdown of what information is in each property:

  • constraintDescriptor: An object with the following fields:
    • annotation: The name of the java annotation describing the constraint declaration.
    • attributes: A map containing the constraint parameter names as keys and the constraint values as value. groups, message, and payload will always be present but will generally not have any useful info in them. All other fields are pertinent to that constraint in particular.
    • composingConstraints: a list of composing constraint descriptions, if this constraint is a composition of other constraints
    • constraintValidatorClasses: The names of java classes that provide the actual validation logic. (Unlikely we want to keep this).
    • groups: The names of the groups the constraint is applied on.
    • messageTemplate: The name of the java class that provides the message template for this constraint (Unlikely we want to keep this)
    • payload: Currently, no validations we use provide payloads, so this will always be an empty array.
    • reportAsSingleViolation: true if the constraint is 'fail-fast' and will halt evaluation with the first composed constraint error.
  • executableParameters: If the constraint violation is caused by a method invocation returning an invalid value, contains a list of the arguments of the method invocation.
  • executableReturnValue: If the constraint violation is caused by a method invocation returning an invalid value, contains the value failing to pass the constraint.
  • invalidValue: the value failing to pass the constraint.
  • leafBean: For our purposes, always a duplicate of rootBean
  • message: the interpolated error message for this constraint violation
  • messageTemplate: The name of the java class that provides the message template for this constraint violation (Unlikely we want to keep this)
  • propertyPath: A list of path nodes to the invalid value from rootBean. Path nodes are objects with the following fields:
    • index: The index of the node if it is contained in a list
    • key: The key of the node if it is contained in a map/object
    • kind: What the node represents. (Will be one of BEAN, CONSTRUCTOR, CROSS_PARAMETER, METHOD, PARAMETER, PROPERTY, RETURN_VALUE)
    • name: The name of the element the node represents, or null if it is an object.
    • inIterable: true if the node is contained in an iterable, like a map or list.
  • rootBean: The object that failed validation
  • rootBeanClass: The schema of the object that failed validation

Example

{
   "channel":"validate",
   "data":[
      {
         "rootBean":{
            "id":"5367fd4544aed4cfdd1c21a7",
            "name":null,
            "dateCreated":null,
            "visibility":null,
            "sequence":"this is not a valid sequence"
         },
         "propertyPath":{
            "nodeList":[
               {
                  "name":null,
                  "parent":null,
                  "index":null,
                  "key":null,
                  "inIterable":false,
                  "iterable":false
               },
               {
                  "name":"sequence",
                  "parent":{
                     "name":null,
                     "parent":null,
                     "index":null,
                     "key":null,
                     "inIterable":false,
                     "iterable":false
                  },
                  "index":null,
                  "key":null,
                  "inIterable":false,
                  "iterable":false
               }
            ],
            "currentLeafNode":{
               "name":"sequence",
               "parent":{
                  "name":null,
                  "parent":null,
                  "index":null,
                  "key":null,
                  "inIterable":false,
                  "iterable":false
               },
               "index":null,
               "key":null,
               "inIterable":false,
               "iterable":false
            },
            "hashCode":0
         },
         "constraintDescriptor":{
            "annotation":{
               "h":{
                  "type":"javax.validation.constraints.Pattern",
                  "memberValues":{
                     "message":"{javax.validation.constraints.Pattern.message}",
                     "flags":[
                        "CASE_INSENSITIVE"
                     ],
                     "payload":[

                     ],
                     "groups":[

                     ],
                     "regexp":"[ATUCGRYKMSWBDHVN]*"
                  }
               }
            },
            "groups":[
               "javax.validation.groups.Default"
            ],
            "attributes":{
               "message":"{javax.validation.constraints.Pattern.message}",
               "payload":[

               ],
               "flags":[
                  "CASE_INSENSITIVE"
               ],
               "regexp":"[ATUCGRYKMSWBDHVN]*",
               "groups":[

               ]
            },
            "composingConstraints":[

            ],
            "elementType":"FIELD",
            "definedOn":"DEFINED_LOCALLY",
            "compositionType":"AND",
            "payload":[

            ],
            "constraintValidatorClasses":[
               "org.hibernate.validator.internal.constraintvalidators.PatternValidator"
            ],
            "reportAsSingleViolation":false
         },
         "messageTemplate":"{javax.validation.constraints.Pattern.message}",
         "rootBeanClass":"org.clothocad.model.SimpleFeature",
         "message":"must match \"[ATUCGRYKMSWBDHVN]*\"",
         "invalidValue":"this is not a valid sequence",
         "leafBean":{
            "id":"5367fd4544aed4cfdd1c21a7",
            "name":null,
            "dateCreated":null,
            "visibility":null,
            "sequence":"this is not a valid sequence"
         }
      }
   ],
   "requestId":"1",
   "options":null
}

Questions for Feedback

  • Should we have 'magic strings' that shorten the names of some of the javax.validation constraints?
  • What parts of the current response object should be removed/condensed/moved to a different part of the object?
Clone this wiki locally