Public/DataFlow/Get-JIMDataFlow.ps1
|
# Copyright (c) Tetron Limited. All rights reserved. # Licensed under the Tetron Commercial License. See LICENSE file in the project root. function Get-JIMDataFlow { <# .SYNOPSIS Gets attribute data flows from JIM. .DESCRIPTION Retrieves a system-wide map of every attribute data flow, in both directions: what contributes each Metaverse Attribute, and what each Connected System attribute is written from. One flow per Synchronisation Rule Attribute Flow mapping. An Import flow reads Connected System attributes and writes a single Metaverse Attribute, so it carries a priority and a "Null is a value" flag. An Export flow reads Metaverse Attributes and writes a single Connected System attribute, so it carries the owning rule's Enforce State. The properties that do not apply to a flow's direction are null rather than defaulted, so you never have to guess which are meaningful. Import flows also carry contributorCount: how many flows contribute to the same Metaverse Attribute, counted across the whole configuration rather than the filtered results, so filtering to one Connected System does not make a shared attribute look like a sole contributor. The filters combine with AND. -SyncRuleName narrows whatever the other filters left, so removing it returns those results. .PARAMETER Direction Filter flows by direction: Import for flows into the Metaverse, Export for flows out of it. .PARAMETER ConnectedSystemId Filter flows by Connected System ID. .PARAMETER ConnectedSystemName Filter flows by Connected System name. Must be an exact match. .PARAMETER InputObject A Connected System object from the pipeline (e.g. from Get-JIMConnectedSystem). Its Id is used to filter flows, equivalent to specifying -ConnectedSystemId directly. .PARAMETER MetaverseObjectTypeId Filter flows by the Metaverse Object Type they apply to. .PARAMETER ConnectedSystemObjectTypeId Filter flows by the Connected System Object Type they apply to. .PARAMETER MetaverseAttributeId Filter flows that read or write this Metaverse Attribute, whichever side it sits on for the direction in question. A flow whose Metaverse side is an expression cannot match: an expression's attribute references live in its text and are not modelled. Use -Search to find those. .PARAMETER ConnectedSystemAttributeId Filter flows that read or write this Connected System attribute, whichever side it sits on for the direction in question. Subject to the same expression limitation as -MetaverseAttributeId. .PARAMETER MultipleContributorsOnly Return only Import flows whose target Metaverse Attribute has more than one contributor, which are the only flows whose priority order decides anything. .PARAMETER Search Free-text term matched case-insensitively against the Synchronisation Rule, the Connected System, both object types, every attribute named on either side, and any expression text. .PARAMETER SyncRuleName Filter flows by the name of the owning Synchronisation Rule. Supports wildcards (e.g. "HR*"). Evaluated client-side. .OUTPUTS PSCustomObject representing attribute data flow(s). .EXAMPLE Get-JIMDataFlow Gets every attribute data flow, in both directions. .EXAMPLE Get-JIMDataFlow -Direction Import -MultipleContributorsOnly Gets the inbound flows whose target Metaverse Attribute has more than one contributor: the attributes whose priority order decides which value wins. .EXAMPLE Get-JIMDataFlow -Search 'department' Answers "what touches department?" across both directions, including any expression that mentions it. .EXAMPLE Get-JIMDataFlow -ConnectedSystemName 'Contoso AD' -Direction Export Answers "what does JIM write to Contoso AD, and from where?". .EXAMPLE Get-JIMDataFlow -Direction Import | Where-Object { $_.nullIsValue } | Select-Object targetMetaverseAttributeName, syncRuleName, priority Lists every contribution that asserts an authoritative "no value", which is the setting most worth reviewing deliberately. .EXAMPLE Get-JIMConnectedSystem -Name "HR*" | Get-JIMDataFlow Gets the flows for Connected Systems with names starting with "HR". .LINK Get-JIMSyncRule Get-JIMSyncRuleMapping Get-JIMMetaverseAttributePriority #> [CmdletBinding(DefaultParameterSetName = 'List')] [OutputType([PSCustomObject])] param( [Parameter(ParameterSetName = 'List')] [Parameter(ParameterSetName = 'ByConnectedSystemName')] [ValidateSet('Import', 'Export')] [string]$Direction, [Parameter(ParameterSetName = 'List', ValueFromPipelineByPropertyName)] [int]$ConnectedSystemId, [Parameter(Mandatory, ParameterSetName = 'ByConnectedSystemName')] [string]$ConnectedSystemName, # A Connected System object (e.g. from Get-JIMConnectedSystem) exposes Id, not # ConnectedSystemId, so it cannot bind to -ConnectedSystemId by property name. Binding the # whole object here and reading its Id below is the fix, the same shape and reasoning as # Get-JIMSyncRule. [Parameter(ParameterSetName = 'List', ValueFromPipeline)] [PSCustomObject]$InputObject, [Parameter(ParameterSetName = 'List')] [Parameter(ParameterSetName = 'ByConnectedSystemName')] [int]$MetaverseObjectTypeId, [Parameter(ParameterSetName = 'List')] [Parameter(ParameterSetName = 'ByConnectedSystemName')] [int]$ConnectedSystemObjectTypeId, [Parameter(ParameterSetName = 'List')] [Parameter(ParameterSetName = 'ByConnectedSystemName')] [int]$MetaverseAttributeId, [Parameter(ParameterSetName = 'List')] [Parameter(ParameterSetName = 'ByConnectedSystemName')] [int]$ConnectedSystemAttributeId, [Parameter(ParameterSetName = 'List')] [Parameter(ParameterSetName = 'ByConnectedSystemName')] [switch]$MultipleContributorsOnly, [Parameter(ParameterSetName = 'List')] [Parameter(ParameterSetName = 'ByConnectedSystemName')] [string]$Search, [Parameter(ParameterSetName = 'List')] [Parameter(ParameterSetName = 'ByConnectedSystemName')] [SupportsWildcards()] [string]$SyncRuleName ) process { # Check connection first if (-not $script:JIMConnection) { Write-Error "You are not connected to JIM. Run Connect-JIM -Url <your JIM URL> to authenticate, then try again." return } # Resolve ConnectedSystemName to ConnectedSystemId if specified if ($PSBoundParameters.ContainsKey('ConnectedSystemName')) { $connectedSystem = Resolve-JIMConnectedSystem -Name $ConnectedSystemName $ConnectedSystemId = $connectedSystem.id } # -ConnectedSystemId (direct or bound by property name) takes precedence; otherwise fall # back to the piped Connected System object's Id (see -InputObject above). $filterByConnectedSystem = $ConnectedSystemId -gt 0 if (-not $filterByConnectedSystem -and $InputObject -and $InputObject.PSObject.Properties['Id']) { $ConnectedSystemId = [int]$InputObject.Id $filterByConnectedSystem = $ConnectedSystemId -gt 0 } # The filters are evaluated by the API, so this cmdlet and the portal's Data Flow page return # the same flows for the same filters. -SyncRuleName stays client-side because it supports # PowerShell wildcards. $baseQueryParams = @('pageSize=100') if ($Direction) { $baseQueryParams += "direction=$Direction" } if ($filterByConnectedSystem) { $baseQueryParams += "connectedSystemId=$ConnectedSystemId" } if ($MetaverseObjectTypeId -gt 0) { $baseQueryParams += "metaverseObjectTypeId=$MetaverseObjectTypeId" } if ($ConnectedSystemObjectTypeId -gt 0) { $baseQueryParams += "connectedSystemObjectTypeId=$ConnectedSystemObjectTypeId" } if ($MetaverseAttributeId -gt 0) { $baseQueryParams += "metaverseAttributeId=$MetaverseAttributeId" } if ($ConnectedSystemAttributeId -gt 0) { $baseQueryParams += "connectedSystemAttributeId=$ConnectedSystemAttributeId" } if ($MultipleContributorsOnly) { $baseQueryParams += 'multipleContributorsOnly=true' } if ($Search) { $baseQueryParams += "search=$([System.Uri]::EscapeDataString($Search))" } Write-Verbose "Getting attribute data flows" # Page through the whole result set. Data flows are configuration rather than object data, so # the set is small, but stopping at the first page would silently truncate the map and make # the filters look as though they had excluded flows they did not. $currentPage = 1 $pagesFetched = 0 do { $queryString = (@("page=$currentPage") + $baseQueryParams) -join '&' $response = Invoke-JIMApi -Endpoint "/api/v1/synchronisation/data-flows?$queryString" $pagesFetched++ # Handle paginated response - check if 'items' property exists (not if it's truthy) $flows = if ($null -ne $response.items) { $response.items } else { $response } # Output each flow individually for pipeline support foreach ($flow in $flows) { if (-not $SyncRuleName -or $flow.syncRuleName -like $SyncRuleName) { $flow } } $hasMore = $response.hasNextPage -eq $true if ($hasMore -and $pagesFetched -ge $script:JIMMaxAllPages) { Write-Warning "Get-JIMDataFlow stopped after $script:JIMMaxAllPages pages; more results remain (total pages: $($response.totalPages)). Narrow the query with -Direction, -ConnectedSystemId, -MetaverseObjectTypeId or -Search." break } if ($hasMore) { $currentPage++ Write-Verbose "Fetching page $currentPage of $($response.totalPages)..." } } while ($hasMore) } } |