models.go 29 KB

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