-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathoutput.go
203 lines (158 loc) · 4.45 KB
/
output.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
package presilo
import (
"bufio"
"errors"
"fmt"
"io/ioutil"
"os"
"sync"
)
func WriteGeneratedCode(context *SchemaParseContext, module string, targetPath string, language string, tabstyle string, unsafeModule bool, splitFiles bool) error {
var schemas []*ObjectSchema
var wg sync.WaitGroup
var err error
// get all object schemas
for _, schema := range context.SchemaDefinitions {
if(schema.GetSchemaType() == SCHEMATYPE_OBJECT) {
schemas = append(schemas, schema.(*ObjectSchema))
}
}
err = generateCode(schemas, module, targetPath, language, tabstyle, unsafeModule, splitFiles, &wg)
wg.Wait()
return err
}
func generateCode(schemas []*ObjectSchema, module string, targetPath string, language string, tabstyle string, unsafeModule bool, splitFiles bool, wg *sync.WaitGroup) error {
var schemaGraph *SchemaGraph
var objectSchema *ObjectSchema
var generator func(*ObjectSchema, string, string) string
var moduleValidator func(string) bool
var writtenChannel chan string
var fileNameChannel chan string
var errorChannel chan error
var written string
var schemaPath string
schemaGraph = NewSchemaGraph(schemas)
// figure out which code generator to use
switch language {
case "go":
generator = GenerateGo
moduleValidator = ValidateGoModule
case "js":
generator = GenerateJS
moduleValidator = ValidateJSModule
case "java":
generator = GenerateJava
moduleValidator = ValidateJavaModule
case "cs":
generator = GenerateCSharp
moduleValidator = ValidateCSharpModule
case "rb":
generator = GenerateRuby
moduleValidator = ValidateRubyModule
case "py":
generator = GeneratePython
moduleValidator = ValidatePythonModule
case "mysql":
generator = GenerateMySQL
moduleValidator = ValidateMySQLModule
default:
return errors.New("No valid language specified")
}
if !unsafeModule && !moduleValidator(module) {
errorMsg := fmt.Sprintf("Package name '%s' is not valid for language '%s'. Use '-usafemodule' to ignore.", module, language)
return errors.New(errorMsg)
}
writtenChannel = make(chan string)
errorChannel = make(chan error)
defer close(writtenChannel)
defer close(errorChannel)
// one for the file writer, one for error listener.
wg.Add(2)
// Start writer goroutines based on our split strategy
if splitFiles {
fileNameChannel = make(chan string)
defer close(fileNameChannel)
go writeSplitFiles(writtenChannel, fileNameChannel, errorChannel, wg)
} else {
schemaPath = fmt.Sprintf("%s%s%s.%s", targetPath, string(os.PathSeparator), module, language)
go writeSingleFile(schemaPath, writtenChannel, errorChannel, wg)
}
// write errors to stderr, no matter where they come from.
go writeErrors(errorChannel, wg)
// generate schemas, pass to writers.
schemas, _ = schemaGraph.GetOrderedSchemas()
for _, objectSchema = range schemas {
if splitFiles {
schemaPath = fmt.Sprintf("%s%s%s.%s", targetPath, string(os.PathSeparator), objectSchema.GetTitle(), language)
fileNameChannel <- schemaPath
}
written = generator(objectSchema, module, tabstyle)
writtenChannel <- written
}
return nil
}
/*
Writes incoming strings to incoming file names.
*/
func writeSplitFiles(source chan string, fileNames chan string, resultError chan error, wg *sync.WaitGroup) {
var schemaPath, contents string
var err error
var ok bool
defer wg.Done()
for {
schemaPath, ok = <-fileNames
if !ok {
return
}
contents = <-source
err = ioutil.WriteFile(schemaPath, []byte(contents), os.ModePerm)
if err != nil {
resultError <- err
}
}
}
/*
Writes all incoming contents from [source] to a file at the given [schemaPath],
returning all found errors to [resultError], and returning only once a value is
received on [exit], or if the file was unable to be opened.
*/
func writeSingleFile(schemaPath string, source chan string, resultError chan error, wg *sync.WaitGroup) {
var contents string
var outFile *os.File
var writer *bufio.Writer
var err error
var ok bool
defer wg.Done()
outFile, err = os.Create(schemaPath)
if err != nil {
resultError <- err
return
}
writer = bufio.NewWriter(outFile)
for {
contents, ok = <-source
if !ok {
break
}
_, err = writer.Write([]byte(contents))
if err != nil {
resultError <- err
}
}
writer.Flush()
}
/*
Writes all incoming errors to stderr.
*/
func writeErrors(intake chan error, wg *sync.WaitGroup) {
var err error
var ok bool
defer wg.Done()
for {
err, ok = <-intake
if !ok {
return
}
fmt.Fprintf(os.Stderr, err.Error())
}
}