233 lines
6.1 KiB
Go
233 lines
6.1 KiB
Go
/*
|
|
* Copyright 2022 CloudWeGo Authors
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package generator
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"path/filepath"
|
|
"reflect"
|
|
"strings"
|
|
|
|
"gopkg.in/yaml.v2"
|
|
"std.gaore.com/Gaore-Go/gr_hz/meta"
|
|
"std.gaore.com/Gaore-Go/gr_hz/util"
|
|
)
|
|
|
|
// Layout contains the basic information of idl
|
|
type Layout struct {
|
|
OutDir string
|
|
GoModule string
|
|
ServiceName string
|
|
UseApacheThrift bool
|
|
HasIdl bool
|
|
NeedGoMod bool
|
|
ModelDir string
|
|
HandlerDir string
|
|
RouterDir string
|
|
}
|
|
|
|
// LayoutGenerator contains the information generated by generating the layout template
|
|
type LayoutGenerator struct {
|
|
ConfigPath string
|
|
TemplateGenerator
|
|
}
|
|
|
|
var (
|
|
layoutConfig = defaultLayoutConfig
|
|
packageConfig = defaultPkgConfig
|
|
)
|
|
|
|
func SetDefaultTemplateConfig() {
|
|
layoutConfig = defaultLayoutConfig
|
|
packageConfig = defaultPkgConfig
|
|
}
|
|
|
|
func (lg *LayoutGenerator) Init() error {
|
|
config := layoutConfig
|
|
// unmarshal from user-defined config file if it exists
|
|
if lg.ConfigPath != "" {
|
|
cdata, err := ioutil.ReadFile(lg.ConfigPath)
|
|
if err != nil {
|
|
return fmt.Errorf("read layout config from %s failed, err: %v", lg.ConfigPath, err.Error())
|
|
}
|
|
config = TemplateConfig{}
|
|
if err = yaml.Unmarshal(cdata, &config); err != nil {
|
|
return fmt.Errorf("unmarshal layout config failed, err: %v", err.Error())
|
|
}
|
|
}
|
|
|
|
if reflect.DeepEqual(config, TemplateConfig{}) {
|
|
return errors.New("empty config")
|
|
}
|
|
lg.Config = &config
|
|
|
|
return lg.TemplateGenerator.Init()
|
|
}
|
|
|
|
// checkInited initialize template definition
|
|
func (lg *LayoutGenerator) checkInited() error {
|
|
if lg.tpls == nil || lg.dirs == nil {
|
|
if err := lg.Init(); err != nil {
|
|
return fmt.Errorf("init layout config failed, err: %v", err.Error())
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (lg *LayoutGenerator) Generate(data map[string]interface{}) error {
|
|
if err := lg.checkInited(); err != nil {
|
|
return err
|
|
}
|
|
return lg.TemplateGenerator.Generate(data, "", "", false)
|
|
}
|
|
|
|
func (lg *LayoutGenerator) GenerateByService(service Layout) error {
|
|
if err := lg.checkInited(); err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(service.HandlerDir) != 0 {
|
|
// override the default "biz/handler/ping.go" to "HANDLER_DIR/ping.go"
|
|
defaultPingDir := defaultHandlerDir + sp + "ping.go"
|
|
if tpl, exist := lg.tpls[defaultPingDir]; exist {
|
|
delete(lg.tpls, defaultPingDir)
|
|
newPingDir := filepath.Clean(service.HandlerDir + sp + "ping.go")
|
|
lg.tpls[newPingDir] = tpl
|
|
}
|
|
}
|
|
|
|
if len(service.RouterDir) != 0 {
|
|
defaultRegisterDir := defaultRouterDir + sp + registerTplName
|
|
if tpl, exist := lg.tpls[defaultRegisterDir]; exist {
|
|
delete(lg.tpls, defaultRegisterDir)
|
|
newRegisterDir := filepath.Clean(service.RouterDir + sp + registerTplName)
|
|
lg.tpls[newRegisterDir] = tpl
|
|
}
|
|
}
|
|
|
|
if !service.NeedGoMod {
|
|
gomodFile := "go.mod"
|
|
if _, exist := lg.tpls[gomodFile]; exist {
|
|
delete(lg.tpls, gomodFile)
|
|
}
|
|
}
|
|
|
|
if util.IsWindows() {
|
|
buildSh := "build.sh"
|
|
bootstrapSh := defaultScriptDir + sp + "bootstrap.sh"
|
|
if _, exist := lg.tpls[buildSh]; exist {
|
|
delete(lg.tpls, buildSh)
|
|
}
|
|
if _, exist := lg.tpls[bootstrapSh]; exist {
|
|
delete(lg.tpls, bootstrapSh)
|
|
}
|
|
}
|
|
|
|
sd, err := serviceToLayoutData(service)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
rd, err := serviceToRouterData(service)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if service.HasIdl {
|
|
for k := range lg.tpls {
|
|
if strings.Contains(k, registerTplName) {
|
|
delete(lg.tpls, k)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
data := map[string]interface{}{
|
|
"*": sd,
|
|
layoutConfig.Layouts[routerIndex].Path: rd, // router.go
|
|
layoutConfig.Layouts[routerGenIndex].Path: rd, // router_gen.go
|
|
}
|
|
|
|
return lg.Generate(data)
|
|
}
|
|
|
|
// serviceToLayoutData stores go mod, serviceName, UseApacheThrift mapping
|
|
func serviceToLayoutData(service Layout) (map[string]interface{}, error) {
|
|
goMod := service.GoModule
|
|
if goMod == "" {
|
|
return nil, errors.New("please specify go-module")
|
|
}
|
|
handlerPkg := filepath.Base(defaultHandlerDir)
|
|
if len(service.HandlerDir) != 0 {
|
|
handlerPkg = filepath.Base(service.HandlerDir)
|
|
}
|
|
routerPkg := filepath.Base(defaultRouterDir)
|
|
if len(service.RouterDir) != 0 {
|
|
routerPkg = filepath.Base(service.RouterDir)
|
|
}
|
|
serviceName := service.ServiceName
|
|
if len(serviceName) == 0 {
|
|
serviceName = meta.DefaultServiceName
|
|
}
|
|
|
|
return map[string]interface{}{
|
|
"GoModule": goMod,
|
|
"ServiceName": serviceName,
|
|
"UseApacheThrift": service.UseApacheThrift,
|
|
"HandlerPkg": handlerPkg,
|
|
"RouterPkg": routerPkg,
|
|
}, nil
|
|
}
|
|
|
|
// serviceToRouterData stores the registers function, router import path, handler import path
|
|
func serviceToRouterData(service Layout) (map[string]interface{}, error) {
|
|
routerDir := sp + defaultRouterDir
|
|
handlerDir := sp + defaultHandlerDir
|
|
if len(service.RouterDir) != 0 {
|
|
routerDir = sp + service.RouterDir
|
|
}
|
|
if len(service.HandlerDir) != 0 {
|
|
handlerDir = sp + service.HandlerDir
|
|
}
|
|
return map[string]interface{}{
|
|
"Registers": []string{},
|
|
"RouterPkgPath": service.GoModule + util.PathToImport(routerDir, ""),
|
|
"HandlerPkgPath": service.GoModule + util.PathToImport(handlerDir, ""),
|
|
}, nil
|
|
}
|
|
|
|
func (lg *LayoutGenerator) GenerateByConfig(configPath string) error {
|
|
if err := lg.checkInited(); err != nil {
|
|
return err
|
|
}
|
|
buf, err := ioutil.ReadFile(configPath)
|
|
if err != nil {
|
|
return fmt.Errorf("read data file '%s' failed, err: %v", configPath, err.Error())
|
|
}
|
|
var data map[string]interface{}
|
|
if err := json.Unmarshal(buf, &data); err != nil {
|
|
return fmt.Errorf("unmarshal json data failed, err: %v", err.Error())
|
|
}
|
|
return lg.Generate(data)
|
|
}
|
|
|
|
func (lg *LayoutGenerator) Degenerate() error {
|
|
return lg.TemplateGenerator.Degenerate()
|
|
}
|