models.go 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927
  1. package common
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "regexp"
  7. "strconv"
  8. "strings"
  9. "text/template"
  10. "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/api"
  11. "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/api/errs"
  12. ts "git.eugeniocarvalho.dev/eugeniucarvalho/gg/generators/typescript"
  13. "github.com/kataras/iris/v12/context"
  14. "go.mongodb.org/mongo-driver/bson/primitive"
  15. )
  16. const (
  17. BSON = "go.mongodb.org/mongo-driver/bson"
  18. BSONX = "go.mongodb.org/mongo-driver/x/bsonx"
  19. MONGO = "go.mongodb.org/mongo-driver/mongo"
  20. BSON_PRIMITIVE = "go.mongodb.org/mongo-driver/bson/primitive"
  21. IRIS_CTX = "github.com/kataras/iris/v12/context"
  22. IRIS = "github.com/kataras/iris/v12"
  23. UPDATE_RELATION = "UpdateRelation"
  24. BASE_HAS_DEPENDE = "HasDep"
  25. )
  26. var (
  27. API_URL = "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/api"
  28. API_ERROR = "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/api/errs"
  29. CODE_GEN_V2_COMMON = "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/common"
  30. CODE_GEN_V2_AUTHORIZATION = "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/authorization"
  31. // Variavel de controle de acesso aos models da API.
  32. Models = &api.Mongo{}
  33. camelToUnderRegex = regexp.MustCompile(`([^[:lower:]])`)
  34. //Generic e
  35. Generic = regexp.MustCompile("(?P<type>[\\w-_]+)<(?P<dtype>[\\w\\*]+)>")
  36. //GenericPart e
  37. GenericPart = regexp.MustCompile("<(?P<id>[\\w\\*]+)>")
  38. //ImportMap e
  39. importMap = map[string]string{
  40. "bson": BSON,
  41. "primitive": BSON_PRIMITIVE,
  42. }
  43. SR = SchemasRelations{
  44. R: map[string][]*Relation{},
  45. }
  46. )
  47. type BuildOptions struct {
  48. Mode string
  49. IgnoreBuildSteps string
  50. IgnoreBuildStepsValues map[int]bool
  51. }
  52. func (b *BuildOptions) IgnoreStep(step int) bool {
  53. _, ok := b.IgnoreBuildStepsValues[step]
  54. return ok
  55. }
  56. func (b *BuildOptions) Parse() error {
  57. var (
  58. value int
  59. err error
  60. )
  61. if b.IgnoreBuildStepsValues == nil {
  62. b.IgnoreBuildStepsValues = map[int]bool{}
  63. }
  64. for _, v := range strings.Split(b.IgnoreBuildSteps, ",") {
  65. if value, err = strconv.Atoi(v); err != nil {
  66. return err
  67. }
  68. b.IgnoreBuildStepsValues[value] = true
  69. }
  70. return nil
  71. }
  72. func ImportMap(base string) string {
  73. if v, ok := importMap[base]; ok {
  74. return v
  75. }
  76. panic(fmt.Sprintf("Import %s não definido", base))
  77. }
  78. type Project struct {
  79. OutPath string `json:"outPath"`
  80. Package string `json:"package"`
  81. Kind string `json:"kind"`
  82. Etag string `json:"etag"`
  83. Version string `json:"version"`
  84. BuildVersion string `json:"buildVersion"`
  85. ID string `json:"id"`
  86. Name string `json:"name"`
  87. DataBaseSufix string `json:"dataBaseSufix"`
  88. Mode string `json:"mode"`
  89. Revision string `json:"revision"`
  90. Title string `json:"title"`
  91. Description string `json:"description"`
  92. OwnerDomain string `json:"ownerDomain"`
  93. OwnerName string `json:"ownerName"`
  94. DocumentationLink string `json:"documentationLink"`
  95. Protocol string `json:"protocol"`
  96. BaseURL string `json:"baseUrl"`
  97. BasePath string `json:"basePath"`
  98. Middlewares []string `json:"middlewares"`
  99. ServicePath string `json:"servicePath"`
  100. GitRepository string `json:"git.repository"`
  101. Environment Environment `json:"environment"`
  102. Variables map[string]interface{} `json:"variables"`
  103. Resource *Resource `json:"-"`
  104. Schemas []*Entity `json:"schemas"`
  105. SchemasRef map[string]*Entity `json:"-"`
  106. Resources []*Resource `json:"resources"`
  107. Auth Auth `json:"auth"`
  108. TypeScriptSource *ts.File `json:"-"`
  109. Icons map[string]string `json:"icons"`
  110. ReplaceWhenEmpty map[string]bool `json:"ReplaceWhenEmpty"`
  111. OmitEmpty map[string]bool `json:"omitempty"`
  112. Clients []*Client `json:"clients,omitempty"`
  113. Translators map[string]TranslationFn `json:"-"`
  114. FormatMap map[string]string `json:"-"`
  115. Queries *QueryDef `json:"queries"`
  116. ACL *ACL `json:"acl"`
  117. Custom map[string]interface{} `json:"custom"`
  118. }
  119. type ACL struct {
  120. Roles []*Role `json:"roles"`
  121. Permissions []*Permission `json:"permissions"`
  122. }
  123. type QueryDef struct {
  124. Blacklistwords map[string][]string `json:"blacklistwords"`
  125. Queries map[string]string `json:"queries"`
  126. Common map[string]string `json:"common"`
  127. }
  128. type Role struct {
  129. Title string `json:"title"`
  130. Description string `json:"description"`
  131. ID string `json:"id"`
  132. AllowRemove bool `json:"allowRemove,omitempty"`
  133. Permissions []string `json:"permissions"`
  134. }
  135. type Permission struct {
  136. Title string `json:"title"`
  137. Description string `json:"description"`
  138. ID string `json:"id"`
  139. }
  140. type Client struct {
  141. Id string `json:"id,omitempty"`
  142. OutputDir string `json:"outputDir,omitempty"`
  143. }
  144. type Auth struct {
  145. AuthCookieDomain string `json:"authCookieDomain"`
  146. AuthTokenID string `json:"authTokenId"`
  147. Oauth2 Oauth2 `json:"oauth2"`
  148. }
  149. type Oauth2 struct {
  150. URI string `json:"uri"`
  151. Client Oauth2Client `json:"client"`
  152. Scopes []Scope `json:"scopes"`
  153. }
  154. type Oauth2Client struct {
  155. RedirectURI string `json:"redirect_uri"`
  156. ClientID string `json:"client_id"`
  157. ClientSecret string `json:"client_secret"`
  158. Scope []string `json:"scope"`
  159. }
  160. type Scope struct {
  161. ID string `json:"id"`
  162. PromptToUser []string `json:"promptToUser"`
  163. Description string `json:"description"`
  164. }
  165. type EnvironmentVariable struct {
  166. ID string `json:"id"`
  167. CamelID string `json:"-"`
  168. Default string `json:"default"`
  169. Required bool `json:"required,omitempty"`
  170. Description string `json:"description"`
  171. }
  172. type Environment map[string]*EnvironmentVariable
  173. type Entity struct {
  174. HasMode bool `json:"hasMode"`
  175. ID string `json:"id"`
  176. Type string `json:"type"`
  177. Description string `json:"description"`
  178. Collection string `json:"collection"`
  179. DB string `json:"db"`
  180. Extends []string `json:"extends"`
  181. Properties []*Propertie `json:"properties"`
  182. Representations map[string][]string `json:"representations"`
  183. Custom map[string]interface{} `json:"custom"`
  184. }
  185. type Resource struct {
  186. ID string `json:"id"`
  187. Description string `json:"description"`
  188. Entity string `json:"entity"`
  189. Formats []*Value `json:"formats"`
  190. Methods []*Method `json:"methods"`
  191. CommonParams map[string]*Parameter `json:"commonParams"`
  192. Custom map[string]interface{} `json:"custom"`
  193. }
  194. type Method struct {
  195. ID string `json:"id"`
  196. Entity string `json:"entity"`
  197. Type string `json:"type"` // Assume valores {one, list, implement}
  198. Path string `json:"path"`
  199. Template string `json:"template"`
  200. BeforePersistAction bool `json:"beforePersistAction"`
  201. HttpMethod string `json:"httpMethod"`
  202. Description string `json:"description"`
  203. Response string `json:"response"`
  204. Request string `json:"request"`
  205. Scopes []string `json:"scopes"`
  206. Middlewares []string `json:"middlewares"`
  207. Postresponse []string `json:"postresponse"`
  208. ParameterOrder []string `json:"parameterOrder"`
  209. ParametersString []string `json:"parameters"`
  210. Resource *Resource `json:"-"`
  211. Hooks map[string]bool `json:"hooks"`
  212. Parameters map[string]*Parameter `json:"parametersmap"`
  213. Preconditions []Action `json:"preconditions"`
  214. BeforeResponse []Action `json:"beforeResponse"`
  215. BeforeParseRequest []Action `json:"beforeParseRequest"`
  216. Custom map[string]interface{} `json:"custom"`
  217. // Parameters map[string]*Parameter `json:"parameters"`
  218. }
  219. type Action struct {
  220. ID string `json:"id"`
  221. Context map[string]interface{} `json:"context"`
  222. }
  223. type Parameter struct {
  224. ID string `json:"id"`
  225. Type string `json:"type"`
  226. Required bool `json:"required"`
  227. Description string `json:"description"`
  228. Default string `json:"default"`
  229. Location string `json:"location"`
  230. ConvertTo string `json:"convertTo"`
  231. Custom map[string]interface{} `json:"custom"`
  232. // Validation *ValidationRule `json:"validation"`
  233. Validation map[string]interface{} `json:"validation"`
  234. }
  235. // type ValidationRule struct {
  236. // Accept []*Value `json:"-"`
  237. // AcceptRef []string `json:"accept"`
  238. // Reject []*Value `json:"reject"`
  239. // RejectRef []string `json:"-"`
  240. // In []string `json:"in"`
  241. // Contains string `json:"contains"`
  242. // Regex string `json:"regex"`
  243. // Min string `json:"min"`
  244. // Max string `json:"max"`
  245. // Type string `json:"type"`
  246. // }
  247. type Value struct {
  248. Id string `json:"id"`
  249. Value string `json:"value"`
  250. Default bool `json:"default"`
  251. Fields string `json:"fields"`
  252. Description string `json:"description"`
  253. }
  254. type Propertie struct {
  255. ID string `json:"id"`
  256. Name string `json:"name"`
  257. Type string `json:"type"`
  258. Description string `json:"description"`
  259. AutogenerateInput string `json:"autogenerate"`
  260. Autogenerate map[string]AutoGenDef `json:"-"`
  261. Targets string `json:"targets"`
  262. Array bool `json:"array"`
  263. Required bool `json:"required"`
  264. Relation bool `json:"relation"`
  265. TagVisited bool `json:"-"`
  266. Reference bool `json:"reference"`
  267. Readonly bool `json:"readonly"`
  268. Unique bool `json:"uniq"`
  269. Default interface{} `json:"default"`
  270. Enum []string `json:"enum"`
  271. Values []interface{} `json:"values"`
  272. EnumDescriptions []string `json:"enumDescriptions"`
  273. Tags map[string]string `json:"tags"`
  274. Filter []*Filter `json:"filter"`
  275. Custom map[string]interface{} `json:"custom"`
  276. }
  277. type AutoGenDef struct {
  278. Type string
  279. Args []string
  280. }
  281. type Filter struct {
  282. Path string `json:"path"`
  283. Type string `json:"type"`
  284. Label string `json:"label"`
  285. UserEnumAsOptions bool `json:"userEnumAsOptions"`
  286. Multiples bool `json:"multiples"`
  287. Options []FilterOption `json:"options,omitempty"`
  288. }
  289. type FilterOption struct {
  290. Value interface{} `json:"value"`
  291. Label string `json:"label"`
  292. }
  293. type ApiFilter struct {
  294. Id string `json:"id"`
  295. Date int64 `json:"date"`
  296. Fields []*Filter `json:"fields"`
  297. }
  298. func NewApiFilter(id string) *ApiFilter {
  299. return &ApiFilter{
  300. Id: id,
  301. Fields: []*Filter{},
  302. }
  303. }
  304. func RequestParams(args string, params map[string]*Parameter) func(ctx context.Context) (resp interface{}, err *errs.Error) {
  305. argsList := strings.Split(args, ",")
  306. return func(ctx context.Context) (resp interface{}, err *errs.Error) {
  307. var (
  308. values = ctx.Values()
  309. id string
  310. value interface{}
  311. sourceValue interface{}
  312. param *Parameter
  313. paramsMap = map[string]interface{}{}
  314. )
  315. values.Set("$params", paramsMap)
  316. for _, arg := range argsList {
  317. param = params[arg]
  318. switch param.Location {
  319. case "query":
  320. id = "query." + arg
  321. value = api.Q(ctx, arg, param.Default)
  322. case "path":
  323. id = "path." + arg
  324. value = api.P(ctx, arg, param.Default)
  325. }
  326. sourceValue = value
  327. emptyValue := (value == "" || value == nil)
  328. if param.Required && emptyValue {
  329. invalidArgument := errs.InvalidArgument()
  330. invalidArgument.Message = fmt.Sprintf(
  331. "ParamRequired: param '%s' in '%s'",
  332. param.ID,
  333. param.Location,
  334. )
  335. return nil, invalidArgument
  336. }
  337. if !emptyValue && param.ConvertTo != "" {
  338. if value, err = convertValueByType(param.ConvertTo, value); err != nil {
  339. invalidArgument := errs.InvalidArgument()
  340. invalidArgument.Message = fmt.Sprintf(
  341. "ParamTypeConversionError: param '%s' in '%s' with value '%v'. Waiting a %s ",
  342. param.ID,
  343. param.Location,
  344. value,
  345. param.ConvertTo,
  346. )
  347. return nil, invalidArgument
  348. }
  349. }
  350. if param.Validation != nil {
  351. for validator, args := range param.Validation {
  352. if fn, found := validationParamFunctions[validator]; found {
  353. ctx.Application().Logger().Info(fmt.Sprintf("validadete[%s][%s][%v]", validator, args, value))
  354. if err = fn(param, value, args); err != nil {
  355. return nil, err
  356. }
  357. }
  358. }
  359. }
  360. values.Set(fmt.Sprintf("%s_conv", id), value)
  361. values.Set(id, sourceValue)
  362. paramsMap[fmt.Sprintf("%s_conv", arg)] = value
  363. paramsMap[arg] = sourceValue
  364. }
  365. ctx.Next()
  366. return
  367. }
  368. }
  369. var (
  370. convertionTypeFunctions = map[string]func(interface{}) (interface{}, *errs.Error){
  371. "ObjectID": stringToObjectId,
  372. "bool": stringToBool,
  373. "int": stringToInt,
  374. "number": stringToFloat,
  375. }
  376. validationParamFunctions = map[string]func(*Parameter, interface{}, interface{}) *errs.Error{
  377. "min": func(param *Parameter, value interface{}, minString interface{}) *errs.Error {
  378. var input float64
  379. if v, ok := value.(int64); ok {
  380. input = float64(v)
  381. } else if v, ok := value.(float64); ok {
  382. input = v
  383. } else if v, ok := value.(string); ok {
  384. input = float64(len(v))
  385. } else {
  386. invalidArgument := errs.InvalidArgument()
  387. invalidArgument.Message = fmt.Sprintf(
  388. "[%s] ValueRestriction: mim validation requires (int,float,string)",
  389. param.ID,
  390. )
  391. return invalidArgument
  392. }
  393. if min, convert := minString.(float64); !convert || input < min {
  394. invalidArgument := errs.InvalidArgument()
  395. invalidArgument.Message = fmt.Sprintf(
  396. "[%s] ValueRestriction: value > %v. Received (%v)",
  397. param.ID,
  398. minString,
  399. value,
  400. )
  401. return invalidArgument
  402. }
  403. return nil
  404. },
  405. "max": func(param *Parameter, value interface{}, maxString interface{}) *errs.Error {
  406. var input float64
  407. if v, ok := value.(int64); ok {
  408. input = float64(v)
  409. } else if v, ok := value.(float64); ok {
  410. input = v
  411. } else if v, ok := value.(string); ok {
  412. input = float64(len(v))
  413. } else {
  414. invalidArgument := errs.InvalidArgument()
  415. invalidArgument.Message = fmt.Sprintf(
  416. "[%s] ValueRestriction: mim validation requires (int,float,string)",
  417. param.ID,
  418. )
  419. return invalidArgument
  420. }
  421. if max, convert := maxString.(float64); !convert || input > max {
  422. invalidArgument := errs.InvalidArgument()
  423. invalidArgument.Message = fmt.Sprintf(
  424. "[%s] ValueRestriction: value < %v. Received (%v)",
  425. param.ID,
  426. maxString,
  427. value,
  428. )
  429. return invalidArgument
  430. }
  431. return nil
  432. },
  433. "accept": func(param *Parameter, input interface{}, accept interface{}) *errs.Error {
  434. var (
  435. acceptValues = accept.([]interface{})
  436. acceptValuesString = []string{}
  437. value = fmt.Sprintf("%v", input)
  438. )
  439. for _, acceptValue := range acceptValues {
  440. if value == acceptValue.(string) {
  441. return nil
  442. }
  443. acceptValuesString = append(acceptValuesString, acceptValue.(string))
  444. }
  445. invalidArgument := errs.InvalidArgument()
  446. invalidArgument.Message = fmt.Sprintf(
  447. "[%s] ValueRestriction: '%s' isn't accept. Accept [%s]",
  448. param.ID,
  449. value,
  450. strings.Join(acceptValuesString, ","),
  451. )
  452. return invalidArgument
  453. },
  454. "reject": func(param *Parameter, input interface{}, reject interface{}) *errs.Error {
  455. var (
  456. rejectValues = reject.([]interface{})
  457. value = fmt.Sprintf("%v", input)
  458. )
  459. for _, rejectValue := range rejectValues {
  460. if value == rejectValue.(string) {
  461. invalidArgument := errs.InvalidArgument()
  462. invalidArgument.Message = fmt.Sprintf(
  463. "[%s] ValueRestriction: '%s' isn't accept",
  464. param.ID,
  465. value,
  466. )
  467. return invalidArgument
  468. }
  469. }
  470. return nil
  471. },
  472. "regex": func(param *Parameter, input interface{}, regex interface{}) *errs.Error {
  473. var (
  474. regexString = regex.(string)
  475. value = input.(string)
  476. )
  477. regexInstance := regexp.MustCompile(regexString)
  478. if !regexInstance.Match([]byte(value)) {
  479. invalidArgument := errs.InvalidArgument()
  480. invalidArgument.Message = fmt.Sprintf(
  481. "[%s] ValueRestriction: '%s' isn't accept",
  482. param.ID,
  483. value,
  484. )
  485. return invalidArgument
  486. }
  487. return nil
  488. },
  489. }
  490. )
  491. func stringToObjectId(value interface{}) (interface{}, *errs.Error) {
  492. var (
  493. valueString = value.(string)
  494. valueObjectID primitive.ObjectID
  495. err error
  496. )
  497. if valueObjectID, err = primitive.ObjectIDFromHex(valueString); err != nil {
  498. invalidArgument := errs.InvalidArgument()
  499. invalidArgument.Message = fmt.Sprintf("The value '%s' is'nt a valid ObjectId", valueString)
  500. return nil, invalidArgument
  501. }
  502. return valueObjectID, nil
  503. }
  504. func stringToBool(value interface{}) (interface{}, *errs.Error) {
  505. var (
  506. valueBool bool
  507. err error
  508. )
  509. if valueBool, err = strconv.ParseBool(value.(string)); err != nil {
  510. invalidArgument := errs.InvalidArgument()
  511. invalidArgument.Message = fmt.Sprintf("The value '%s' is'nt a valid boolean. Accept [true,1,T,false,0,F]", valueBool)
  512. return nil, invalidArgument
  513. }
  514. return valueBool, nil
  515. }
  516. func stringToInt(value interface{}) (interface{}, *errs.Error) {
  517. var (
  518. valueInt int64
  519. err error
  520. )
  521. if valueInt, err = strconv.ParseInt(value.(string), 10, 64); err != nil {
  522. invalidArgument := errs.InvalidArgument()
  523. invalidArgument.Message = fmt.Sprintf("The value '%s' is'nt a valid int", valueInt)
  524. return nil, invalidArgument
  525. }
  526. return valueInt, nil
  527. }
  528. func stringToFloat(value interface{}) (interface{}, *errs.Error) {
  529. var (
  530. valueFloat float64
  531. err error
  532. )
  533. if valueFloat, err = strconv.ParseFloat(value.(string), 64); err != nil {
  534. invalidArgument := errs.InvalidArgument()
  535. invalidArgument.Message = fmt.Sprintf("The value '%s' is'nt a valid number", valueFloat)
  536. return nil, invalidArgument
  537. }
  538. return valueFloat, nil
  539. }
  540. func convertValueByType(typ string, value interface{}) (interface{}, *errs.Error) {
  541. var err *errs.Error
  542. if fn, found := convertionTypeFunctions[typ]; found {
  543. if value, err = fn(value); err != nil {
  544. return nil, err
  545. }
  546. }
  547. return value, nil
  548. }
  549. // func validateParam(param *Parameter, value interface{}) (interface{}, *errs.Error) {
  550. // var err *errs.Error
  551. // return value, nil
  552. // }
  553. func (t *Method) Hook(id string) bool {
  554. // active := t.Hooks[id]
  555. // return active
  556. return t.Hooks[id]
  557. }
  558. func (t *Propertie) ParseAutogenerate() error {
  559. if t.AutogenerateInput != "" {
  560. parts := strings.Split(t.AutogenerateInput, ":")
  561. if len(parts) < 2 {
  562. return fmt.Errorf("Invalid autogenerate input '%s' in attribute '%s'.", t.AutogenerateInput, t.ID)
  563. }
  564. if t.Autogenerate == nil {
  565. t.Autogenerate = map[string]AutoGenDef{}
  566. }
  567. args := strings.Split(parts[1], "#")
  568. for _, k := range strings.Split(parts[0], ",") {
  569. t.Autogenerate[k] = AutoGenDef{
  570. Type: args[0],
  571. Args: args[1:],
  572. }
  573. }
  574. }
  575. return nil
  576. }
  577. type SchemasRelations struct {
  578. R map[string][]*Relation
  579. }
  580. type Relation struct {
  581. Source string
  582. Target string
  583. Attr string
  584. Collection string
  585. DB string
  586. IsArray bool
  587. }
  588. type EntityInfo struct {
  589. Name string
  590. Origin string
  591. NewName string
  592. DynamicType string
  593. DynamicTypeId string
  594. IsGeneric bool
  595. }
  596. type TranslationFn func(p *Project) error
  597. func (p *Project) Build(b *BuildOptions) error {
  598. var err error
  599. for _, c := range p.Clients {
  600. if fn, found := p.Translators[c.Id]; found {
  601. if err = fn(p); err != nil {
  602. fmt.Println("error on ", c.Id)
  603. return err
  604. }
  605. } else {
  606. return fmt.Errorf("Middleware '%s' not defined!", c.Id)
  607. }
  608. }
  609. // fmt.Println("--- RunBuildCommads")
  610. return RunBuildCommads(p, b)
  611. }
  612. func (p *Project) OutDirectory(path string) {
  613. p.OutPath = path
  614. }
  615. func (p *Project) Client(id string) *Client {
  616. for _, c := range p.Clients {
  617. if c.Id == id {
  618. return c
  619. }
  620. }
  621. return nil
  622. }
  623. func (p *Project) Save(path string) error {
  624. data, err := json.MarshalIndent(p, "", " ")
  625. if err == nil {
  626. err = FilePutContentsBytes(path, data, 0777)
  627. }
  628. return err
  629. }
  630. func (p *Project) GetCollection(entity string) string {
  631. for _, e := range p.Schemas {
  632. if e.ID == entity {
  633. return e.Collection
  634. }
  635. }
  636. return "undefined"
  637. }
  638. func getCustom(options map[string]interface{}, path string) (resp interface{}) {
  639. if options != nil {
  640. resp = options[path]
  641. }
  642. return
  643. }
  644. func (p *Project) GetEntityDB(entity string) string {
  645. if en, found := p.SchemasRef[entity]; found {
  646. return en.DB + p.DataBaseSufix
  647. }
  648. panic(fmt.Sprintf("DB attribute is empty in entity '%s'", entity))
  649. }
  650. func (p *Project) EntityDesc(ID string) *Entity {
  651. if _, y := p.SchemasRef[ID]; !y {
  652. fmt.Println("EntityDesc(ID)", ID)
  653. return nil
  654. }
  655. return p.SchemasRef[ID]
  656. }
  657. func (m *Method) HasPathParams() bool {
  658. return len(m.ParameterOrder) > 0
  659. }
  660. func (m *Method) HasFormatParam() (bool, *Parameter) {
  661. for id, param := range m.Parameters {
  662. // param = m.Parameters[id]
  663. // fmt.Println("param:", param.ID)
  664. if id == "format" {
  665. return true, param
  666. }
  667. }
  668. return false, nil
  669. }
  670. func (p *Project) GetUrlFromMethod(method *Method) string {
  671. return p.BaseURL + method.Path
  672. }
  673. func (p *Project) ResponseEntity(property string) *EntityInfo {
  674. var (
  675. pi = &EntityInfo{
  676. Origin: property,
  677. }
  678. )
  679. match := Generic.FindStringSubmatch(property)
  680. if len(match) == 0 {
  681. return pi
  682. }
  683. for i, name := range Generic.SubexpNames() {
  684. switch name {
  685. case "type":
  686. pi.Name = match[i]
  687. case "dtype":
  688. pi.DynamicType = match[i]
  689. pi.IsGeneric = true
  690. }
  691. }
  692. if pi.IsGeneric {
  693. entity := p.GetSchema(pi.Name)
  694. match = GenericPart.FindStringSubmatch(entity.ID)
  695. for i, name := range GenericPart.SubexpNames() {
  696. switch name {
  697. case "id":
  698. pi.DynamicTypeId = match[i]
  699. }
  700. }
  701. }
  702. pi.NewName = pi.Name + UpFirst(strings.Replace(pi.DynamicType, "*", "", -1))
  703. return pi
  704. }
  705. func (p *Project) GetPath(m *Method) string {
  706. path := []byte(p.BasePath + m.Path)
  707. for attr, param := range m.Parameters {
  708. path = regexp.MustCompile("{"+attr+"}").ReplaceAll(path, []byte("{"+attr+":"+param.Type+"}"))
  709. }
  710. return string(path)
  711. }
  712. func (p *Project) GetSchema(id string) *Entity {
  713. id = strings.Replace(id, "*", "", -1)
  714. if model, ok := p.SchemasRef[id]; ok {
  715. return model
  716. }
  717. panic(fmt.Sprintf("Entity '%s' not defined!", id))
  718. }
  719. // Metodos das propriedades
  720. func (p *Propertie) FillTags(project *Project, propName string) {
  721. if p.TagVisited {
  722. return
  723. }
  724. if propName == "Id" {
  725. }
  726. if p.Tags != nil {
  727. for k, v := range p.Tags {
  728. if _, found := project.ReplaceWhenEmpty[k]; found && v == "" {
  729. p.Tags[k] = LcFirst(p.ID)
  730. }
  731. if _, found := project.OmitEmpty[k]; found {
  732. if p.Tags[k] != "-" {
  733. p.Tags[k] += ",omitempty"
  734. }
  735. }
  736. }
  737. }
  738. p.TagVisited = true
  739. }
  740. func (p *Propertie) GetType() string {
  741. return strings.Replace(p.Type, "*", "", 1)
  742. }
  743. // Metodos das informacoes da entidade
  744. func (p *EntityInfo) TranslateType(typ string) string {
  745. if typ == p.DynamicTypeId {
  746. return p.DynamicType
  747. }
  748. return typ
  749. }
  750. // Metodos do esquema de relacoes
  751. // Add adiciona uma relação ao esquema
  752. func (s *SchemasRelations) Has(entity string) bool {
  753. // spew.Dump(s)
  754. _, found := s.R[entity]
  755. return found
  756. }
  757. // Add adiciona uma relação ao esquema
  758. func (s *SchemasRelations) Get(entity string) []*Relation {
  759. if e, found := s.R[entity]; found {
  760. return e
  761. }
  762. return []*Relation{}
  763. }
  764. // Add adiciona uma relação ao esquema
  765. func (s *SchemasRelations) Add(r *Relation) {
  766. if _, found := s.R[r.Source]; !found {
  767. s.R[r.Source] = []*Relation{}
  768. }
  769. s.R[r.Source] = append(s.R[r.Source], r)
  770. }
  771. func ParseTemplate(input string, name ...string) (*template.Template, error) {
  772. var tmpl, err = template.New(strings.Join(name, "")).Parse(input)
  773. return tmpl, err
  774. }
  775. func TemplateToString(template *template.Template, data interface{}) (string, error) {
  776. var result bytes.Buffer
  777. if err := template.Execute(&result, data); err != nil {
  778. return "", err
  779. }
  780. return result.String(), nil
  781. }
  782. func NewProject() *Project {
  783. return &Project{
  784. Mode: "",
  785. SchemasRef: map[string]*Entity{},
  786. Icons: map[string]string{},
  787. ReplaceWhenEmpty: map[string]bool{},
  788. OmitEmpty: map[string]bool{},
  789. FormatMap: map[string]string{},
  790. Queries: &QueryDef{},
  791. Schemas: []*Entity{},
  792. Resources: []*Resource{},
  793. Translators: map[string]TranslationFn{},
  794. }
  795. }