dubbo.apache.org/dubbo-go/v3@v3.1.1/metadata/definition/definition.go (about)

     1  /*
     2   * Licensed to the Apache Software Foundation (ASF) under one or more
     3   * contributor license agreements.  See the NOTICE file distributed with
     4   * this work for additional information regarding copyright ownership.
     5   * The ASF licenses this file to You under the Apache License, Version 2.0
     6   * (the "License"); you may not use this file except in compliance with
     7   * the License.  You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  
    18  package definition
    19  
    20  import (
    21  	"bytes"
    22  	"encoding/json"
    23  	"fmt"
    24  	"sort"
    25  	"strings"
    26  )
    27  
    28  import (
    29  	"dubbo.apache.org/dubbo-go/v3/common"
    30  	"dubbo.apache.org/dubbo-go/v3/common/constant"
    31  )
    32  
    33  // ServiceDefiner is a interface of service's definition
    34  type ServiceDefiner interface {
    35  	ToBytes() ([]byte, error)
    36  }
    37  
    38  // ServiceDefinition is the describer of service definition
    39  type ServiceDefinition struct {
    40  	CanonicalName string             `json:"canonicalName"`
    41  	CodeSource    string             `json:"codeSource"`
    42  	Methods       []MethodDefinition `json:"methods"`
    43  	Types         []TypeDefinition   `json:"types"`
    44  }
    45  
    46  // ToBytes convert ServiceDefinition to json string
    47  func (def *ServiceDefinition) ToBytes() ([]byte, error) {
    48  	return json.Marshal(def)
    49  }
    50  
    51  // String will iterate all methods and parameters and convert them to json string
    52  func (def *ServiceDefinition) String() string {
    53  	var methodStr strings.Builder
    54  	for _, m := range def.Methods {
    55  		var paramType strings.Builder
    56  		for _, p := range m.ParameterTypes {
    57  			paramType.WriteString(fmt.Sprintf("{type:%v}", p))
    58  		}
    59  		var param strings.Builder
    60  		for _, d := range m.Parameters {
    61  			param.WriteString(fmt.Sprintf("{id:%v,type:%v,builderName:%v}", d.ID, d.Type, d.TypeBuilderName))
    62  		}
    63  		methodStr.WriteString(fmt.Sprintf("{name:%v,parameterTypes:[%v],returnType:%v,params:[%v] }", m.Name, paramType.String(), m.ReturnType, param.String()))
    64  	}
    65  	var types strings.Builder
    66  	for _, d := range def.Types {
    67  		types.WriteString(fmt.Sprintf("{id:%v,type:%v,builderName:%v}", d.ID, d.Type, d.TypeBuilderName))
    68  	}
    69  	return fmt.Sprintf("{canonicalName:%v, codeSource:%v, methods:[%v], types:[%v]}", def.CanonicalName, def.CodeSource, methodStr.String(), types.String())
    70  }
    71  
    72  // FullServiceDefinition is the describer of service definition with parameters
    73  type FullServiceDefinition struct {
    74  	Parameters map[string]string `json:"parameters"`
    75  	ServiceDefinition
    76  }
    77  
    78  // MethodDefinition is the describer of method definition
    79  type MethodDefinition struct {
    80  	Name           string           `json:"name"`
    81  	ParameterTypes []string         `json:"parameterTypes"`
    82  	ReturnType     string           `json:"returnType"`
    83  	Parameters     []TypeDefinition `json:"parameters"`
    84  }
    85  
    86  // TypeDefinition is the describer of type definition
    87  type TypeDefinition struct {
    88  	ID              string                    `json:"id"`
    89  	Type            string                    `json:"type"`
    90  	Items           []TypeDefinition          `json:"items"`
    91  	Enums           []string                  `json:"enums"`
    92  	Properties      map[string]TypeDefinition `json:"properties"`
    93  	TypeBuilderName string                    `json:"typeBuilderName"`
    94  }
    95  
    96  // BuildServiceDefinition can build service definition which will be used to describe a service
    97  func BuildServiceDefinition(service common.Service, url *common.URL) *ServiceDefinition {
    98  	sd := &ServiceDefinition{}
    99  	sd.CanonicalName = url.Service()
   100  
   101  	for k, m := range service.Method() {
   102  		var paramTypes []string
   103  		if len(m.ArgsType()) > 0 {
   104  			for _, t := range m.ArgsType() {
   105  				paramTypes = append(paramTypes, t.Kind().String())
   106  			}
   107  		}
   108  
   109  		var returnType string
   110  		if m.ReplyType() != nil {
   111  			returnType = m.ReplyType().Kind().String()
   112  		}
   113  
   114  		methodD := MethodDefinition{
   115  			Name:           k,
   116  			ParameterTypes: paramTypes,
   117  			ReturnType:     returnType,
   118  		}
   119  		sd.Methods = append(sd.Methods, methodD)
   120  	}
   121  
   122  	return sd
   123  }
   124  
   125  // BuildFullDefinition can build service definition with full url parameters
   126  func BuildFullDefinition(service common.Service, url *common.URL) *FullServiceDefinition {
   127  	fsd := &FullServiceDefinition{}
   128  	sd := BuildServiceDefinition(service, url)
   129  	fsd.ServiceDefinition = *sd
   130  	fsd.Parameters = make(map[string]string)
   131  	for k, v := range url.GetParams() {
   132  		fsd.Parameters[k] = strings.Join(v, ",")
   133  	}
   134  	return fsd
   135  }
   136  
   137  // ToBytes convert ServiceDefinition to json string
   138  func (def *FullServiceDefinition) ToBytes() ([]byte, error) {
   139  	return json.Marshal(def)
   140  }
   141  
   142  // String will iterate all methods and parameters and convert them to json string
   143  func (def *FullServiceDefinition) String() string {
   144  	var methodStr strings.Builder
   145  	for _, m := range def.Methods {
   146  		var paramType strings.Builder
   147  		for _, p := range m.ParameterTypes {
   148  			paramType.WriteString(fmt.Sprintf("{type:%v}", p))
   149  		}
   150  		var param strings.Builder
   151  		for _, d := range m.Parameters {
   152  			param.WriteString(fmt.Sprintf("{id:%v,type:%v,builderName:%v}", d.ID, d.Type, d.TypeBuilderName))
   153  		}
   154  		methodStr.WriteString(fmt.Sprintf("{name:%v,parameterTypes:[%v],returnType:%v,params:[%v] }", m.Name, paramType.String(), m.ReturnType, param.String()))
   155  	}
   156  	var types strings.Builder
   157  	for _, d := range def.Types {
   158  		types.WriteString(fmt.Sprintf("{id:%v,type:%v,builderName:%v}", d.ID, d.Type, d.TypeBuilderName))
   159  	}
   160  
   161  	sortSlice := make([]string, 0)
   162  	var parameters strings.Builder
   163  	for k := range def.Parameters {
   164  		sortSlice = append(sortSlice, k)
   165  	}
   166  	sort.Slice(sortSlice, func(i, j int) bool { return sortSlice[i] < sortSlice[j] })
   167  	for _, k := range sortSlice {
   168  		parameters.WriteString(fmt.Sprintf("%v:%v,", k, def.Parameters[k]))
   169  	}
   170  
   171  	return fmt.Sprintf("{parameters:{%v}, canonicalName:%v, codeSource:%v, methods:[%v], types:[%v]}",
   172  		strings.TrimRight(parameters.String(), ","), def.CanonicalName, def.CodeSource, methodStr.String(), types.String())
   173  }
   174  
   175  // ServiceDescriperBuild builds the service key, format is `group/serviceName:version` which be same as URL's service key
   176  func ServiceDescriperBuild(serviceName string, group string, version string) string {
   177  	buf := &bytes.Buffer{}
   178  	if group != "" {
   179  		buf.WriteString(group)
   180  		buf.WriteString(constant.PathSeparator)
   181  	}
   182  	buf.WriteString(serviceName)
   183  	if version != "" && version != "0.0.0" {
   184  		buf.WriteString(constant.KeySeparator)
   185  		buf.WriteString(version)
   186  	}
   187  	return buf.String()
   188  }