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