PageRenderTime 38ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/tools/Scaffolders/Model/ModelScaffolding.Model.ps1

#
Powershell | 208 lines | 183 code | 18 blank | 7 comment | 32 complexity | 3b8ca73b2a7b1117edb1c8492f3621c3 MD5 | raw file
  1. [T4Scaffolding.Scaffolder(Description = "Creates model with properties (and optional controller). You can specify property types or can use conventions.")][CmdletBinding()]
  2. param(
  3. [parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)][string]$Model,
  4. [string[]]$Properties,
  5. [string]$Folder,
  6. [string]$DbContextType,
  7. [string]$Area,
  8. [string]$Layout,
  9. [string]$Project,
  10. [string]$CodeLanguage,
  11. [string[]]$TemplateFolders,
  12. [switch]$Force = $false,
  13. [switch]$NoAnnotations = $false,
  14. [switch]$Controller = $false,
  15. [switch]$Repository = $false,
  16. [switch]$NoChildItems = $false,
  17. [switch]$NoTypeWarning = $false,
  18. [switch]$ReferenceScriptLibraries = $false
  19. )
  20. # Parses names like Name[99]? to {Name="Name"; MaxLength=99; Required=$false}
  21. function ParseName([string]$name) {
  22. $result = @{Name = $name; MaxLength = 0; Required = $true; Type = ""; Reference=""}
  23. # parse reference if any
  24. if ($result.Name.EndsWith("+")) {
  25. $result.Name = $result.Name.Substring(0, $result.Name.Length - 1)
  26. $result.Reference = "!";
  27. Write-Verbose "Found reference switch for $name"
  28. }
  29. # parse nullable if any
  30. if ($result.Name.EndsWith("?")) {
  31. $result.Name = $result.Name.Substring(0, $result.Name.Length - 1)
  32. $result.Required = $false;
  33. Write-Verbose "Found nullable switch for $name"
  34. }
  35. [int]$start = 0
  36. # parse length if any
  37. if ($result.Name.EndsWith("]")) {
  38. $start = $result.Name.IndexOf("[")
  39. if ($start -gt 0) {
  40. $lengthPart = $result.Name.Substring($start + 1, $result.Name.Length - $start - 2)
  41. $result.MaxLength = [System.Convert]::ToInt32($lengthPart)
  42. $result.Name = $result.Name.Substring(0, $start)
  43. Write-Verbose "Found max length for $name"
  44. }
  45. }
  46. # parse type if any
  47. $start = $result.Name.IndexOf(":")
  48. if ($start -gt 0) {
  49. $result.Type = $result.Name.Substring($start + 1, $result.Name.Length - $start - 1)
  50. $result.Name = $result.Name.Substring(0, $start)
  51. }
  52. if ($result.Reference) {
  53. if ($result.Name -imatch '^.*id$') {
  54. $result.Reference = $result.Name.Substring(0, $result.Name.Length-2)
  55. if ($result.Reference.EndsWith("_")) {
  56. $result.Reference = $result.Name.Substring(0, $result.Name.Length-1)
  57. }
  58. }
  59. else {
  60. $result.Reference = ""
  61. Write-Warning "Cannot extract reference property for $name"
  62. }
  63. }
  64. ($result)
  65. }
  66. if (!$Folder) {
  67. $modelsFolder = Get-ProjectFolder "Models" -Create
  68. if ($modelsFolder) {
  69. $Folder = "Models"
  70. Write-Verbose "Models folder used by default"
  71. }
  72. }
  73. $patterns = @()
  74. $defaultProperties = @()
  75. $defaultProjectLanguage = Get-ProjectLanguage
  76. # TODO: in future try to cache and not use arrays but something else, because we can have many patterns (check real performance)
  77. try {
  78. $patternsFile = "TypePatterns." + $defaultProjectLanguage + ".t4"
  79. $patternsPath = Join-Path $TemplateFolders[0] $patternsFile
  80. Write-Verbose "Trying to process $patternsFile ..."
  81. Get-Content $patternsPath | Foreach-Object {
  82. $items = $_.Split(' ')
  83. $type = $items[0]
  84. if ($type -eq "default") {
  85. Write-Verbose "Processing default properties: $_"
  86. if ($items.Length -gt 1) {
  87. for ($i = 1; $i -lt $items.Length; $i++) {
  88. $defaultProperties += $items[$i]
  89. }
  90. }
  91. }
  92. else {
  93. Write-Verbose "Processing pattern type: $type"
  94. $typeInfo = ParseName($type)
  95. if ($items.Length -gt 1) {
  96. for ($i = 1; $i -lt $items.Length; $i++) {
  97. $patterns += @{ Type = $typeInfo.Name; Pattern = '^' + $items[$i] + '$'; MaxLength = $typeInfo.MaxLength; Reference = $typeInfo.Reference }
  98. # Write-Verbose " Processed pattern: $($items[$i])"
  99. }
  100. }
  101. }
  102. }
  103. Write-Verbose "$patternsFile processed"
  104. }
  105. catch { Write-Warning "Type patterns was not loaded: $($_.Exception.Message)" }
  106. if ($defaultProperties.Length -eq 0) {
  107. $defaultProperties = @("Id", "Name")
  108. }
  109. $defaultSpace = (Get-Project $Project).Properties.Item("DefaultNamespace").Value
  110. if ($Properties -eq $null) {
  111. $Properties = $defaultProperties
  112. }
  113. if (!$Folder) {
  114. $outputPath = $Model
  115. $space = $defaultSpace
  116. }
  117. else {
  118. $outputPath = Join-Path $Folder $Model
  119. $space = $defaultSpace + "." + $Folder.Replace("\", ".")
  120. }
  121. $props = @()
  122. [int]$typedCount = 0
  123. foreach ($property in $Properties) {
  124. $nameInfo = ParseName($property)
  125. $type = $nameInfo.Type
  126. # try to find some attributes from TypePatterns
  127. if ($type.Length -eq 0) {
  128. for ($i = 0; $i -lt $patterns.Length; $i++) {
  129. $p = $patterns[$i]
  130. if ($nameInfo.Name -cmatch $p.Pattern) {
  131. $type = $p.Type
  132. if ($nameInfo.MaxLength -eq 0 ) { $nameInfo.MaxLength = $p.MaxLength }
  133. if (!$nameInfo.Reference) { $nameInfo.Reference = $p.Reference }
  134. break
  135. }
  136. }
  137. }
  138. else {
  139. $typedCount++
  140. }
  141. if (!$type) { $type = "string" }
  142. # create reference class if not any
  143. $referenceType = ""
  144. if ($nameInfo.Reference) {
  145. $reference = Get-ProjectType $nameInfo.Reference 2>null
  146. if (!$reference) {
  147. $idType = $nameInfo.Type.ToLower()
  148. $newModel = $nameInfo.Reference
  149. Write-Host "Scaffolding new model $newModel"
  150. Scaffold ModelScaffolding.Model -Model $newModel Id:$idType,Name -Folder $Folder -Project $Project -CodeLanguage $CodeLanguage `
  151. -Controller:$Controller -Force:$Force -NoAnnotations:$NoAnnotations -NoTypeWarning `
  152. -DbContextType $DbContextType -Repository:$Repository -Area $Area -Layout $Layout -NoChildItems:$NoChildItems -ReferenceScriptLibraries:$ReferenceScriptLibraries
  153. $referenceType = $space + "." + $nameInfo.Reference
  154. }
  155. else {
  156. $refNamespace = $reference.Namespace.Name
  157. if ($space -ne $refNamespace -and !$space.StartsWith($refNamespace + ".")) {
  158. if ($refNamespace.StartsWith($space + ".")) {
  159. $refNamespace = $refNamespace.Substring($space.Length + 1)
  160. }
  161. $referenceType = $refNamespace + "." + $reference.Name
  162. }
  163. }
  164. }
  165. # add processed property
  166. $props += @{Name = $nameInfo.Name; Type = $type; MaxLength = $nameInfo.MaxLength; Required = $nameInfo.Required; Reference = $nameInfo.Reference; ReferenceType = $referenceType}
  167. }
  168. if ($typedCount -gt 0 -and $typedCount -lt $Properties.Length -and !$NoTypeWarning) {
  169. Write-Warning "Types were not specified for all properties. Types for such properties were assigned automatically."
  170. }
  171. Add-ProjectItemViaTemplate $outputPath -Template TypeTemplate `
  172. -Model @{ Namespace = $space; TypeName = $Model; Properties = $props; Annotations = !$NoAnnotations } `
  173. -SuccessMessage "Added $Model at {0}" `
  174. -TemplateFolders $TemplateFolders -Project $Project -CodeLanguage $CodeLanguage -Force:$Force
  175. if ($Controller) {
  176. $controllerName = Get-PluralizedWord $Model
  177. Scaffold Controller -ControllerName $controllerName -ModelType $Model -Project $Project -CodeLanguage $CodeLanguage `
  178. -Force:$Force -DbContextType $DbContextType -Repository:$Repository -Area $Area -Layout $Layout -NoChildItems:$NoChildItems -ReferenceScriptLibraries:$ReferenceScriptLibraries
  179. }