github.com/johnnyeven/libtools@v0.0.0-20191126065708-61829c1adf46/courier/swagger/gen/openapi_common.go (about)

     1  package gen
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"regexp"
     7  	"strconv"
     8  	"strings"
     9  
    10  	"github.com/morlay/oas"
    11  )
    12  
    13  var (
    14  	rxValidate = regexp.MustCompile(`^@([^\[\(\{]+)([\[\(\{])([^\}^\]^\)]+)([\}\]\)])$`)
    15  )
    16  
    17  func BindValidateFromValidateTagString(schema *oas.Schema, validate string) {
    18  	commonValidations := getCommonValidations(validate)
    19  	bindSchemaWithValidations(schema, commonValidations)
    20  	schema.AddExtension(XTagValidate, validate)
    21  }
    22  
    23  func getCommonValidations(validateTag string) (commonValidations oas.SchemaValidation) {
    24  	var matched = rxValidate.FindAllStringSubmatch(validateTag, -1)
    25  
    26  	// "@int[1,2]", "int", "[", "1,2", "]"
    27  	if len(matched) > 0 && len(matched[0]) == 5 {
    28  		tpe := matched[0][1]
    29  		startBracket := matched[0][2]
    30  		endBracket := matched[0][4]
    31  		values := strings.Split(matched[0][3], ",")
    32  
    33  		if startBracket != "{" && endBracket != "}" {
    34  			switch tpe {
    35  			case "byte", "int", "int8", "int16", "int32", "int64", "rune", "uint", "uint8", "uint16", "uint32", "uint64", "uintptr", "float32", "float64":
    36  				if len(values) > 0 {
    37  					if val, err := strconv.ParseFloat(values[0], 64); err == nil {
    38  						commonValidations.Minimum = &val
    39  						commonValidations.ExclusiveMinimum = (startBracket == "(")
    40  					}
    41  				}
    42  				if len(values) > 1 {
    43  					if val, err := strconv.ParseFloat(values[1], 64); err == nil {
    44  						commonValidations.Maximum = &val
    45  						commonValidations.ExclusiveMaximum = (endBracket == ")")
    46  					}
    47  				}
    48  			case "string":
    49  				if len(values) > 0 {
    50  					if val, err := strconv.ParseInt(values[0], 10, 64); err == nil {
    51  						commonValidations.MinLength = &val
    52  					}
    53  				}
    54  				if len(values) > 1 {
    55  					if val, err := strconv.ParseInt(values[1], 10, 64); err == nil {
    56  						commonValidations.MaxLength = &val
    57  					}
    58  				}
    59  			}
    60  		} else {
    61  			enums := make([]interface{}, 0)
    62  
    63  			for _, value := range values {
    64  				if tpe != "string" {
    65  					if val, err := strconv.ParseInt(value, 10, 64); err == nil {
    66  						enums = append(enums, val)
    67  					}
    68  				} else {
    69  					enums = append(enums, value)
    70  				}
    71  			}
    72  
    73  			commonValidations.Enum = enums
    74  		}
    75  	}
    76  
    77  	return
    78  }
    79  
    80  func bindSchemaWithValidations(schema *oas.Schema, schemaValidation oas.SchemaValidation) {
    81  	schema.SchemaValidation = schemaValidation
    82  
    83  	// for partial enum
    84  	if len(schema.Enum) != 0 && len(schemaValidation.Enum) != 0 {
    85  		var enums []interface{}
    86  
    87  		for _, enumValueOrIndex := range schemaValidation.Enum {
    88  			switch reflect.TypeOf(enumValueOrIndex).Name() {
    89  			case "string":
    90  				if enumContainsValue(schema.Enum, enumValueOrIndex) {
    91  					enums = append(enums, enumValueOrIndex)
    92  				} else if enumValueOrIndex != "" {
    93  					panic(fmt.Errorf("%s is not value of %s", enumValueOrIndex, schema.Enum))
    94  				}
    95  			default:
    96  				if idx, ok := enumValueOrIndex.(int); ok {
    97  					if schema.Enum[idx] != nil {
    98  						enums = append(enums, schema.Enum[idx])
    99  					} else if idx != 0 {
   100  						panic(fmt.Errorf("%s is out-range of  %s", enumValueOrIndex, schema.Enum))
   101  					}
   102  				}
   103  
   104  			}
   105  		}
   106  
   107  		schema.Enum = enums
   108  	}
   109  }
   110  
   111  func enumContainsValue(enum []interface{}, value interface{}) bool {
   112  	var isContains = false
   113  
   114  	for _, enumValue := range enum {
   115  		if enumValue == value {
   116  			isContains = true
   117  		}
   118  	}
   119  
   120  	return isContains
   121  }