models.go 28 KB

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