github.com/TIBCOSoftware/flogo-lib@v0.5.9/flogo/gen/gen.go (about) 1 package main 2 3 import ( 4 "path/filepath" 5 "io/ioutil" 6 "os" 7 "go/build" 8 "fmt" 9 "encoding/json" 10 "strings" 11 "text/template" 12 "io" 13 ) 14 15 func main() { 16 args := os.Args 17 18 fmt.Println("Generating flogo metadata in ", args[1]) 19 20 generateGoMetadata(args[1]) 21 } 22 23 func generateGoMetadata(dir string) error { 24 //todo optimize metadata recreation to minimize compile times 25 dependencies, err := ListDependencies(dir) 26 27 if err != nil { 28 return err 29 } 30 31 for _, dependency := range dependencies { 32 33 fmt.Println("Generating flogo metadata for:", dependency.Ref) 34 35 createMetadata(dependency) 36 } 37 38 return nil 39 } 40 41 func createMetadata(dependency *Dependency) error { 42 43 var mdFilePath string 44 var mdGoFilePath string 45 var tplMetadata string 46 47 switch dependency.ContribType { 48 case ACTION: 49 mdFilePath = filepath.Join(dependency.Dir, "action.json") 50 mdGoFilePath = filepath.Join(dependency.Dir, "action_metadata.go") 51 tplMetadata = tplMetadataGoFile 52 case TRIGGER: 53 mdFilePath = filepath.Join(dependency.Dir, "trigger.json") 54 mdGoFilePath = filepath.Join(dependency.Dir, "trigger_metadata.go") 55 tplMetadata = tplTriggerMetadataGoFile 56 case ACTIVITY: 57 mdFilePath = filepath.Join(dependency.Dir, "activity.json") 58 mdGoFilePath = filepath.Join(dependency.Dir, "activity_metadata.go") 59 tplMetadata = tplActivityMetadataGoFile 60 default: 61 return nil 62 } 63 64 raw, err := ioutil.ReadFile(mdFilePath) 65 if err != nil { 66 return err 67 } 68 69 info := &struct { 70 Package string 71 MetadataJSON string 72 }{ 73 Package: filepath.Base(dependency.Dir), 74 MetadataJSON: string(raw), 75 } 76 77 f, _ := os.Create(mdGoFilePath) 78 RenderTemplate(f, tplMetadata, info) 79 f.Close() 80 81 return nil 82 } 83 84 var tplMetadataGoFile = `package {{.Package}} 85 86 var jsonMetadata = ` + "`{{.MetadataJSON}}`" + ` 87 88 func getJsonMetadata() string { 89 return jsonMetadata 90 } 91 ` 92 93 var tplActivityMetadataGoFile = `package {{.Package}} 94 95 import ( 96 "github.com/TIBCOSoftware/flogo-lib/core/activity" 97 ) 98 99 var jsonMetadata = ` + "`{{.MetadataJSON}}`" + ` 100 101 // init create & register activity 102 func init() { 103 md := activity.NewMetadata(jsonMetadata) 104 activity.Register(NewActivity(md)) 105 } 106 ` 107 108 var tplTriggerMetadataGoFile = `package {{.Package}} 109 110 import ( 111 "github.com/TIBCOSoftware/flogo-lib/core/trigger" 112 ) 113 114 var jsonMetadata = ` + "`{{.MetadataJSON}}`" + ` 115 116 // init create & register trigger factory 117 func init() { 118 md := trigger.NewMetadata(jsonMetadata) 119 trigger.RegisterFactory(md.ID, NewFactory(md)) 120 } 121 ` 122 123 func ListDependencies(dir string) ([]*Dependency, error) { 124 125 var cType ContribType 126 127 // Get build context 128 bc := build.Default 129 currentGoPath := bc.GOPATH 130 bc.GOPATH = dir 131 //dir, _ := os.Getwd() 132 //fmt.Println("gopath:", dir) 133 ndir := "." 134 //fmt.Println("dir:", ndir) 135 136 defer func() { bc.GOPATH = currentGoPath }() 137 pkgs, err := bc.ImportDir(ndir, 0) 138 if err != nil { 139 //fmt.Println("err:", err) 140 return nil, err 141 } 142 //fmt.Println("pkgs:",pkgs) 143 144 var deps []*Dependency 145 // Get all imports 146 for _, imp := range pkgs.Imports { 147 148 //fmt.Println("imp:",imp) 149 150 pkg, err := bc.Import(imp, ndir, build.FindOnly) 151 if err != nil { 152 //fmt.Println("import err:",err) 153 // Ignore package 154 continue 155 } 156 157 //fmt.Println("pkg:",pkg.Dir) 158 159 if cType == 0 || cType == ACTION { 160 filePath := filepath.Join(pkg.Dir, "action.json") 161 // Check if it is an action 162 info, err := os.Stat(filePath) 163 if err == nil { 164 desc, err := readDescriptor(filePath, info) 165 if err == nil && desc.Type == "flogo:action" { 166 deps = append(deps, &Dependency{ContribType: ACTION, Ref: imp, Dir: pkg.Dir}) 167 } 168 } 169 } 170 if cType == 0 || cType == TRIGGER { 171 filePath := filepath.Join(pkg.Dir, "trigger.json") 172 // Check if it is a trigger 173 info, err := os.Stat(filePath) 174 if err == nil { 175 desc, err := readDescriptor(filePath, info) 176 if err == nil && desc.Type == "flogo:trigger" { 177 deps = append(deps, &Dependency{ContribType: TRIGGER, Ref: imp, Dir: pkg.Dir}) 178 } 179 } 180 } 181 if cType == 0 || cType == ACTIVITY { 182 filePath := filepath.Join(pkg.Dir, "activity.json") 183 // Check if it is an activity 184 info, err := os.Stat(filePath) 185 if err == nil { 186 desc, err := readDescriptor(filePath, info) 187 if err == nil && desc.Type == "flogo:activity" { 188 deps = append(deps, &Dependency{ContribType: ACTIVITY, Ref: imp, Dir: pkg.Dir}) 189 } 190 } 191 } 192 } 193 return deps, nil 194 } 195 196 func readDescriptor(path string, info os.FileInfo) (*Descriptor, error) { 197 198 raw, err := ioutil.ReadFile(path) 199 if err != nil { 200 fmt.Println("error: " + err.Error()) 201 return nil, err 202 } 203 204 return ParseDescriptor(string(raw)) 205 } 206 207 // ParseDescriptor parse a descriptor 208 func ParseDescriptor(descJson string) (*Descriptor, error) { 209 descriptor := &Descriptor{} 210 211 err := json.Unmarshal([]byte(descJson), descriptor) 212 213 if err != nil { 214 return nil, err 215 } 216 217 return descriptor, nil 218 } 219 220 type Descriptor struct { 221 Name string `json:"name"` 222 Version string `json:"version"` 223 Description string `json:"description"` 224 Type string `json:"type"` 225 } 226 227 type Dependency struct { 228 ContribType ContribType 229 Ref string 230 Dir string 231 } 232 233 func (d *Dependency) MarshalJSON() ([]byte, error) { 234 return json.Marshal(&struct { 235 ContribType string `json:"type"` 236 Ref string `json:"ref"` 237 }{ 238 ContribType: d.ContribType.String(), 239 Ref: d.Ref, 240 }) 241 } 242 243 func (d *Dependency) UnmarshalJSON(data []byte) error { 244 ser := &struct { 245 ContribType string `json:"type"` 246 Ref string `json:"ref"` 247 }{} 248 249 if err := json.Unmarshal(data, ser); err != nil { 250 return err 251 } 252 253 d.Ref = ser.Ref 254 d.ContribType = ToContribType(ser.ContribType) 255 256 return nil 257 } 258 259 type ContribType int 260 261 const ( 262 ACTION ContribType = 1 + iota 263 TRIGGER 264 ACTIVITY 265 ) 266 267 var ctStr = [...]string{ 268 "all", 269 "action", 270 "trigger", 271 "activity", 272 } 273 274 func (m ContribType) String() string { return ctStr[m] } 275 276 func ToContribType(name string) ContribType { 277 switch name { 278 case "action": 279 return ACTION 280 case "trigger": 281 return TRIGGER 282 case "activity": 283 return ACTIVITY 284 case "all": 285 return 0 286 } 287 288 return -1 289 } 290 291 //RenderTemplate renders the specified template 292 func RenderTemplate(w io.Writer, text string, data interface{}) { 293 t := template.New("top") 294 t.Funcs(template.FuncMap{"trim": strings.TrimSpace}) 295 template.Must(t.Parse(text)) 296 if err := t.Execute(w, data); err != nil { 297 panic(err) 298 } 299 }