diff --git a/src/main.py b/src/main.py index 40570ed..f4b05be 100644 --- a/src/main.py +++ b/src/main.py @@ -2,6 +2,7 @@ import click from pathlib import Path from json_parser import parse_json +from psm_parser import write_psm from xml_parser import get_xml_data, add_connection, write_xml_data @@ -14,8 +15,9 @@ from xml_parser import get_xml_data, add_connection, write_xml_data def main(json: Path, xml: Path, name: str, description: str, pretty: bool): xml_data = get_xml_data(xml) field_names = parse_json(json) - root = add_connection(xml_data, name, field_names, description=description) + root = add_connection(xml_data, name, field_names, description=description) write_xml_data(root, xml, pretty=pretty) + write_psm(name, field_names) if __name__ == "__main__": diff --git a/src/psm_parser.py b/src/psm_parser.py new file mode 100644 index 0000000..10064d9 --- /dev/null +++ b/src/psm_parser.py @@ -0,0 +1,178 @@ +from pathlib import Path +from datetime import datetime + +from xml_parser import sanitize_name + +get_all_code = """ +function Get-AllCodeServerPages!NAME! { + [CmdletBinding()] + param ( + [Parameter(Mandatory=$true)] + [string]$Resource, + + [Parameter(Mandatory=$true)] + [string]$RootProperty, + + [Parameter(Mandatory=$false)] + [string]$CacheKeyProperty = "conceptCodeId", + + [Parameter(Mandatory=$false)] + [ScriptBlock]$Converter = ${function:ConvertFrom-CodeServerObject!NAME!}, + + + [Parameter(Mandatory=$false)] + [int]$PageSize = 500 + ) + + begin { + if ($null -eq $Global:cache) { + $Global:cache = @{} + } + $cacheKey = $Resource.GetHashCode() + $cache[$cacheKey] = @{} + } + + process { + $currentPage = 0; + $Global:debugOut = @() + while ($null -eq $data.totalPages -or $currentPage -lt $data.totalPages) { + $uri = "{0}?pageSize={1}&page={2}" -f $Resource, $PageSize, ++$currentPage + $data = Invoke-RestMethod -Uri $uri + + write-debug $uri + if ($null -eq $data.totalPages) { + throw "Did not get totalPages, abort!" + } else { + $Global:debugOut += $data.conceptCodes + if ($null -ne $Converter) { + foreach ($codeObject in $data.$RootProperty) { + $convertedObject = Invoke-Command -ScriptBlock $Converter -ArgumentList (,$codeObject) + $Global:cache[$cacheKey].Add($convertedObject.$CacheKeyProperty, $convertedObject) + } + } else { + foreach ($codeObject in $data.$RootProperty) { + $key = ($objAttributes | Where-Object {$_.attributeName -eq $CacheKeyProperty}).attributeValue + $Global:cache[$cacheKey].Add($key, $codeObject.attributes) + } + } + + } + } + + write-output $cache[$cacheKey].Values + + } + + end { + + } +} +""" + +get_code = """ +function Get-CodeServerObject!NAME! { + [CmdletBinding()] + param ( + [Parameter(Mandatory=$true)] + [string]$conceptCodeId, + + [Parameter(Mandatory=$true)] + [string]$Resource, + + [Parameter(Mandatory=$true)] + [string]$RootProperty, + + [Parameter(Mandatory=$false)] + [string]$CacheKeyProperty = "conceptCodeId" + ) + + begin { + + if ($null -eq $Global:cache) { + $params = @{ + Resource = $Resource; + RootProperty = $RootProperty; + } + + if ($PSBoundParameters.ContainsKey("CacheKeyProperty")) { + $params.Add("CacheKeyProperty", $CacheKeyProperty) + } + + [void](Get-AllCodeServerPagesRoles @params) + } + + $cacheKey = $Resource.GetHashCode() + } + + process { + Write-Debug $cacheKey + Write-Output $cache[$cacheKey][$conceptCodeId] + } + + end { + + } +} +""" + +convert_from = """ +Function ConvertFrom-CodeServerObject!NAME!([PSCustomObject[]]$codeServerObject!NAME!) { + $map = @{ +!MAPS! + } + + if ($null -eq $codeServerObject!NAME!) { + return + } + + $obj = New-Object CodeServer!NAME! -ArgumentList $codeServerObject!NAME! + $Global:meDebug = $codeServerObject!NAME! + + write-output $obj +} +""" + +class_definition = """ +class CodeServer!NAME! { + CodeServer!NAME!() {} + + CodeServer!NAME!([psobject]$source) { + $dic = @{} + $source.attributes | foreach-object {$dic.Add($_.attributeName, $_.attributevalue)} + + $this.{conceptCodeId} = $source.conceptCodeId +!VARIABLES! + + } + +!STRINGS! + +} + +Export-ModuleMember ConvertFrom-CodeServerObject!NAME! +Export-AllCodeServerPages!NAME! +Export-CodeServerObject!NAME! +""" + +def define_maps(items: list[str]) -> str: + return "\n".join([f"\t'{sanitize_name(item)}' = '{item}'" for item in items]) + +def define_variables(items: list[str]) -> str: + return "\n".join([f"\t$this.{{{sanitize_name(item)}}} = $dic['{item}']" for item in items]) + +def define_strings(items: list[str]) -> str: + return "\n".join(["\t" + "[string]$" + "{" + sanitize_name(item) + "}" for item in items]) + +def write_psm(name, items: list[str], filename: Path = Path("Connector.psm1")) -> str: + from rich import print + + if filename.exists(): + filename.rename(str(filename) + f".{datetime.now().strftime('%Y-%m-%d.%H%M%S')}.bak") + output = get_all_code.replace("!NAME!", name) + output += get_code.replace("!NAME!", name) + output += convert_from.replace("!NAME!", name).replace("!MAPS!", define_maps(items)) + output += class_definition.replace("!NAME!", name).replace("!VARIABLES!", define_variables(items)).replace("!STRINGS!", define_strings(items)) + with open(filename, "w") as f: + f.write(output) + print(output) + pass \ No newline at end of file diff --git a/src/xml_parser.py b/src/xml_parser.py index cba352b..43d8b9b 100644 --- a/src/xml_parser.py +++ b/src/xml_parser.py @@ -13,7 +13,7 @@ def write_xml_data(root: ET.Element, file_path: Path, pretty: bool = True) -> No xml_str = ET.tostring(root, encoding="utf-8", xml_declaration=True, pretty_print=pretty) file_path.write_bytes(xml_str) -def _sanitize_name(name: str) -> str: +def sanitize_name(name: str) -> str: """ Sanitize a name by removing all non-letter characters except hyphens and Scandinavian letters. """ @@ -61,10 +61,10 @@ def add_connection(root: ET.Element, name: str, attr_list: list[str], descriptio ET.SubElement(mapping, "Map", ToCommand=f"Get-CodeServerPages{name}", Parameter="conceptCodeId") for attr in attr_list: - property = ET.SubElement(properties, "Property", Name=_sanitize_name(attr), DataType="String", IsMultivalue="false", IsAutoFill="false") + property = ET.SubElement(properties, "Property", Name=sanitize_name(attr), DataType="String", IsMultivalue="false", IsAutoFill="false") return_binding = ET.SubElement(property, "ReturnBinding") - ET.SubElement(return_binding, "Bind", CommandResultOf=f"Get-AllCodeServerPages{name}", Path=_sanitize_name(attr)) - ET.SubElement(return_binding, "Bind", CommandResultOf=f"Get-CodeServerPage{name}", Path=_sanitize_name(attr)) + ET.SubElement(return_binding, "Bind", CommandResultOf=f"Get-AllCodeServerPages{name}", Path=sanitize_name(attr)) + ET.SubElement(return_binding, "Bind", CommandResultOf=f"Get-CodeServerPage{name}", Path=sanitize_name(attr)) read_configuration = ET.SubElement(new_class, "ReadConfiguration") listing_command = ET.SubElement(read_configuration, "ListingCommand", Command=f"Get-AllCodeServerPages{name}")