1// Copyright 2015 go-swagger maintainers 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 15package generator 16 17import ( 18 "encoding/json" 19 "errors" 20 "fmt" 21 "os" 22 "path/filepath" 23 "sort" 24 25 "github.com/go-openapi/analysis" 26 "github.com/go-openapi/runtime" 27 "github.com/go-openapi/loads" 28 "github.com/go-openapi/swag" 29) 30 31// GenerateClient generates a client library for a swagger spec document. 32func GenerateClient(name string, modelNames, operationIDs []string, opts *GenOpts) error { 33 if opts == nil { 34 return errors.New("gen opts are required") 35 } 36 if err := opts.EnsureDefaults(true); err != nil { 37 return err 38 } 39 40 if opts.TemplateDir != "" { 41 if err := templates.LoadDir(opts.TemplateDir); err != nil { 42 return err 43 } 44 } 45 46 // Load the spec 47 var err error 48 var specDoc *loads.Document 49 opts.Spec, specDoc, err = loadSpec(opts.Spec) 50 if err != nil { 51 return err 52 } 53 54 // Validate if needed 55 if opts.ValidateSpec { 56 if err = validateSpec(opts.Spec, specDoc); err != nil { 57 return err 58 } 59 } 60 61 analyzed := analysis.New(specDoc.Spec()) 62 63 models, err := gatherModels(specDoc, modelNames) 64 if err != nil { 65 return err 66 } 67 operations := gatherOperations(analyzed, operationIDs) 68 69 defaultScheme := opts.DefaultScheme 70 if defaultScheme == "" { 71 defaultScheme = sHTTP 72 } 73 74 defaultConsumes := opts.DefaultConsumes 75 if defaultConsumes == "" { 76 defaultConsumes = runtime.JSONMime 77 } 78 79 defaultProduces := opts.DefaultProduces 80 if defaultProduces == "" { 81 defaultProduces = runtime.JSONMime 82 } 83 84 generator := appGenerator{ 85 Name: appNameOrDefault(specDoc, name, "rest"), 86 SpecDoc: specDoc, 87 Analyzed: analyzed, 88 Models: models, 89 Operations: operations, 90 Target: opts.Target, 91 DumpData: opts.DumpData, 92 Package: opts.LanguageOpts.MangleName(swag.ToFileName(opts.ClientPackage), "client"), 93 APIPackage: opts.LanguageOpts.MangleName(swag.ToFileName(opts.APIPackage), "api"), 94 ModelsPackage: opts.LanguageOpts.MangleName(swag.ToFileName(opts.ModelPackage), "definitions"), 95 ServerPackage: opts.LanguageOpts.MangleName(swag.ToFileName(opts.ServerPackage), "server"), 96 ClientPackage: opts.LanguageOpts.MangleName(swag.ToFileName(opts.ClientPackage), "client"), 97 Principal: opts.Principal, 98 DefaultScheme: defaultScheme, 99 DefaultProduces: defaultProduces, 100 DefaultConsumes: defaultConsumes, 101 GenOpts: opts, 102 } 103 generator.Receiver = "o" 104 105 return (&clientGenerator{generator}).Generate() 106} 107 108type clientGenerator struct { 109 appGenerator 110} 111 112func (c *clientGenerator) Generate() error { 113 app, err := c.makeCodegenApp() 114 if app.Name == "" { 115 app.Name = "APIClient" 116 } 117 app.DefaultImports = []string{filepath.ToSlash(filepath.Join(baseImport(c.Target), c.ModelsPackage))} 118 if err != nil { 119 return err 120 } 121 122 if c.DumpData { 123 bb, _ := json.MarshalIndent(swag.ToDynamicJSON(app), "", " ") 124 fmt.Fprintln(os.Stdout, string(bb)) 125 return nil 126 } 127 128 // errChan := make(chan error, 100) 129 // wg := nsync.NewControlWaitGroup(20) 130 131 if c.GenOpts.IncludeModel { 132 for _, mod := range app.Models { 133 // if len(errChan) > 0 { 134 // wg.Wait() 135 // return <-errChan 136 // } 137 modCopy := mod 138 // wg.Do(func() { 139 modCopy.IncludeValidator = true 140 if err := c.GenOpts.renderDefinition(&modCopy); err != nil { 141 return err 142 } 143 // }) 144 } 145 } 146 147 // wg.Wait() 148 if c.GenOpts.IncludeHandler { 149 sort.Sort(app.OperationGroups) 150 for i := range app.OperationGroups { 151 opGroup := app.OperationGroups[i] 152 opGroup.DefaultImports = []string{filepath.ToSlash(filepath.Join(baseImport(c.Target), c.ModelsPackage))} 153 opGroup.RootPackage = c.ClientPackage 154 app.OperationGroups[i] = opGroup 155 sort.Sort(opGroup.Operations) 156 for _, op := range opGroup.Operations { 157 // if len(errChan) > 0 { 158 // wg.Wait() 159 // return <-errChan 160 // } 161 opCopy := op 162 if opCopy.Package == "" { 163 opCopy.Package = c.Package 164 } 165 // wg.Do(func() { 166 if err := c.GenOpts.renderOperation(&opCopy); err != nil { 167 return err 168 } 169 // }) 170 } 171 app.DefaultImports = append(app.DefaultImports, filepath.ToSlash(filepath.Join(baseImport(c.Target), c.ClientPackage, opGroup.Name))) 172 173 // wg.Do(func() { 174 if err := c.GenOpts.renderOperationGroup(&opGroup); err != nil { 175 // errChan <- err 176 return err 177 } 178 // }) 179 } 180 // wg.Wait() 181 } 182 183 if c.GenOpts.IncludeSupport { 184 // wg.Do(func() { 185 if err := c.GenOpts.renderApplication(&app); err != nil { 186 return err 187 } 188 // }) 189 } 190 191 // wg.Wait() 192 193 // if len(errChan) > 0 { 194 // return <-errChan 195 // } 196 197 return nil 198} 199