InteractiveApi.psm1

function Get-ValidMethods {
    if ($methods) {
        $method_names = foreach ($m in $methods) {
            $m.name
        }
        return $method_names
    }
    else {
        $global:proxy = New-WebServiceProxy -Uri "http://api.jumpforward.com/webapi/services.asmx?wsdl" -Namespace X
        $global:methods = $proxy | Get-Member -Type Method | Where-Object { $_.Definition -like "X.*" -and $_.Name -notlike "End*" }
        $method_names = foreach ($m in $methods) {
            $m.name
        }
        return $method_names
    }
}

<#
.SYNOPSIS
    Interactive SOAP request wrapper
.DESCRIPTION
    Creates a SOAP API proxy object and allows dynamic interaction with the required parameters for the request, as well as listing the
    fields any specified request.
.PARAMETER Method
    Specify the API call to make. Press tab to autocomplete the command name, pressing tab will continue to loop through all possible API calls.
.PARAMETER AccessKey
    The API key generated for your institution by JumpForward.
.PARAMETER EntryCount
    Specify the number of subentries you want to generate for the API call.
.PARAMETER Uri
    Defaults to the JumpForward API endpoint, but can be changed if you need to explore an alternate SOAP API with a WSDL URI.
.PARAMETER Specifications
    Add this parameter to list out the fields required for an API call rather than actually sending the request.
.EXAMPLE
    PS C:\>New-SoapRequest -Method AddCollege -Specifications
    Writes a list of all possible fields allowed on the API call.
.EXAMPLE
    PS C:\>New-SoapRequest -Method GetCollegeDepartmentCourses -AccessKey "aaabbbccc111222333" -EntryCount 4
    Returns a result object with the department courses listed for the four colleges after prompting for the field information to send with the request.
#>

function New-SoapRequest {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, Position = 0)]
        [ArgumentCompleter(
            {
                param($Command, $Parameter, $WordToComplete, $CommandAst, $FakeBoundParams)
                Get-ValidMethods
            }
        )]
        [ValidateScript( { $_ -in (Get-ValidMethods) })]
        [String]
        $Method,
        [Parameter(Mandatory = $true)]
        [String]
        $AccessKey,
        [Int]
        $EntryCount = 1,
        $Uri = "http://api.jumpforward.com/webapi/services.asmx?wsdl",
        [Switch]
        $Specifications,
        [array]
        $Data=$false
    )
    $entry = $proxy.$Method.OverloadDefinitions.split('(')[1].split(' ')[0]
    
    function Format-APICall ($object, $entry=$false, $bulk=$false) {
        foreach ($p in $object.PSObject.Properties) {
            $name = $p.name
            if ($p.TypeNameOfValue -like "X.*") {
                $subentry = ($p.TypeNameOfValue | Select-String -Pattern "^X" | Select-Object -ExpandProperty Line).split('[')[0]
                # Add as many sub entry objects as were specified
                if ($bulk){
                    foreach ($row in $Data){
                        $p.value += Format-APICall -object (New-Object ($subentry)) -entry $row
                    }
                }
                else{
                    for ($i = 0; $i -lt $EntryCount; $i++) {
                        $p.value += Format-APICall -object (New-Object ($subentry))
                    }
                }
            }
            elseif ($p.name -eq "accessKey") {
                $p.value = $AccessKey
            }
            else {
                if($entry){
                    $input = $entry.$name
                }
                else{
                    $input = Read-Host -Prompt "Enter value for $name"
                }
                if ($input.length -gt 0) {
                    $p.Value = $input
                }
            }
        }
        return $object
    }
    function Get-APIRequirement ($object) {
        foreach ($p in $object.PSObject.Properties) {
            if ($p.TypeNameOfValue -like "X.*") {
                $name = $object.getType().name
                Write-Host "`n$name"
                $subentry = ($p.TypeNameOfValue | Select-String -Pattern "^X" | Select-Object -ExpandProperty Line).split('[')[0]
                Get-APIRequirement -object (New-Object ($subentry))
            }
            elseif ($p.name -eq "accessKey") {
                $p.value = $AccessKey
            }
            else {
                Write-Host "Field: $($p.name)"
            }
        }
        return $object
    }
    if ($Specifications) {
        $object = Get-APIRequirement -object (new-object ($entry))
    }
    else {
        $object = Format-APICall -object (new-object ($entry)) -bulk [boolean]$Data
        $proxy.$Method($object)
    }
}