解析xml生成相应的java文件

package gsxdb

import (
    "io"
    "ron.zhang/util/file"
    "ron.zhang/util/str"
    "text/template"
)

//xbean的模板
var xbeanTmplate = `
package xbean;
import xdb.Bean;

public class {{.Name }}Stub extends XbeanAdaptor<{{.Name}}> implements Bean {
    {{range $index,$V:=.Attributes }}  
            private {{.Des }} {{$index}} ;{{print "\n"}}  
    {{end}}

    {{range $index,$V:=.Attributes }}  
        public void set{{Uper $index}} ( {{.Des}}  a) {
            this.{{$index}}=a;
        }

        public {{.Des}} get{{Uper $index}} () {
            return this.{{$index}};
        }

    {{end}}
}`

var funcMap = template.FuncMap{
    "Uper":         uper,
    "templateType": templateType,
}

func uper(input string) string {
    out, _ := str.FristLetterUper(input)
    return out
}

/*
xtable的访问封装,不直接使用
*/
var xtalbeInterface = `
    {{$keyType:=.KeyType}}
    package xbean;

    {{if .Bean.Attributes}} 
        import xbean.{{.Bean.Name}};
    {{end}}


    public interface {{Uper .Bean.Name }}Provider {
        public {{.Bean.Name}} get({{.KeyType}} key);
        public {{.Bean.Name}} select({{.KeyType}} key);

        public  {{.Bean.Name}} new{{.Bean.Name}} ({{.KeyType}} key);

        {{range $index,$V:=.Bean.Attributes }}  
            public {{.Des}} select{{Uper $index}} ({{$keyType}} key);
           {{end}}
    }
`

var xtableProviderImplment = `
    {{$keyType:=.KeyType}}
    {{$TableName:= Uper .Name}}
    package xbean;

    {{if .Bean.Attributes}} 
        import xbean.{{.Bean.Name}};
    {{end}}

    public class {{Uper .Bean.Name }}ProviderImpl implements {{Uper .Bean.Name}}Provider {
        @Override
        public {{.Bean.Name}} get({{.KeyType}} key){
            return xtable.{{$TableName}}.get(key);
        }
        @Override
        public {{.Bean.Name}} select({{.KeyType}} key){
                return xtable.{{$TableName}}.select(key);
        }

        @Override
        public  {{.Bean.Name}} new{{.Bean.Name}} ({{.KeyType}} key){
            return xbean.Pod.new{{.Bean.Name}}();
        }

        {{range $index,$V:=.Bean.Attributes }}  
            @Override
            public {{.Des}} select{{Uper $index}} ({{$keyType}} key){
                return xtable.{{$TableName}}.select{{Uper $index}}(key);
            }
           {{end}}
    }
    
`

var xtableProviderTest = `
    {{$keyType:=.KeyType}}
package gsxdb

import (
    "encoding/xml"
    "fmt"
    "io/ioutil"
)

/*
xml对应的bean,需要做个转化,设计的时候考虑不全,做个适配吧
*/
type XmlXdb struct {
    XMLName   xml.Name    `xml:"xdb"`
    Xbeans    []XmlXbean  `xml:"xbean,>"`
    Xtables   []XmlXtable `xml:"table,>"`
    name2Bean map[string]Xbean
}

type XmlXbean struct {
    Name       string         `xml:"name,attr"`
    Attributes []XmlAttribute `xml:"variable,>"`
}

type XmlXtable struct {
    Name  string `xml:"name,attr"`
    Key   string `xml:"key,attr"`
    Value string `xml:"value,attr"`
}

type XmlAttribute struct {
    Value string `xml:"value,attr"`
    Name  string `xml:"name,attr"`
    Type  string `xml:"type,attr"`
    Key   string `xml:"key,attr"`
}

/*
解析xml
*/
func ParserFromFile(name string) (XmlXdb, error) {
    v := XmlXdb{}
    //读取xml数据
    bytes, err := ioutil.ReadFile(name)
    if err != nil {
        panic(err)
    }

    //解析xml,生成结构体
    err = xml.Unmarshal(bytes, &v)
    if err != nil {
        fmt.Printf("error: %v", err)
        return v, err
    }

    return v, nil
}

package gsxdb

import ()

/*
类型接口
*/

type Xtype interface {
    Des() string
    DefaultValue() interface{}
}

type Xmap struct {
    KeyType   string
    ValueType string
}

//map类型实现xtype的方法
func (a Xmap) Des() string {
    return "java.util.Map<" + a.KeyType + "," + a.ValueType + ">"
}

func (a Xmap) DefaultValue() interface{} {
    return nullValue()
}

//list类型
type Xlist struct {
    ValueType string
}

//list类型实现xtype的方法
func (a Xlist) Des() string {
    return "java.util.List<" + a.ValueType + ">"
}

func (a Xlist) DefaultValue() interface{} {
    return nullValue()
}

type XInt struct {
    XstrType
}

func (a XInt) DefaultValue() interface{} {
    return zeroInt()
}

type XLong struct {
    XstrType
}

func (a XLong) DefaultValue() interface{} {
    return zeroLong()
}

type XstrType string

//list类型实现xtype的方法
func (a XstrType) Des() string {
    return string(a)
}

func (a XstrType) DefaultValue() interface{} {
    return nullValue()
}

type Xbean struct {
    Name       string
    Attributes map[string]Xtype
}

type XbeanProvider struct {
    Name    string
    Bean    Xbean
    KeyType string
}

var zeroInt = func() interface{} {
    return 0
}

var zeroLong = func() interface{} {
    return "0l"
}

var nullValue = func() interface{} {
    return "null"
}

 


    {{$TableName:= Uper .Name}}
    package xbean;

    {{if .Bean.Attributes}} 
        import xbean.{{.Bean.Name}};
    {{end}}

    public class {{Uper .Bean.Name }}ProviderTest implements {{Uper .Bean.Name}}Provider {
        private java.util.Map<{{templateType .KeyType}},{{.Bean.Name}}> containers=new java.util.HashMap<{{templateType .KeyType}},{{.Bean.Name}}>();


        @Override
        public {{.Bean.Name}} get({{.KeyType}} key){
            return containers.get(key);
        }
        @Override
        public {{.Bean.Name}} select({{.KeyType}} key){
                return containers.get(key);
        }

        public  {{.Bean.Name}} new{{.Bean.Name}} ({{.KeyType}} key){
            return xbean.Pod.new{{.Bean.Name}}();
        }

        {{range $index,$V:=.Bean.Attributes }} 
            @Override
            public {{.Des}} select{{Uper $index}} ({{$keyType}} key){
                if (containers.containsKey( key)) {
                    return containers.get(key).get{{Uper $index}}();;
                }
                
                return {{ .DefaultValue}};
            }
           {{end}}
    }
    
`

/*
生成xbean的stub文件
*/
func GenXBean(bean Xbean, writer io.Writer) {
    tpl, err := template.New("data").Funcs(funcMap).Parse(xbeanTmplate)
    if err != nil {
        panic(nil)
    }

    tpl.Execute(writer, bean)
}

/*
生成表的数据
*/
func GenXBeanProvider(bean XbeanProvider, templatStr string, writer io.Writer) {

    tpl, err := template.New("data").Funcs(funcMap).Parse(templatStr)
    if err != nil {
        panic(nil)
    }
    tpl.Execute(writer, bean)
}

/*
生成java文件
*/
func (a *XmlXdb) Gen() {

    a.transBeans()
    //生成Xbean
    for _, value := range a.name2Bean {
        GenXBean(value, file.CreateFileR("./src/xbean", value.Name+".java"))
    }

    //生成Xtables
    var provider XbeanProvider
    for _, value := range a.Xtables {
        provider = a.tranTable(value)
        GenXBeanProvider(provider, xtalbeInterface, file.CreateFileR("../gs/src/xbean", provider.Bean.Name+"Provider.java"))
        GenXBeanProvider(provider, xtableProviderImplment, file.CreateFileR("../gs/src/xbean", provider.Bean.Name+"ProviderImpl.java"))
        GenXBeanProvider(provider, xtableProviderTest, file.CreateFileR("./src/xbean", provider.Bean.Name+"ProviderTest.java"))
    }

}

func (a XmlXdb) tranTable(input XmlXtable) XbeanProvider {
    provider := XbeanProvider{}
    provider.Name = input.Name
    provider.KeyType = input.Key
    bean, has := a.name2Bean[input.Value]
    if has {
        provider.Bean = bean

    } else {
        provider.Bean = Xbean{input.Value, nil}
    }

    return provider
}

//初始化函数
func (a *XmlXdb) transBeans() {

    if a.name2Bean != nil {
        return
    }

    //初始化转换字典
    a.name2Bean = make(map[string]Xbean, len(a.Xbeans))

    for _, v := range a.Xbeans {
        if _, b := a.name2Bean[v.Name]; !b {
            a.name2Bean[v.Name] = tranBean(v)
        }
    }

}

func tranBean(input XmlXbean) Xbean {
    bean := Xbean{}
    bean.Name = input.Name
    bean.Attributes = make(map[string]Xtype, len(input.Attributes))

    for _, value := range input.Attributes {
        bean.Attributes[value.Name] = caseType(value)
    }

    return bean
}

/*
类型做个适配
*/
func caseType(inut XmlAttribute) Xtype {

    switch inut.Type {
    case "vector", "list":
        return Xlist{templateType(inut.Value)}
    case "map":
        return Xmap{templateType(inut.Key), templateType(inut.Value)}
    case "int":
        return XInt{XstrType(inut.Type)}

    case "long":
        return XLong{XstrType(inut.Type)}
    default:
        return XstrType(inut.Type)
    }

}

func templateType(input string) string {
    switch input {
    case "long":
        return "Long"
    case "int":
        return "Integer"
    default:
        return input
    }
}