src/metadata/GraphDataModel.ps1
# Copyright 2019, 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. ScriptClass GraphDataModel { $SchemaData = $null $methodBindings = $null $typeSchemas = $null $namespace = $null $namespaceAlias = $null $firstNamespaceMatch = $null $secondNamespaceMatch = $null function __initialize($schemaData) { $this.SchemaData = $schemaData $this.namespace = $schemaData.Edmx.DataServices.Schema.Namespace $this.namespaceAlias = if ( $schemaData.Edmx.DataServices.Schema | gm Alias -erroraction ignore ) { $schemaData.Edmx.DataServices.Schema.Alias } # Previously, the "Namespace" attribute of the Schema element was sufficient to determine # the fully qualified names of the types referenced in the rest of the schema. However, on # 2020-01-22, the metadata hosted by the Graph service was changed to include an Alias attribute # that allows use of the alias in a type name as a (typically shorter) synonym for the fully qualified # name of the type. That change regressed this code which was unaware of the "Alias" attribute. # The code below now accounts for it, though there is special handling in other parts of the code # to resolve aliases when resolving type names. # Note that namespace aliases are indeed legal and are documented for OData: # https://www.odata.org/documentation/odata-version-3-0/common-schema-definition-language-csdl/. $this.firstNamespaceMatch = $this.namespace + '.' if ( $this.namespaceAlias ) { if ( $this.namespace.length -gt $this.namespaceAlias.length ) { $this.secondNamespaceMatch = $this.namespaceAlias + '.' } else { $this.firstnamespaceMatch = $this.namespaceAlias + '.' $this.secondNamespaceMatch = $this.namespace + '.' } } } function GetNamespace { $this.SchemaData.Edmx.DataServices.Schema.Namespace } function GetEntityTypeByName($typeName) { __InitializeTypesOnDemand $this.typeSchemas[$typeName] } function GetMethodBindingsForType($typeName) { if ( $this.methodBindings -eq $null ) { $this.methodBindings = @{} $actions = GetActions __AddMethodBindingsFromMethodSchemas $actions $functions = GetFunctions __AddMethodBindingsFromMethodSchemas $functions } $this.methodBindings[$typeName] } function GetEntityTypes { __InitializeTypesOnDemand $this.typeSchemas.values } function GetComplexTypes($typeName) { if ( $typeName ) { $this.SchemaData.Edmx.DataServices.Schema.ComplexType | where Name -eq $typeName } else { $this.SchemaData.Edmx.DataServices.Schema.ComplexType } } function GetEntitySets { $::.ProgressWriter |=> WriteProgress -id 1 -activity "Reading entity sets" $this.SchemaData.Edmx.DataServices.Schema.EntityContainer.EntitySet } function GetSingletons { $::.ProgressWriter |=> WriteProgress -id 1 -activity "Reading singletons" $this.SchemaData.Edmx.DataServices.Schema.EntityContainer.Singleton } function GetActions { $::.ProgressWriter |=> WriteProgress -id 1 "Reading actions" $this.SchemaData.Edmx.DataServices.Schema.Action } function GetFunctions { $::.ProgressWriter |=> WriteProgress -id 1 "Reading functions" $this.SchemaData.Edmx.DataServices.Schema.Function } function UnqualifyTypeName($qualifiedTypeName, $onlyIfQualified) { $unqualified = if ( $qualifiedTypeName.Contains('.') ) { $qualifierLength = if ( $qualifiedTypeName.startswith($this.firstNamespaceMatch) ) { $this.firstNamespaceMatch.length } elseif ( $this.secondNamespaceMatch -and $qualifiedTypeName.startswith($this.secondNamespaceMatch) ) { $this.secondNamespaceMatch.length } if ( $qualifierLength -ne $null ) { $qualifiedTypeName.substring($qualifierLength) } } if ( $unqualified ) { $unqualified } elseif ( ! $onlyIfQualified ) { $qualifiedTypeName } } function UnaliasQualifiedName($name) { $unqualifiedName = UnqualifyTypeName $name $true $this.namespace, $unqualifiedName -join '.' } function __InitializeTypesOnDemand { if ( ! $this.typeSchemas ) { $::.ProgressWriter |=> WriteProgress -id 1 -activity "Reading entity types" $typeSchemas = $this.SchemaData.Edmx.DataServices.Schema.EntityType $this.typeSchemas = @{} $typeSchemas | foreach { $qualifiedName = $this.namespace, $_.name -join '.' $this.typeSchemas.Add($qualifiedName, $_) } $::.ProgressWriter |=> WriteProgress -id 1 -activity "Reading entity types" -completed } } function __AddMethodBindingsFromMethodSchemas($methodSchemas) { $methodSchemas | foreach { $methodSchema = $_; $_.parameter | where name -eq bindingParameter | foreach { (__AddMethodBinding $_.type $methodSchema) } } } function __AddMethodBinding($typeName, $methodSchema) { $unaliasedName = UnaliasQualifiedName $typeName if ( $this.methodBindings[$unaliasedName] -eq $null ) { $this.methodBindings[$unaliasedName] = @() } $this.methodBindings[$unaliasedName] += $methodSchema } } |