model.go raw

   1  package dara
   2  
   3  import (
   4  	"encoding/json"
   5  	"errors"
   6  	"fmt"
   7  	"reflect"
   8  	"regexp"
   9  	"strconv"
  10  	"strings"
  11  )
  12  
  13  type Model interface {
  14  	Validate() error
  15  	ToMap() map[string]interface{}
  16  	copyWithouStream() Model
  17  }
  18  
  19  func Validate(params interface{}) error {
  20  	if params == nil {
  21  		return nil
  22  	}
  23  	requestValue := reflect.ValueOf(params)
  24  	if requestValue.IsNil() {
  25  		return nil
  26  	}
  27  	err := validate(requestValue.Elem())
  28  	return err
  29  }
  30  
  31  // ValidateRequired checks if a value is set (non-nil)
  32  func ValidateRequired(value interface{}, fieldName string) error {
  33  	if value == nil {
  34  		return errors.New(fieldName + " should be setted")
  35  	}
  36  
  37  	// Check for typed nil pointers
  38  	switch v := value.(type) {
  39  	case *string:
  40  		if v == nil {
  41  			return errors.New(fieldName + " should be setted")
  42  		}
  43  	case *int:
  44  		if v == nil {
  45  			return errors.New(fieldName + " should be setted")
  46  		}
  47  	case *int8:
  48  		if v == nil {
  49  			return errors.New(fieldName + " should be setted")
  50  		}
  51  	case *int16:
  52  		if v == nil {
  53  			return errors.New(fieldName + " should be setted")
  54  		}
  55  	case *int32:
  56  		if v == nil {
  57  			return errors.New(fieldName + " should be setted")
  58  		}
  59  	case *int64:
  60  		if v == nil {
  61  			return errors.New(fieldName + " should be setted")
  62  		}
  63  	case *uint:
  64  		if v == nil {
  65  			return errors.New(fieldName + " should be setted")
  66  		}
  67  	case *uint8:
  68  		if v == nil {
  69  			return errors.New(fieldName + " should be setted")
  70  		}
  71  	case *uint16:
  72  		if v == nil {
  73  			return errors.New(fieldName + " should be setted")
  74  		}
  75  	case *uint32:
  76  		if v == nil {
  77  			return errors.New(fieldName + " should be setted")
  78  		}
  79  	case *uint64:
  80  		if v == nil {
  81  			return errors.New(fieldName + " should be setted")
  82  		}
  83  	case *float32:
  84  		if v == nil {
  85  			return errors.New(fieldName + " should be setted")
  86  		}
  87  	case *float64:
  88  		if v == nil {
  89  			return errors.New(fieldName + " should be setted")
  90  		}
  91  	}
  92  
  93  	return nil
  94  }
  95  
  96  // ValidateMaxLength validates maximum length using type assertions
  97  func ValidateMaxLength(value interface{}, maxLength int, fieldName string) error {
  98  	length := getValueLength(value)
  99  	if length > maxLength {
 100  		return fmt.Errorf("The length of %s is %d which is more than %d", fieldName, length, maxLength)
 101  	}
 102  	return nil
 103  }
 104  
 105  // ValidateMinLength validates minimum length using type assertions
 106  func ValidateMinLength(value interface{}, minLength int, fieldName string) error {
 107  	length := getValueLength(value)
 108  	if length < minLength {
 109  		return fmt.Errorf("The length of %s is %d which is less than %d", fieldName, length, minLength)
 110  	}
 111  	return nil
 112  }
 113  
 114  // ValidatePattern validates string against regex pattern
 115  func ValidatePattern(value interface{}, pattern string, fieldName string) error {
 116  	strValue := getStringValue(value)
 117  	if strValue == "" {
 118  		return nil // Empty strings are valid unless required
 119  	}
 120  
 121  	r, err := regexp.Compile("^" + pattern + "$")
 122  	if err != nil {
 123  		return err
 124  	}
 125  
 126  	if !r.MatchString(strValue) {
 127  		return errors.New(strValue + " is not matched " + pattern)
 128  	}
 129  	return nil
 130  }
 131  
 132  // ValidateMaximum validates maximum value for numeric types
 133  func ValidateMaximum(value interface{}, maximum float64, fieldName string) error {
 134  	numValue, ok := getNumericValue(value)
 135  	if !ok {
 136  		return nil // Skip validation for non-numeric types
 137  	}
 138  
 139  	if numValue > maximum {
 140  		return fmt.Errorf("The size of %s is %f which is greater than %f", fieldName, numValue, maximum)
 141  	}
 142  	return nil
 143  }
 144  
 145  // ValidateMinimum validates minimum value for numeric types
 146  func ValidateMinimum(value interface{}, minimum float64, fieldName string) error {
 147  	numValue, ok := getNumericValue(value)
 148  	if !ok {
 149  		return nil // Skip validation for non-numeric types
 150  	}
 151  
 152  	if numValue < minimum {
 153  		return fmt.Errorf("The size of %s is %f which is less than %f", fieldName, numValue, minimum)
 154  	}
 155  	return nil
 156  }
 157  
 158  // ValidateArray validates array/slice elements recursively
 159  func ValidateArray(arr interface{}, validator func(interface{}) error) error {
 160  	switch v := arr.(type) {
 161  	case []interface{}:
 162  		for _, item := range v {
 163  			if err := validator(item); err != nil {
 164  				return err
 165  			}
 166  		}
 167  	case []*string:
 168  		for _, item := range v {
 169  			if err := validator(item); err != nil {
 170  				return err
 171  			}
 172  		}
 173  	case []*int:
 174  		for _, item := range v {
 175  			if err := validator(item); err != nil {
 176  				return err
 177  			}
 178  		}
 179  		// Add more specific types as needed
 180  	}
 181  	return nil
 182  }
 183  
 184  // ValidateMap validates map values recursively
 185  func ValidateMap(m interface{}, validator func(interface{}) error) error {
 186  	switch v := m.(type) {
 187  	case map[string]interface{}:
 188  		for _, value := range v {
 189  			if err := validator(value); err != nil {
 190  				return err
 191  			}
 192  		}
 193  	case map[string]*string:
 194  		for _, value := range v {
 195  			if err := validator(value); err != nil {
 196  				return err
 197  			}
 198  		}
 199  		// Add more specific types as needed
 200  	}
 201  	return nil
 202  }
 203  
 204  // Helper functions using pure type assertions (no reflection)
 205  
 206  // getStringValue extracts string value using type assertions
 207  func getStringValue(value interface{}) string {
 208  	switch v := value.(type) {
 209  	case string:
 210  		return v
 211  	case *string:
 212  		if v != nil {
 213  			return *v
 214  		}
 215  		return ""
 216  	default:
 217  		return ""
 218  	}
 219  }
 220  
 221  // getNumericValue extracts numeric value as float64 using type assertions
 222  func getNumericValue(value interface{}) (float64, bool) {
 223  	switch v := value.(type) {
 224  	// Direct numeric types
 225  	case int:
 226  		return float64(v), true
 227  	case int8:
 228  		return float64(v), true
 229  	case int16:
 230  		return float64(v), true
 231  	case int32:
 232  		return float64(v), true
 233  	case int64:
 234  		return float64(v), true
 235  	case uint:
 236  		return float64(v), true
 237  	case uint8:
 238  		return float64(v), true
 239  	case uint16:
 240  		return float64(v), true
 241  	case uint32:
 242  		return float64(v), true
 243  	case uint64:
 244  		return float64(v), true
 245  	case float32:
 246  		return float64(v), true
 247  	case float64:
 248  		return v, true
 249  
 250  	// Pointer types
 251  	case *int:
 252  		if v != nil {
 253  			return float64(*v), true
 254  		}
 255  	case *int8:
 256  		if v != nil {
 257  			return float64(*v), true
 258  		}
 259  	case *int16:
 260  		if v != nil {
 261  			return float64(*v), true
 262  		}
 263  	case *int32:
 264  		if v != nil {
 265  			return float64(*v), true
 266  		}
 267  	case *int64:
 268  		if v != nil {
 269  			return float64(*v), true
 270  		}
 271  	case *uint:
 272  		if v != nil {
 273  			return float64(*v), true
 274  		}
 275  	case *uint8:
 276  		if v != nil {
 277  			return float64(*v), true
 278  		}
 279  	case *uint16:
 280  		if v != nil {
 281  			return float64(*v), true
 282  		}
 283  	case *uint32:
 284  		if v != nil {
 285  			return float64(*v), true
 286  		}
 287  	case *uint64:
 288  		if v != nil {
 289  			return float64(*v), true
 290  		}
 291  	case *float32:
 292  		if v != nil {
 293  			return float64(*v), true
 294  		}
 295  	case *float64:
 296  		if v != nil {
 297  			return *v, true
 298  		}
 299  	default:
 300  		return 0, false
 301  	}
 302  	return 0, false
 303  }
 304  
 305  // getValueLength returns length of string, array, slice, or map using type assertions
 306  func getValueLength(value interface{}) int {
 307  	switch v := value.(type) {
 308  	case string:
 309  		// Use the same method as original implementation for consistency
 310  		return len([]rune(v))
 311  	case *string:
 312  		if v != nil {
 313  			return len([]rune(*v))
 314  		}
 315  		return 0
 316  	case []interface{}:
 317  		return len(v)
 318  	case []string:
 319  		return len(v)
 320  	case []*string:
 321  		return len(v)
 322  	case []int:
 323  		return len(v)
 324  	case []*int:
 325  		return len(v)
 326  	case map[string]interface{}:
 327  		return len(v)
 328  	case map[string]string:
 329  		return len(v)
 330  	case map[string]*string:
 331  		return len(v)
 332  	// Add more specific types as needed
 333  	default:
 334  		return 0
 335  	}
 336  }
 337  
 338  // Deprecated: use new validation methods instead
 339  // Verify whether the parameters meet the requirements
 340  func validate(dataValue reflect.Value) error {
 341  	if strings.HasPrefix(dataValue.Type().String(), "*") { // Determines whether the input is a structure object or a pointer object
 342  		if dataValue.IsNil() {
 343  			return nil
 344  		}
 345  		dataValue = dataValue.Elem()
 346  	}
 347  	dataType := dataValue.Type()
 348  	for i := 0; i < dataType.NumField(); i++ {
 349  		field := dataType.Field(i)
 350  		valueField := dataValue.Field(i)
 351  		for _, value := range validateParams {
 352  			err := validateParam(field, valueField, value)
 353  			if err != nil {
 354  				return err
 355  			}
 356  		}
 357  	}
 358  	return nil
 359  }
 360  
 361  func validateParam(field reflect.StructField, valueField reflect.Value, tagName string) error {
 362  	tag, containsTag := field.Tag.Lookup(tagName) // Take out the checked regular expression
 363  	if containsTag && tagName == "require" {
 364  		err := checkRequire(field, valueField)
 365  		if err != nil {
 366  			return err
 367  		}
 368  	}
 369  	if strings.HasPrefix(field.Type.String(), "[]") { // Verify the parameters of the array type
 370  		err := validateSlice(field, valueField, containsTag, tag, tagName)
 371  		if err != nil {
 372  			return err
 373  		}
 374  	} else if valueField.Kind() == reflect.Ptr { // Determines whether it is a pointer object
 375  		err := validatePtr(field, valueField, containsTag, tag, tagName)
 376  		if err != nil {
 377  			return err
 378  		}
 379  	}
 380  	return nil
 381  }
 382  
 383  func validateSlice(field reflect.StructField, valueField reflect.Value, containsregexpTag bool, tag, tagName string) error {
 384  	if valueField.IsValid() && !valueField.IsNil() { // Determines whether the parameter has a value
 385  		if containsregexpTag {
 386  			if tagName == "maxItems" {
 387  				err := checkMaxItems(field, valueField, tag)
 388  				if err != nil {
 389  					return err
 390  				}
 391  			}
 392  
 393  			if tagName == "minItems" {
 394  				err := checkMinItems(field, valueField, tag)
 395  				if err != nil {
 396  					return err
 397  				}
 398  			}
 399  		}
 400  
 401  		for m := 0; m < valueField.Len(); m++ {
 402  			elementValue := valueField.Index(m)
 403  			if elementValue.Type().Kind() == reflect.Ptr { // Determines whether the child elements of an array are of a basic type
 404  				err := validatePtr(field, elementValue, containsregexpTag, tag, tagName)
 405  				if err != nil {
 406  					return err
 407  				}
 408  			}
 409  		}
 410  	}
 411  	return nil
 412  }
 413  
 414  func validatePtr(field reflect.StructField, elementValue reflect.Value, containsregexpTag bool, tag, tagName string) error {
 415  	if elementValue.IsNil() {
 416  		return nil
 417  	}
 418  	if isFilterType(elementValue.Elem().Type().String(), basicTypes) {
 419  		if containsregexpTag {
 420  			if tagName == "pattern" {
 421  				err := checkPattern(field, elementValue.Elem(), tag)
 422  				if err != nil {
 423  					return err
 424  				}
 425  			}
 426  
 427  			if tagName == "maxLength" {
 428  				err := checkMaxLength(field, elementValue.Elem(), tag)
 429  				if err != nil {
 430  					return err
 431  				}
 432  			}
 433  
 434  			if tagName == "minLength" {
 435  				err := checkMinLength(field, elementValue.Elem(), tag)
 436  				if err != nil {
 437  					return err
 438  				}
 439  			}
 440  
 441  			if tagName == "maximum" {
 442  				err := checkMaximum(field, elementValue.Elem(), tag)
 443  				if err != nil {
 444  					return err
 445  				}
 446  			}
 447  
 448  			if tagName == "minimum" {
 449  				err := checkMinimum(field, elementValue.Elem(), tag)
 450  				if err != nil {
 451  					return err
 452  				}
 453  			}
 454  		}
 455  	} else {
 456  		err := validate(elementValue)
 457  		if err != nil {
 458  			return err
 459  		}
 460  	}
 461  	return nil
 462  }
 463  
 464  func checkRequire(field reflect.StructField, valueField reflect.Value) error {
 465  	name, _ := field.Tag.Lookup("json")
 466  	strs := strings.Split(name, ",")
 467  	name = strs[0]
 468  	if !valueField.IsNil() && valueField.IsValid() {
 469  		return nil
 470  	}
 471  	return errors.New(name + " should be setted")
 472  }
 473  
 474  func checkPattern(field reflect.StructField, valueField reflect.Value, tag string) error {
 475  	if valueField.IsValid() && valueField.String() != "" {
 476  		value := valueField.String()
 477  		r, _ := regexp.Compile("^" + tag + "$")
 478  		if match := r.MatchString(value); !match { // Determines whether the parameter value satisfies the regular expression or not, and throws an error
 479  			return errors.New(value + " is not matched " + tag)
 480  		}
 481  	}
 482  	return nil
 483  }
 484  
 485  func checkMaxItems(field reflect.StructField, valueField reflect.Value, tag string) error {
 486  	if valueField.IsValid() && valueField.String() != "" {
 487  		maxItems, err := strconv.Atoi(tag)
 488  		if err != nil {
 489  			return err
 490  		}
 491  		length := valueField.Len()
 492  		if maxItems < length {
 493  			errMsg := fmt.Sprintf("The length of %s is %d which is more than %d", field.Name, length, maxItems)
 494  			return errors.New(errMsg)
 495  		}
 496  	}
 497  	return nil
 498  }
 499  
 500  func checkMinItems(field reflect.StructField, valueField reflect.Value, tag string) error {
 501  	if valueField.IsValid() {
 502  		minItems, err := strconv.Atoi(tag)
 503  		if err != nil {
 504  			return err
 505  		}
 506  		length := valueField.Len()
 507  		if minItems > length {
 508  			errMsg := fmt.Sprintf("The length of %s is %d which is less than %d", field.Name, length, minItems)
 509  			return errors.New(errMsg)
 510  		}
 511  	}
 512  	return nil
 513  }
 514  
 515  func checkMaxLength(field reflect.StructField, valueField reflect.Value, tag string) error {
 516  	if valueField.IsValid() && valueField.String() != "" {
 517  		maxLength, err := strconv.Atoi(tag)
 518  		if err != nil {
 519  			return err
 520  		}
 521  		length := valueField.Len()
 522  		if valueField.Kind().String() == "string" {
 523  			length = strings.Count(valueField.String(), "") - 1
 524  		}
 525  		if maxLength < length {
 526  			errMsg := fmt.Sprintf("The length of %s is %d which is more than %d", field.Name, length, maxLength)
 527  			return errors.New(errMsg)
 528  		}
 529  	}
 530  	return nil
 531  }
 532  
 533  func checkMinLength(field reflect.StructField, valueField reflect.Value, tag string) error {
 534  	if valueField.IsValid() {
 535  		minLength, err := strconv.Atoi(tag)
 536  		if err != nil {
 537  			return err
 538  		}
 539  		length := valueField.Len()
 540  		if valueField.Kind().String() == "string" {
 541  			length = strings.Count(valueField.String(), "") - 1
 542  		}
 543  		if minLength > length {
 544  			errMsg := fmt.Sprintf("The length of %s is %d which is less than %d", field.Name, length, minLength)
 545  			return errors.New(errMsg)
 546  		}
 547  	}
 548  	return nil
 549  }
 550  
 551  func checkMaximum(field reflect.StructField, valueField reflect.Value, tag string) error {
 552  	if valueField.IsValid() && valueField.String() != "" {
 553  		maximum, err := strconv.ParseFloat(tag, 64)
 554  		if err != nil {
 555  			return err
 556  		}
 557  		byt, _ := json.Marshal(valueField.Interface())
 558  		num, err := strconv.ParseFloat(string(byt), 64)
 559  		if err != nil {
 560  			return err
 561  		}
 562  		if maximum < num {
 563  			errMsg := fmt.Sprintf("The size of %s is %f which is greater than %f", field.Name, num, maximum)
 564  			return errors.New(errMsg)
 565  		}
 566  	}
 567  	return nil
 568  }
 569  
 570  func checkMinimum(field reflect.StructField, valueField reflect.Value, tag string) error {
 571  	if valueField.IsValid() && valueField.String() != "" {
 572  		minimum, err := strconv.ParseFloat(tag, 64)
 573  		if err != nil {
 574  			return err
 575  		}
 576  
 577  		byt, _ := json.Marshal(valueField.Interface())
 578  		num, err := strconv.ParseFloat(string(byt), 64)
 579  		if err != nil {
 580  			return err
 581  		}
 582  		if minimum > num {
 583  			errMsg := fmt.Sprintf("The size of %s is %f which is less than %f", field.Name, num, minimum)
 584  			return errors.New(errMsg)
 585  		}
 586  	}
 587  	return nil
 588  }
 589