src/typesystem/GraphObjectBuilder.ps1
# Copyright 2020, Adam Edwards # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. . (import-script TypeManager) . (import-script TypeDefinition) ScriptClass GraphObjectBuilder { $typeManager = $null $typeDefinition = $null $setDefaultValues = $false $maxLevel = 0 $propertyFilter = $null $currentLevel = 0 function __initialize([PSTypeName('TypeManager')] $typeManager, [PSTypeName('TypeDefinition')] $typeDefinition, $setDefaultValues, $recurse, [string[]] $propertyFilter, [object[]] $valueList, [HashTable[]] $propertyList ) { $this.typeManager = $typeManager $this.typeDefinition = $typeDefinition $this.setDefaultValues = $setDefaultValues -or $valueList -or ! $typeDefinition.IsComposite $values = $valueList $properties = $propertyFilter if ( $propertyList ) { $values = @() $properties = @() foreach ( $table in $propertyList ) { foreach ( $propertyName in $table.keys ) { $properties += $propertyName $values += $table[$propertyName] } } } if ( $properties ) { if ( $valueList -and ( $valueList.length -gt $properties.length ) ) { throw 'Specified list of values has more elements than the specified set of properties' } $this.propertyFilter = @{} for ( $propertyIndex = 0; $propertyIndex -lt $properties.length; $propertyIndex++ ) { $hasValue = $false $value = if ( $values -and ( $propertyIndex -lt $values.length ) ) { $hasValue = $true $values[$propertyIndex] } $this.propertyFilter.Add($properties[$propertyIndex], @{HasValue=$hasValue;Value=$value}) } } $this.maxLevel = if ( $recurse ) { $this.scriptclass.MAX_OBJECT_DEPTH } else { 0 } } function ToObject { $this.currentLevel = 0 GetPropertyValue $this.typeDefinition $false $false $null } function GetPropertyValue($typeDefinition, $isCollection, $useCustomValue, $customValue) { if ( $useCustomValue ) { return $customValue } # For any collection, we simply want to provide an empty array or # other defaul representation of the collection if ( $isCollection ) { if ( $this.setDefaultValues ) { if ( $typeDefinition.DefaultCollectionValue ) { , ( . $typeDefinition.DefaultCollectionValue ) } else { @() } } else { $null } } else { # For non-collections, we want to embed the value directly in # the parent object if ( $typeDefinition.IsComposite ) { NewCompositeValue $typeDefinition } else { NewScalarValue $typeDefinition } } } function NewCompositeValue($typeDefinition) { if ( $this.currentLevel -gt $this.scriptclass.MAX_OBJECT_DEPTH ) { throw "Object depth maximum of '$($this.scriptclass.MAX_OBJECT_DEPTH)' exceeded" } if ( $this.currentLevel -gt $this.maxLevel ) { return $null } try { $this.currentLevel += 1 $object = @{} if ( $typeDefinition.properties ) { foreach ( $property in $typeDefinition.properties ) { $propertyInfo = if ( $this.propertyFilter ) { $this.propertyFilter[$property.name] } if ( ! $this.propertyFilter -or $propertyInfo ) { $propertyTypeDefinition = $this.typeManager |=> FindTypeDefinition Unknown $property.typeId $true if ( ! $propertyTypeDefinition ) { throw "Unable to find type '$($property.typeId)' for property $($property.name) of type $($typeDefinition.typeId)" } $hasValue = $propertyInfo -and $propertyInfo.HasValue $customValue = if ( $hasValue ) { $propertyInfo.Value } $value = GetPropertyValue $propertyTypeDefinition $property.isCollection $hasValue $customValue $object.Add($property.Name, $value) } } } } finally { $this.currentLevel -= 1 } $object } function NewScalarValue($typeDefinition) { if ( $this.setDefaultValues ) { if ( $typeDefinition.DefaultValue -ne $null ) { if ( $typeDefinition.DefaultValue -is [ScriptBlock] ) { . $typeDefinition.DefaultValue } else { $typeDefinition.DefaultValue } } } else { $null } } static { const MAX_OBJECT_DEPTH 64 $maxLevel = 0 } } |