github.com/sacloud/libsacloud/v2@v2.32.3/internal/dsl/field_desc.go (about) 1 // Copyright 2016-2022 The Libsacloud Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package dsl 16 17 import ( 18 "fmt" 19 "strings" 20 21 "github.com/sacloud/libsacloud/v2/internal/dsl/meta" 22 ) 23 24 // FieldDesc フィールド記述 25 type FieldDesc struct { 26 Name string 27 Tags *FieldTags 28 Type meta.Type 29 Description string // TODO 現在は未使用 30 Methods []*MethodDesc 31 DefaultValue string // デフォルト値、コード生成時にソースコードに直接転記される 32 } 33 34 // CloneFieldWithTags 指定のフィールドをクローンし指定のタグを設定して返す 35 func CloneFieldWithTags(f *FieldDesc, tags ...*FieldTags) *FieldDesc { 36 var tag *FieldTags 37 for _, t := range tags { 38 if t != nil { 39 tag = t 40 break 41 } 42 } 43 if tag == nil { 44 tag = &FieldTags{} 45 } 46 return &FieldDesc{ 47 Name: f.Name, 48 Tags: tag, 49 Type: f.Type, 50 Description: f.Description, 51 Methods: f.Methods, 52 DefaultValue: f.DefaultValue, 53 } 54 } 55 56 // CloneUpdateFieldWithTags 指定のフィールドのポインタ型をクローンし指定のタグを設定して返す 57 func CloneUpdateFieldWithTags(f *FieldDesc, tags ...*FieldTags) *FieldDesc { 58 return CloneFieldWithTags(f.ToPtrType(), tags...) 59 } 60 61 // ToPtrType ポインタを受け取る型に変換したFieldDescを返す 62 func (f *FieldDesc) ToPtrType() *FieldDesc { 63 return &FieldDesc{ 64 Name: f.Name, 65 Tags: f.Tags, 66 Type: f.Type.ToPtrType(), 67 Description: f.Description, 68 Methods: f.Methods, 69 DefaultValue: f.DefaultValue, 70 } 71 } 72 73 // HasTag タグの定義がなされているか 74 func (f *FieldDesc) HasTag() bool { 75 return f.Tags != nil && !f.Tags.Empty() 76 } 77 78 // SetTags タグの設定 79 func (f *FieldDesc) SetTags(t *FieldTags) { 80 f.Tags = t 81 } 82 83 // TypeName フィールドの型を返す、コード生成で利用される 84 func (f *FieldDesc) TypeName() string { 85 return f.Type.GoTypeSourceCode() 86 } 87 88 // TagString タグのソースコード上での表現を返す 89 func (f *FieldDesc) TagString() string { 90 if !f.HasTag() { 91 return "" 92 } 93 return f.Tags.String() 94 } 95 96 // IsRequired 必須項目であるかを判定 97 func (f *FieldDesc) IsRequired() bool { 98 if f.Tags == nil { 99 return false 100 } 101 return strings.Contains(f.Tags.Validate, "required") 102 } 103 104 // FieldTags フィールドに付与するタグ 105 type FieldTags struct { 106 // JSON jsonタグ 107 JSON string 108 // YAML yamlタグ 109 YAML string 110 // Structs structsタグ 111 Structs string 112 // MapConv mapconvタグ 113 MapConv string 114 // Validate validateタグ 115 Validate string 116 // Request requestタグ(service向けmapconvタグ) 117 Request string 118 } 119 120 func (f *FieldTags) Empty() bool { 121 return f.JSON == "" && f.YAML == "" && f.Structs == "" && f.MapConv == "" && f.Validate == "" && f.Request == "" 122 } 123 124 // String FieldTagsの文字列表現 125 func (f *FieldTags) String() string { 126 var tags []string 127 if f.JSON != "" { 128 tags = append(tags, fmt.Sprintf(`json:"%s"`, f.JSON)) 129 } 130 if f.YAML != "" { 131 tags = append(tags, fmt.Sprintf(`yaml:"%s"`, f.YAML)) 132 } 133 if f.Structs != "" { 134 tags = append(tags, fmt.Sprintf(`structs:"%s"`, f.Structs)) 135 } 136 if f.MapConv != "" { 137 tags = append(tags, fmt.Sprintf(`mapconv:"%s"`, f.MapConv)) 138 } 139 if f.Request != "" { 140 tags = append(tags, fmt.Sprintf(`request:"%s"`, f.Request)) 141 } 142 if f.Validate != "" { 143 tags = append(tags, fmt.Sprintf(`validate:"%s"`, f.Validate)) 144 } 145 return strings.Join(tags, " ") 146 } 147 148 func ValidateRequiredTag() *FieldTags { 149 return ValidateTag("required") 150 } 151 152 func ValidateTag(t string, args ...interface{}) *FieldTags { 153 tag := t 154 if len(args) > 0 { 155 tag = fmt.Sprintf(t, args...) 156 } 157 return &FieldTags{Validate: tag} 158 } 159 160 func RequestOmitEmptyTag() *FieldTags { 161 return RequestTag(",omitempty") 162 } 163 164 func RequestTag(t string, args ...interface{}) *FieldTags { 165 tag := t 166 if len(args) > 0 { 167 tag = fmt.Sprintf(t, args...) 168 } 169 return &FieldTags{Request: tag} 170 }