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 }