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  }