github.com/sacloud/iaas-api-go@v1.12.0/internal/dsl/envelope.go (about)

     1  // Copyright 2022-2023 The sacloud/iaas-api-go 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  
    20  	"github.com/sacloud/iaas-api-go/internal/dsl/meta"
    21  )
    22  
    23  // EnvelopeType Modelを用いてAPIとやりとりする際のリクエスト/レスポンスのエンベロープ
    24  type EnvelopeType struct {
    25  	Form     PayloadForm // ペイロードの形体(単数/複数)
    26  	Payloads []*EnvelopePayloadDesc
    27  }
    28  
    29  // IsSingular 単数系か判定
    30  func (f *EnvelopeType) IsSingular() bool {
    31  	return f.Form.IsSingular()
    32  }
    33  
    34  // IsPlural 複数形か判定
    35  func (f *EnvelopeType) IsPlural() bool {
    36  	return f.Form.IsPlural()
    37  }
    38  
    39  // EnvelopePayloadDesc エンベロープに含まれるペイロードの情報
    40  type EnvelopePayloadDesc struct {
    41  	Name string    // ペイロードのフィールド名
    42  	Type meta.Type // ペイロードの型情報
    43  	Tags *FieldTags
    44  }
    45  
    46  // TypeName ペイロードの型定義
    47  func (d *EnvelopePayloadDesc) TypeName() string {
    48  	return d.Type.GoTypeSourceCode()
    49  }
    50  
    51  // TagString タグの文字列表現
    52  func (d *EnvelopePayloadDesc) TagString() string {
    53  	if d.Tags == nil {
    54  		d.Tags = &FieldTags{
    55  			JSON: ",omitempty",
    56  		}
    57  	}
    58  	tags := d.Tags.String()
    59  	if tags == "" {
    60  		return tags
    61  	}
    62  	return fmt.Sprintf("`%s`", d.Tags.String())
    63  }
    64  
    65  // PayloadForm ペイロードの形体
    66  type PayloadForm int
    67  
    68  // PayloadForms ペイロードの形体
    69  var PayloadForms = struct {
    70  	Singular PayloadForm
    71  	Plural   PayloadForm
    72  }{
    73  	Singular: PayloadForm(0),
    74  	Plural:   PayloadForm(1),
    75  }
    76  
    77  // IsSingular 単数系か判定
    78  func (f PayloadForm) IsSingular() bool {
    79  	return int(f) == int(PayloadForms.Singular)
    80  }
    81  
    82  // IsPlural 複数形か判定
    83  func (f PayloadForm) IsPlural() bool {
    84  	return int(f) == int(PayloadForms.Plural)
    85  }
    86  
    87  // RequestEnvelope リクエストのエンベロープを作成する
    88  func RequestEnvelope(descs ...*EnvelopePayloadDesc) *EnvelopeType {
    89  	ret := &EnvelopeType{
    90  		Form: PayloadForms.Singular,
    91  	}
    92  
    93  	ret.Payloads = append(ret.Payloads, descs...)
    94  
    95  	return ret
    96  }
    97  
    98  // RequestEnvelopeFromModel モデル定義からリクエストのエンベロープを作成する
    99  func RequestEnvelopeFromModel(model *Model) *EnvelopeType {
   100  	var descs []*EnvelopePayloadDesc
   101  	for _, field := range model.Fields {
   102  		t := field.Type
   103  		if m, ok := t.(*Model); ok {
   104  			if m.HasNakedType() {
   105  				t = m.NakedType
   106  			}
   107  		}
   108  		descs = append(descs, &EnvelopePayloadDesc{
   109  			Name: field.Name,
   110  			Type: t,
   111  			Tags: field.Tags,
   112  		})
   113  	}
   114  	ret := &EnvelopeType{
   115  		Form: PayloadForms.Singular,
   116  	}
   117  
   118  	ret.Payloads = append(ret.Payloads, descs...)
   119  
   120  	return ret
   121  }
   122  
   123  // ResponseEnvelope エンベロープから抽出するレスポンス定義の追加
   124  func ResponseEnvelope(sourceFields ...*EnvelopePayloadDesc) *EnvelopeType {
   125  	return responseEnvelope(PayloadForms.Singular, sourceFields...)
   126  }
   127  
   128  // ResponseEnvelopePlural エンベロープから抽出するレスポンス定義の追加(複数形)
   129  func ResponseEnvelopePlural(sourceFields ...*EnvelopePayloadDesc) *EnvelopeType {
   130  	return responseEnvelope(PayloadForms.Plural, sourceFields...)
   131  }
   132  
   133  func responseEnvelope(form PayloadForm, sourceFields ...*EnvelopePayloadDesc) *EnvelopeType {
   134  	et := &EnvelopeType{
   135  		Form: form,
   136  	}
   137  	for _, sf := range sourceFields {
   138  		if sf.Tags == nil {
   139  			sf.Tags = &FieldTags{
   140  				JSON: ",omitempty",
   141  			}
   142  		}
   143  		et.Payloads = append(et.Payloads, sf)
   144  	}
   145  	return et
   146  }