docs: def validate(self, expected_type, is_array, val):
          """
          Validates that the expected type matches the value
  
          Returns two element tuple: (bool, string)
  
          - `bool` - True if valid, False if not
          - `string` - Description of validation error, or None if valid
  
          :Parameters:
            expected_type
              string name of the type expected. This may be a Barrister primitive, or a user defined type.
            is_array
              If True then require that the val be a list
            val
              Value to validate against the expected type
          """
          if val == None:
              if expected_type.optional:
                  return True, None
              else:
                  return False, "Value cannot be null"
          elif is_array:
              if not isinstance(val, list):
                  return self._type_err(val, "list")
              else:
                  for v in val:
                      ok, msg = self.validate(expected_type, False, v)
                      if not ok:
                          return ok, msg
          elif expected_type.type == "int":
              if not isinstance(val, (long, int)):
                  return self._type_err(val, "int")
          elif expected_type.type == "float":
              if not isinstance(val, (float, int, long)):
                  return self._type_err(val, "float")
          elif expected_type.type == "bool":
              if not isinstance(val, bool):
                  return self._type_err(val, "bool")
          elif expected_type.type == "string":
              if not isinstance(val, (str, unicode)):
                  return self._type_err(val, "string")
          else:
              return self.get(expected_type.type).validate(val)
          return True, None