:green_heart: Fix section tests.

:green_heart: Fix section tests.

import module namespace response = "http://www.28msec.com/modules/http-response";
import module namespace test = "http://apps.28.io/test";
import module namespace config = "http://apps.28.io/config";
import module namespace backend = "http://apps.28.io/backend";

declare variable $local:expected as object :=
    {
      "byconcept" : [ "1001000 - Statement - Consolidated Statements Of Operations", "1002000 - Statement - Consolidated Statements of Comprehensive Income", "1004000 - Statement - Consolidated Statements Of Cash Flows", "2401402 - Disclosure - Summary Of Business Segment Data (Details)", "2405403 - Disclosure - Earnings Per Share (Schedule Of Weighted-Average Number Of Shares Outstanding Used To Compute Earnings Per Share) (Details)", "2424403 - Disclosure - Quarterly Financial Data (Schedule Of Quarterly Financial Data) (Details)", "1002000 - Statement - Consolidated Statements of Income", "1003000 - Statement - Consolidated Statements of Comprehensive Income", "1005000 - Statement - Consolidated Statements of Changes in Stockholders' Equity", "1006000 - Statement - Consolidated Statements of Cash Flows", "2429403 - Disclosure - Earnings Per Share (Details)", "2438402 - Disclosure - International Operations (Details)", "2440402 - Disclosure - Parent Company - Statements of Income (Details)", "2440404 - Disclosure - Parent Company - Statements of Cash Flows (Details2)", "1001000 - Statement - CONSOLIDATED STATEMENTS OF INCOME", "1005000 - Statement - CONSOLIDATED STATEMENTS OF SHAREOWNERS' EQUITY", "1001000 - Statement - Consolidated Income Statements", "000100 - Statement - Consolidated Statement Of Income", "041101 - Disclosure - Earnings Per Share (Details)", "041702 - Disclosure - Disclosures About Segments And Related Information (Schedule Of Segments And Related Information) (Details)", "100020 - Statement - Statement of Earnings", "100030 - Statement - Statement of Comprehensive Income", "100040 - Statement - Statement of Changes in Shareowners' Equity", "100060 - Statement - Statement of Cash Flows", "401500 - Disclosure - Shareowners' Equity (Details)", "402800 - Disclosure - Quarterly Information (unaudited) (Details)", "1001000 - Statement - Consolidated Statements of Income", "1004000 - Statement - Consolidated Statements of Cash Flows", "1005000 - Statement - Consolidated Statements of Stockholders' Equity", "1001000 - Statement - Consolidated Statement of Income", "1002000 - Statement - Consolidated Statement of Comprehensive Income", "1004000 - Statement - Consolidated Statement of Cash Flows", "1005000 - Statement - Consolidated Statement of Shareholders Equity", "2414402 - Disclosure - Quarterly Results (Detail)", "1001000 - Statement - CONSOLIDATED STATEMENTS OF EARNINGS", "2418402 - Disclosure - EARNINGS PER SHARE (DETAILS)", "2447402 - Disclosure - QUARTERLY RESULTS (UNAUDITED) (DETAILS)", "1005000 - Statement - Consolidated Statement of Equity", "2404402 - Disclosure - Summarized Financial Data - Chevron U.S.A. Inc. (Details)", "2405402 - Disclosure - Summarized Financial Data - Chevron Transport Corporation (Details)", "2410402 - Disclosure - Operating Segments and Geographic Data (Details)", "2427402 - Disclosure - Earnings Per Share (Details)", "1001000 - Statement - Consolidated Statement of Operations", "2404402 - Disclosure - Earnings Per Share (Details)", "2410403 - Disclosure - Equity (Changes in Noncontrolling Interests) (Details)", "2420404 - Disclosure - Segment Financial Data (Selected Quarterly Financial Data) (Details)", "2421402 - Disclosure - Selected Quarterly Financial Data - Unaudited (Details)", "1001000 - Statement - Consolidated Statements Of Income (Audited)", "1002000 - Statement - Consolidated Statements Of Comprehensive Income (Audited)", "2415402 - Disclosure - Quarterly Financial Data (Unaudited) (Quarterly Financial Data) (Details)", "1002000 - Statement - Consolidated Statements of Earnings", "1004000 - Statement - Consolidated Statements of Equity", "2419402 - Disclosure - Selected Quarterly Financial Data (Unaudited) (Details)", "1004000 - Statement - Consolidated Statement of Equity", "2420402 - Disclosure - Earnings Per Share - Calculations of Earnings Per Share (Detail)", "1001000 - Statement - Consolidated Statements Of Income", "1005000 - Statement - Consolidated Statements of Shareholders' Equity", "1002000 - Statement - Consolidated Statements Of Earnings", "1004000 - Statement - Consolidated Statements of Stockholders' Equity", "1005000 - Statement - Consolidated Statements Of Cash Flows", "2415402 - Disclosure - Quarterly Financial Data (Unaudited) (Details)", "1003000 - Statement - Consolidated Statements of Operations", "1005000 - Statement - Consolidated Statements of Changes in Shareholders' Equity", "2429403 - Disclosure - Quarterly Financial Data Quarterly Financial Data (Unaudited) (Details)", "2430405 - Disclosure - Schedule I Condensed Income Statement (Details)", "000100 - Statement - Consolidated Statements Of Income", "000400 - Statement - Consolidated Statements Of Changes In Stockholders' Equity", "041801 - Disclosure - Quarterly Financial Information (Unaudited) (Quarterly Financial Results) (Details)", "1003000 - Statement - Consolidated Statements Of Operations", "1004000 - Statement - Consolidated Statements of Comprehensive Income", "1006000 - Statement - Consolidated Statements Of Equity", "2420402 - Disclosure - Net Income per Share (Calculation Of Basic And Diluted Net Income Per Share) (Detail)", "2475402 - Disclosure - Quarterly Financial Summary (Detail)", "000011 - Statement - Consolidated Statement of Income", "004010 - Disclosure - Significant Accounting Policies (Details)", "004170 - Disclosure - Quarterly Data (Unaudited) (Details)", "1003 - Statement - Income Statements", "1004 - Statement - Comprehensive Income Statements", "1008 - Statement - Cash Flows Statements", "1009 - Statement - Stockholders' Equity Statements", "1055 - Disclosure - Basic and Diluted Earnings Per Share (Detail)", "1121 - Disclosure - Quarterly Information (Unaudited) (Detail)", "010020 - Statement - Consolidated Statements of Income", "010035 - Statement - Consolidated Statements of Comprehensive Income", "010060 - Statement - Consolidated Statements of Cash Flows", "010080 - Statement - Consolidated Statements of Shareholders' Equity", "042600 - Disclosure - Parent Company (Details)", "042620 - Disclosure - Parent Company (Details 2)", "042700 - Disclosure - Quarterly Financial Data (Unaudited) (Details)", "1003 - Statement - Consolidated Statements of Income", "1008 - Statement - Consolidated Statements of Changes in Equity", "1118 - Disclosure - Schedule of Quarterly Financial Information (Detail)", "0110 - Statement - Consolidated Statements of Earnings", "0120 - Statement - Consolidated Statements of Comprehensive Income", "0140 - Statement - Consolidated Statements of Changes in Shareholders' Equity", "0150 - Statement - Consolidated Statements of Cash Flows", "0625 - Disclosure - Business Segments (Details)", "0630 - Disclosure - Parent Company (Details)", "06302 - Disclosure - Parent Company (Details 2)", "1002000 - Statement - CONSOLIDATED STATEMENTS OF OPERATIONS", "1004000 - Statement - CONSOLIDATED STATEMENTS OF CHANGES IN EQUITY", "2436402 - Disclosure - Basic and Diluted Earnings Per Share (Detail)" ]
    };

declare %an:nondeterministic function local:test-sections($expected as integer, $params as object) as item
{
    let $endpoint := "sections"
    let $request := test:invoke($endpoint, $params)
    let $actual as integer := count($request[2].Sections[])
    let $status as integer := $request[1]
    return test:assert-eq($expected, $actual, $status, test:url($endpoint, $params))
};

declare %an:sequential function local:test-sections-result($expected as array, $params as object) as item
{
    let $endpoint := "sections"
    let $request := test:invoke($endpoint, $params)
    let $actual as array := [ distinct-values($request[2].Sections[].Section) ]
    let $status as integer := $request[1]
    return test:assert-eq-array($expected, $actual, $status, test:url($endpoint, $params))
};

declare %an:nondeterministic function local:test-generic-components($expected as integer, $params as object) as item
{
    let $endpoint := "sections"
    let $request := test:invoke($endpoint, $params)
    let $actual as integer := count($request[2].Sections[])
    let $status as integer := $request[1]
    return test:assert-eq($expected, $actual, $status, test:url($endpoint, $params))
};

declare %an:sequential function local:check($o as object) as object
{
    if (not(every $k in (keys($o) ! $o.$$) satisfies ($k instance of boolean and $k)))
    then {
            response:status-code(500);
            $o
    } else
            $o
};

local:check({
    cocacola: local:test-sections(94, {
        ticker:"ko",
        fiscalYear: "2013",
        fiscalPeriod: "FY"
    }),
    cocacola-implied: local:test-sections(55, {
        ticker:"ko",
        fiscalYear: "2013",
        fiscalPeriod: "FY",
        hypercube: "xbrl28:ImpliedTable"
    }),
    cocacolaincome: local:test-sections(1, {
        ticker:"ko",
        section:"http://www.thecocacolacompany.com/role/ConsolidatedStatementsOfIncome",
        fiscalYear: "2013",
        fiscalPeriod: "FY"
    }),
    cocacolaincome-q4: local:test-sections(1, {
        ticker:"ko",
        section:"http://www.thecocacolacompany.com/role/ConsolidatedStatementsOfIncome",
        fiscalYear: "2013",
        fiscalPeriod: "Q4"
    }),
    byconcept: local:test-sections-result($local:expected.byconcept, {
        tag:"DOW30",
        concept:"us-gaap:NetIncomeLoss",
        fiscalYear: "2013",
        fiscalPeriod: "FY"
    }),
    byfyfp: local:test-sections(1, {
        ticker:"ko",
        fiscalYear:"2012",
        fiscalPeriod:"Q1",
        section:"http://www.thecoca-colacompany.com/role/CondensedConsolidatedBalanceSheets"
    }),
    byfyfplowercase: local:test-sections(1, {
        ticker:"ko",
        fiscalYear:"2012",
        fiscalPeriod:"q2",
        section: "http://www.thecoca-colacompany.com/role/CondensedConsolidatedBalanceSheets"
    }),
    generic: local:test-generic-components(1, {
      profile-name: "generic",
      aid: "0000021344-14-000008",
      section: "http://www.thecocacolacompany.com/role/DocumentAndEntityInformationDocument"
    }),
    generic-aid: local:test-generic-components(95, {
      profile-name: "generic",
      aid: "0000021344-14-000008"
    }),
    generic-aid-with-tables: if(test:is-dow30()) then true else local:test-generic-components(66, {
      profile-name: "generic",
      aid: "0001214659-13-001731"
    }),
    platinumre: if(test:is-dow30()) then true else test:invoke-and-assert-deep-equal(
      "sections",
      {aid:"0001171500-15-000007"},
      function($b as item*) as item* { count($b.Sections[]) },
      76
    ),
    example1: test:invoke-and-assert-deep-equal(
      "sections",
      {aid:"0000021344-13-000039"},
      function($b as item*) as item* { [ trim($b.Sections[], ("ReportElements", "Components", "ValidationErrors")) ] },
      test:get-expected-result("secxbrl/sections-expected1.jq"),
      { NoArrayOrder: true }
    ),
    example2: test:invoke-and-assert-deep-equal(
      "sections",
      {
        ticker:"ko",
        fiscalYear: "2013",
        fiscalPeriod: "FY"
      },
      function($b as item*) as item* {
        [ trim(
          $b.Sections[],
          ("ReportElements", "Components", "ValidationErrors")
        ) ]
      },
      test:get-expected-result("secxbrl/sections-expected2.jq"),
      { NoArrayOrder: true }
    ),
    url: test:invoke-and-assert-deep-equal(
      "sections",
      {aid:"0000021344-13-000039"},
      function($b as item*) as item* {
        project(
          $b.Sections[]
            [$$.SectionURI = "http://www.thecoca-colacompany.com/role/DocumentAndEntityInformation"],
          ("ReportElements", "Components")
        )
      },
      {
        "ReportElements" : backend:url("report-elements", {
            token: $config:test-token,
            aid: "0000021344-13-000039",
            format: "json",
            section: "http://www.thecoca-colacompany.com/role/DocumentAndEntityInformation",
            profile-name: "sec"
            }),
        "Components" : backend:url("components", {
            token: $config:test-token,
            aid: "0000021344-13-000039",
            format: "json",
            section: "http://www.thecoca-colacompany.com/role/DocumentAndEntityInformation",
            profile-name: "sec"
            })
      },
      { NoArrayOrder: true }
    )
})

import module namespace response = "http://www.28msec.com/modules/http-response";
import module namespace test = "http://apps.28.io/test";
import module namespace config = "http://apps.28.io/config";
import module namespace backend = "http://apps.28.io/backend";

declare variable $local:expected as object :=
    {
      "byconcept" : [ "1001000 - Statement - Consolidated Statements Of Operations", "1002000 - Statement - Consolidated Statements of Comprehensive Income", "1004000 - Statement - Consolidated Statements Of Cash Flows", "2401402 - Disclosure - Summary Of Business Segment Data (Details)", "2405403 - Disclosure - Earnings Per Share (Schedule Of Weighted-Average Number Of Shares Outstanding Used To Compute Earnings Per Share) (Details)", "2424403 - Disclosure - Quarterly Financial Data (Schedule Of Quarterly Financial Data) (Details)", "1002000 - Statement - Consolidated Statements of Income", "1003000 - Statement - Consolidated Statements of Comprehensive Income", "1005000 - Statement - Consolidated Statements of Changes in Stockholders' Equity", "1006000 - Statement - Consolidated Statements of Cash Flows", "2429403 - Disclosure - Earnings Per Share (Details)", "2438402 - Disclosure - International Operations (Details)", "2440402 - Disclosure - Parent Company - Statements of Income (Details)", "2440404 - Disclosure - Parent Company - Statements of Cash Flows (Details2)", "1001000 - Statement - CONSOLIDATED STATEMENTS OF INCOME", "1005000 - Statement - CONSOLIDATED STATEMENTS OF SHAREOWNERS' EQUITY", "1001000 - Statement - Consolidated Income Statements", "000100 - Statement - Consolidated Statement Of Income", "041101 - Disclosure - Earnings Per Share (Details)", "041702 - Disclosure - Disclosures About Segments And Related Information (Schedule Of Segments And Related Information) (Details)", "100020 - Statement - Statement of Earnings", "100030 - Statement - Statement of Comprehensive Income", "100040 - Statement - Statement of Changes in Shareowners' Equity", "100060 - Statement - Statement of Cash Flows", "401500 - Disclosure - Shareowners' Equity (Details)", "402800 - Disclosure - Quarterly Information (unaudited) (Details)", "1001000 - Statement - Consolidated Statements of Income", "1004000 - Statement - Consolidated Statements of Cash Flows", "1005000 - Statement - Consolidated Statements of Stockholders' Equity", "1001000 - Statement - Consolidated Statement of Income", "1002000 - Statement - Consolidated Statement of Comprehensive Income", "1004000 - Statement - Consolidated Statement of Cash Flows", "1005000 - Statement - Consolidated Statement of Shareholders Equity", "2414402 - Disclosure - Quarterly Results (Detail)", "1001000 - Statement - CONSOLIDATED STATEMENTS OF EARNINGS", "2418402 - Disclosure - EARNINGS PER SHARE (DETAILS)", "2447402 - Disclosure - QUARTERLY RESULTS (UNAUDITED) (DETAILS)", "1005000 - Statement - Consolidated Statement of Equity", "2404402 - Disclosure - Summarized Financial Data - Chevron U.S.A. Inc. (Details)", "2405402 - Disclosure - Summarized Financial Data - Chevron Transport Corporation (Details)", "2410402 - Disclosure - Operating Segments and Geographic Data (Details)", "2427402 - Disclosure - Earnings Per Share (Details)", "1001000 - Statement - Consolidated Statement of Operations", "2404402 - Disclosure - Earnings Per Share (Details)", "2410403 - Disclosure - Equity (Changes in Noncontrolling Interests) (Details)", "2420404 - Disclosure - Segment Financial Data (Selected Quarterly Financial Data) (Details)", "2421402 - Disclosure - Selected Quarterly Financial Data - Unaudited (Details)", "1001000 - Statement - Consolidated Statements Of Income (Audited)", "1002000 - Statement - Consolidated Statements Of Comprehensive Income (Audited)", "2415402 - Disclosure - Quarterly Financial Data (Unaudited) (Quarterly Financial Data) (Details)", "1002000 - Statement - Consolidated Statements of Earnings", "1004000 - Statement - Consolidated Statements of Equity", "2419402 - Disclosure - Selected Quarterly Financial Data (Unaudited) (Details)", "1004000 - Statement - Consolidated Statement of Equity", "2420402 - Disclosure - Earnings Per Share - Calculations of Earnings Per Share (Detail)", "1001000 - Statement - Consolidated Statements Of Income", "1005000 - Statement - Consolidated Statements of Shareholders' Equity", "1002000 - Statement - Consolidated Statements Of Earnings", "1004000 - Statement - Consolidated Statements of Stockholders' Equity", "1005000 - Statement - Consolidated Statements Of Cash Flows", "2415402 - Disclosure - Quarterly Financial Data (Unaudited) (Details)", "1003000 - Statement - Consolidated Statements of Operations", "1005000 - Statement - Consolidated Statements of Changes in Shareholders' Equity", "2429403 - Disclosure - Quarterly Financial Data Quarterly Financial Data (Unaudited) (Details)", "2430405 - Disclosure - Schedule I Condensed Income Statement (Details)", "000100 - Statement - Consolidated Statements Of Income", "000400 - Statement - Consolidated Statements Of Changes In Stockholders' Equity", "041801 - Disclosure - Quarterly Financial Information (Unaudited) (Quarterly Financial Results) (Details)", "1003000 - Statement - Consolidated Statements Of Operations", "1004000 - Statement - Consolidated Statements of Comprehensive Income", "1006000 - Statement - Consolidated Statements Of Equity", "2420402 - Disclosure - Net Income per Share (Calculation Of Basic And Diluted Net Income Per Share) (Detail)", "2475402 - Disclosure - Quarterly Financial Summary (Detail)", "000011 - Statement - Consolidated Statement of Income", "004010 - Disclosure - Significant Accounting Policies (Details)", "004170 - Disclosure - Quarterly Data (Unaudited) (Details)", "1003 - Statement - Income Statements", "1004 - Statement - Comprehensive Income Statements", "1008 - Statement - Cash Flows Statements", "1009 - Statement - Stockholders' Equity Statements", "1055 - Disclosure - Basic and Diluted Earnings Per Share (Detail)", "1121 - Disclosure - Quarterly Information (Unaudited) (Detail)", "010020 - Statement - Consolidated Statements of Income", "010035 - Statement - Consolidated Statements of Comprehensive Income", "010060 - Statement - Consolidated Statements of Cash Flows", "010080 - Statement - Consolidated Statements of Shareholders' Equity", "042600 - Disclosure - Parent Company (Details)", "042620 - Disclosure - Parent Company (Details 2)", "042700 - Disclosure - Quarterly Financial Data (Unaudited) (Details)", "1003 - Statement - Consolidated Statements of Income", "1008 - Statement - Consolidated Statements of Changes in Equity", "1118 - Disclosure - Schedule of Quarterly Financial Information (Detail)", "0110 - Statement - Consolidated Statements of Earnings", "0120 - Statement - Consolidated Statements of Comprehensive Income", "0140 - Statement - Consolidated Statements of Changes in Shareholders' Equity", "0150 - Statement - Consolidated Statements of Cash Flows", "0625 - Disclosure - Business Segments (Details)", "0630 - Disclosure - Parent Company (Details)", "06302 - Disclosure - Parent Company (Details 2)", "1002000 - Statement - CONSOLIDATED STATEMENTS OF OPERATIONS", "1004000 - Statement - CONSOLIDATED STATEMENTS OF CHANGES IN EQUITY", "2436402 - Disclosure - Basic and Diluted Earnings Per Share (Detail)" ]
    };

declare %an:nondeterministic function local:test-sections($expected as integer, $params as object) as item
{
    let $endpoint := "sections"
    let $request := test:invoke($endpoint, $params)
    let $actual as integer := count($request[2].Sections[])
    let $status as integer := $request[1]
    return test:assert-eq($expected, $actual, $status, test:url($endpoint, $params))
};

declare %an:sequential function local:test-sections-result($expected as array, $params as object) as item
{
    let $endpoint := "sections"
    let $request := test:invoke($endpoint, $params)
    let $actual as array := [ distinct-values($request[2].Sections[].Section) ]
    let $status as integer := $request[1]
    return test:assert-eq-array($expected, $actual, $status, test:url($endpoint, $params))
};

declare %an:nondeterministic function local:test-generic-components($expected as integer, $params as object) as item
{
    let $endpoint := "sections"
    let $request := test:invoke($endpoint, $params)
    let $actual as integer := count($request[2].Sections[])
    let $status as integer := $request[1]
    return test:assert-eq($expected, $actual, $status, test:url($endpoint, $params))
};

declare %an:sequential function local:check($o as object) as object
{
    if (not(every $k in (keys($o) ! $o.$$) satisfies ($k instance of boolean and $k)))
    then {
            response:status-code(500);
            $o
    } else
            $o
};

local:check({
    cocacola: local:test-sections(94, {
        ticker:"ko",
        fiscalYear: "2013",
        fiscalPeriod: "FY"
    }),
    cocacola-implied: local:test-sections(55, {
        ticker:"ko",
        fiscalYear: "2013",
        fiscalPeriod: "FY",
        hypercube: "xbrl28:ImpliedTable"
    }),
    cocacolaincome: local:test-sections(1, {
        ticker:"ko",
        section:"http://www.thecocacolacompany.com/role/ConsolidatedStatementsOfIncome",
        fiscalYear: "2013",
        fiscalPeriod: "FY"
    }),
    cocacolaincome-q4: local:test-sections(1, {
        ticker:"ko",
        section:"http://www.thecocacolacompany.com/role/ConsolidatedStatementsOfIncome",
        fiscalYear: "2013",
        fiscalPeriod: "Q4"
    }),
    byconcept: local:test-sections-result($local:expected.byconcept, {
        tag:"DOW30",
        concept:"us-gaap:NetIncomeLoss",
        fiscalYear: "2013",
        fiscalPeriod: "FY"
    }),
    byfyfp: local:test-sections(1, {
        ticker:"ko",
        fiscalYear:"2012",
        fiscalPeriod:"Q1",
        section:"http://www.thecoca-colacompany.com/role/CondensedConsolidatedBalanceSheets"
    }),
    byfyfplowercase: local:test-sections(1, {
        ticker:"ko",
        fiscalYear:"2012",
        fiscalPeriod:"q2",
        section: "http://www.thecoca-colacompany.com/role/CondensedConsolidatedBalanceSheets"
    }),
    generic: local:test-generic-components(1, {
      profile-name: "generic",
      aid: "0000021344-14-000008",
      section: "http://www.thecocacolacompany.com/role/DocumentAndEntityInformationDocument"
    }),
    generic-aid: local:test-generic-components(95, {
      profile-name: "generic",
      aid: "0000021344-14-000008"
    }),
    generic-aid-with-tables: if(test:is-dow30()) then true else local:test-generic-components(72, {
      profile-name: "generic",
      aid: "0001214659-13-001731"
    }),
    platinumre: if(test:is-dow30()) then true else test:invoke-and-assert-deep-equal(
      "sections",
      {aid:"0001171500-15-000007"},
      function($b as item*) as item* { count($b.Components[]) },
      76
    ),
    example1: test:invoke-and-assert-deep-equal(
      "sections",
      {aid:"0000021344-13-000039"},
      function($b as item*) as item* { [ trim($b.Sections[], ("ReportElements", "Components", "ValidationErrors")) ] },
      test:get-expected-result("secxbrl/sections-expected1.jq"),
      { NoArrayOrder: true }
    ),
    example2: test:invoke-and-assert-deep-equal(
      "sections",
      {
        ticker:"ko",
        fiscalYear: "2013",
        fiscalPeriod: "FY"
      },
      function($b as item*) as item* {
        [ trim(
          $b.Sections[],
          ("ReportElements", "Components", "ValidationErrors")
        ) ]
      },
      test:get-expected-result("secxbrl/sections-expected2.jq"),
      { NoArrayOrder: true }
    ),
    url: test:invoke-and-assert-deep-equal(
      "sections",
      {aid:"0000021344-13-000039"},
      function($b as item*) as item* {
        project(
          $b.Sections[]
            [$$.SectionURI = "http://www.thecoca-colacompany.com/role/DocumentAndEntityInformation"],
          ("ReportElements", "Components")
        )
      },
      {
        "ReportElements" : backend:url("report-elements", {
            token: $config:test-token,
            aid: "0000021344-13-000039",
            format: "json",
            section: "http://www.thecoca-colacompany.com/role/DocumentAndEntityInformation",
            profile-name: "sec"
            }),
        "Components" : backend:url("components", {
            token: $config:test-token,
            aid: "0000021344-13-000039",
            format: "json",
            section: "http://www.thecoca-colacompany.com/role/DocumentAndEntityInformation",
            profile-name: "sec"
            })
      },
      { NoArrayOrder: true }
    )
})


Update facttable-for-report.jq

Update facttable-for-report.jq

import module namespace response = "http://www.28msec.com/modules/http-response";
import module namespace request = "http://www.28msec.com/modules/http-request";
import module namespace schema = "http://zorba.io/modules/schema";
import module namespace test = "http://apps.28.io/test";
import module namespace http-client = "http://zorba.io/modules/http-client";

declare function local:expected-OtherOperatingIncomeExpenses-ATnT-2013() as object {
    {
        "Aspects": {
            "xbrl28:Archive": "0000732717-14-000010",
            "xbrl:Concept": "fac:OtherOperatingIncomeExpenses",
            "xbrl:Entity": "http://www.sec.gov/CIK 0000732717",
            "xbrl:Period": "2013-01-01/2013-12-31",
            "sec:FiscalPeriod": "FY",
            "sec:FiscalPeriodType": "YTD",
            "sec:FiscalYear": 2013,
            "sec:Accepted": "20140221162554",
            "dei:LegalEntityAxis": "sec:DefaultLegalEntity"
        },
        "KeyAspects": [
            "xbrl:Concept",
            "xbrl:Entity",
            "xbrl:Period",
            "xbrl:Unit",
            "sec:Accepted"
        ],
        "Type": "NumericValue",
        "Value": -145082000000,
        "Decimals": -6,
        "Concept": {
            "Balance": "CREDIT",
            "PeriodType": "duration",
            "DataType": "xbrli:monetaryItemType"
        },
        "AuditTrails": [
            {
                "Id": "bf2d1587-491c-4492-b587-ddd00d762f2d",
                "Type": "xbrl28:formula",
                "Label": "Other Operating Income (Expenses)",
                "Message": "fac:OtherOperatingIncomeExpenses[-145,082,000,000 USD] = fac:OperatingIncomeLoss[30,479,000,000 USD] - fac:GrossProfit[77,288,000,000 USD] - fac:OperatingExpenses[98,273,000,000 USD]",
                "Data": {
                    "OutputConcept": "fac:OtherOperatingIncomeExpenses"
                }
            }
        ],
        "xbrl28:Type": "xbrl28:formula",
        "EntityRegistrantName": "AT&T INC.",
        "Unit": "iso4217:USD"
    }
};

declare function local:compare-audit-trails($expected as array?, $actual as array?) as object* {
    for $exp as object at $pos in $expected[]
    let $act as object? := $actual[][$pos]
    return
        if (exists($exp.Data.ValidatedFacts))
        then
            let $expM := copy $e := $exp modify ( delete json $e.Data.ValidatedFacts ) return $e
            let $actM := copy $a := $act modify ( delete json $a.Data.ValidatedFacts ) return $a
            return  (
                if(deep-equal($expM, $actM))
                then ()
                else
                    {
                        type: "unexpected-audittrails-value",
                        expected: $expM,
                        actual: $actM
                    },
                if(count($exp.Data.ValidatedFacts[]) eq count($act.Data.ValidatedFacts[]))
                then ()
                else
                    {
                        type: "number-of-validated-facts-differs",
                        expected: $exp,
                        actual: $act
                    }
            )
        else
            if(deep-equal($exp, $act))
            then ()
            else
                {
                    type: "unexpected-audittrails-value",
                    expected: $exp,
                    actual: $act
                }
};

declare function local:diff-facts($fact-expected as object, $fact-actual as object?) as object* {
    if(empty($fact-actual))
    then
        {
            type: "missing-fact-in-result"
        }
    else
        (
            for $key in distinct-values((keys($fact-expected), keys($fact-actual)))
            where not($key = ("Aspects", "KeyAspects", "Profiles", "AuditTrails"))
            let $exp-value := $fact-expected.$key
            let $act-value := $fact-actual.$key
            return
                if(deep-equal($exp-value, $act-value) or
                   (schema:schema-type($exp-value) eq schema:schema-type($act-value) and schema:schema-type($exp-value) eq xs:QName("xs:decimal") and fn:format-number(xs:decimal($exp-value),"#,##0.0000000000000") eq fn:format-number(xs:decimal($act-value),"#,##0.0000000000000"))
                )
                then ()
                else
                    {
                        type: "unexpected-fact-field-value",
                        field: $key,
                        expected: $exp-value,
                        actual: $act-value
                    },
            (: compare aspects :)
            for $key in distinct-values((keys($fact-expected.Aspects), keys($fact-actual.Aspects)))
            let $exp-value := $fact-expected.Aspects.$key
            let $act-value := $fact-actual.Aspects.$key
            return
                if(deep-equal($exp-value, $act-value))
                then ()
                else
                    {
                        type: "unexpected-aspect-value",
                        aspect: $key,
                        expected: $exp-value,
                        actual: $act-value
                    },
            (: compare keyaspects :)
            let $exp-value := $fact-expected.KeyAspects
            let $act-value := $fact-actual.KeyAspects
            return
                if(deep-equal($exp-value, $act-value))
                then ()
                else
                    {
                        type: "unexpected-keyaspects-value",
                        expected: $exp-value,
                        actual: $act-value
                    },
            (: compare Profiles :)
            let $exp-value := $fact-expected.Profiles
            let $act-value := $fact-actual.Profiles
            return
                if(deep-equal($exp-value, $act-value))
                then ()
                else
                    {
                        type: "unexpected-profiles-value",
                        expected: $exp-value,
                        actual: $act-value
                    },
            (: compare Audittrails :)
            let $exp-value := $fact-expected.AuditTrails
            let $act-value := $fact-actual.AuditTrails
            return
                local:compare-audit-trails($exp-value, $act-value)
        )
};

declare function local:compare-fact-tables($fact-table-expected as object, $fact-table-actual as object) as object*{
    let $actual-facts as object+ := $fact-table-actual.FactTable[]
    let $expected-facts as object+ := $fact-table-expected.FactTable[]
    let $errors :=
        (
            for $exp in $expected-facts
            let $act := $actual-facts[$$.Aspects."xbrl:Concept" eq $exp.Aspects."xbrl:Concept"
                                      and $$.Aspects."xbrl:Entity" eq $exp.Aspects."xbrl:Entity"
                                      and $$.Aspects."xbrl:Period" eq $exp.Aspects."xbrl:Period"
                                      and $$.Aspects."xbrl28:Archive" eq $exp.Aspects."xbrl28:Archive"]
            let $errors as object* := local:diff-facts($exp, $act)
            return
                if(empty($errors))
                then ()
                else {
                    expectedFact: $exp,
                    actualFact: $act,
                    errors: [$errors]
                },

            for $act in $actual-facts
            let $exp := $expected-facts[$$.Aspects."xbrl:Concept" eq $act.Aspects."xbrl:Concept"
                                      and $$.Aspects."xbrl:Entity" eq $act.Aspects."xbrl:Entity"
                                      and $$.Aspects."xbrl:Period" eq $act.Aspects."xbrl:Period"
                                      and $$.Aspects."xbrl28:Archive" eq $act.Aspects."xbrl28:Archive"]
            where empty($exp)
            return
                {
                    unexpectedFact: $act
                }
        )
    return
        if(empty($errors))
        then ()
        else (
                {
                    expectedNumberOfFacts: count($expected-facts),
                    actualNumberOfFacts: count($actual-facts)
                },
                $errors
            )
};

declare %an:nondeterministic function local:test-facttable($expected as integer, $params as object) as item
{
    let $endpoint := "facttable-for-report"
    let $request := test:invoke($endpoint, $params)
    let $actual as integer := count($request[2].FactTable[])
    let $status as integer := $request[1]
    return test:assert-eq($expected, $actual, $status, test:url($endpoint, $params))
};

declare %an:nondeterministic function local:test-facttable-fact($concept as string, $expected as object, $params as object) as item
{
    let $endpoint := "facttable-for-report"
    let $request := test:invoke($endpoint, $params)
    let $facts as object* := $request[2].FactTable[]
    let $actual := $facts[$$.Aspects."xbrl:Concept" eq $concept]
    let $diff :=
      for $f in $actual return local:diff-facts($expected, $f)
    return if (empty($diff)) then true else { url: test:url($endpoint, $params), factDiffErrors: [ $diff ], expectedFact: $expected, actualFact: $actual }
};

declare %an:nondeterministic function local:test-report-does-not-exist($params as object) as item
{
    let $endpoint := "facttable-for-report"
    let $request := test:invoke($endpoint, $params)
    let $status as integer := $request[1]
    return if ($status eq 404) then true else { url: test:url($endpoint, $params), unexpectedResponse: $request[2] }
};

declare %an:sequential function local:check($o as object) as object
{
    if (not(every $k in (keys($o) ! $o.$$) satisfies ($k instance of boolean and $k)))
    then {
            response:status-code(500);
            $o
    } else
            $o
};

declare %an:nondeterministic function local:test-values() as item*
{
    let $endpoint := "facttable-for-report"
    let $params := {ticker:"ko",fiscalYear:"2013",fiscalPeriod:"FY",fiscalPeriodType: ["instant", "YTD", "QTD"],report:"FundamentalAccountingConcepts"}
    let $request := test:invoke($endpoint, $params)
    let $actual as object := $request[2]
    let $expected := parse-json(
        http-client:get("http://" || request:server-name() || ":" || request:server-port() ||
                        "/test/facttable-for-report-expected1.jq").body.content)
    let $diff := local:compare-fact-tables($expected, $actual)
    return if (empty($diff)) then true else { url: test:url($endpoint, $params), factTableDiff: [ ({ params : $params },$diff) ], expectedFactTable: $expected, actualFactTable: $actual }
};

let $dow30 := test:is-dow30()
local:check({
    cocacola: local:test-facttable(95, {
        report:"FundamentalAccountingConcepts",
        ticker:"ko",
        fiscalYear:"2013",
        fiscalPeriod:"Q1"}),
    aid: local:test-facttable(if($dow30) then 0 else 95, {
        aid:"0001193125-14-157120",
        report:"FundamentalAccountingConcepts"}),
    aid2: local:test-facttable(19, {
        aid:"0000732717-14-000022",
        report:"FundamentalAccountingConcepts"}),
    aid2-qtd: local:test-facttable(96, {
        aid:"0000732717-14-000022",
        report:"FundamentalAccountingConcepts",
        fiscalPeriodType: [ "instant", "QTD" ]
    }),
    tickerrole: local:test-facttable(95, {
        report:"FundamentalAccountingConcepts",
        ticker:"ko",
        fiscalYear:"2012",
        fiscalPeriod:"Q1"}),
    tickerfyfprole: local:test-facttable(246, {
        report:"FundamentalAccountingConcepts",
        ticker:["ko","wmt"],
        fiscalYear:"2013",
        fiscalPeriod:"FY",
        fiscalPeriodType:["instant", "QTD"]
    }),
    allvalues : local:test-values(),
    otheroperatingincometest: local:test-facttable-fact("fac:OtherOperatingIncomeExpenses",
                                                        local:expected-OtherOperatingIncomeExpenses-ATnT-2013(),
                                                        {
        report:"FundamentalAccountingConcepts",
        ticker:"t",
        fiscalYear:"2013",
        fiscalPeriod:["FY"]}),
    reportDoesntExist: local:test-report-does-not-exist({
        report:"report-not-found",
        ticker:"MSFT",
        fiscalYear:"ALL",
        fiscalPeriod:"FY"})
})

import module namespace response = "http://www.28msec.com/modules/http-response";
import module namespace request = "http://www.28msec.com/modules/http-request";
import module namespace schema = "http://zorba.io/modules/schema";
import module namespace test = "http://apps.28.io/test";
import module namespace http-client = "http://zorba.io/modules/http-client";

declare function local:expected-OtherOperatingIncomeExpenses-ATnT-2013() as object {
    {
        "Aspects": {
            "xbrl28:Archive": "0000732717-14-000010",
            "xbrl:Concept": "fac:OtherOperatingIncomeExpenses",
            "xbrl:Entity": "http://www.sec.gov/CIK 0000732717",
            "xbrl:Period": "2013-01-01/2013-12-31",
            "sec:FiscalPeriod": "FY",
            "sec:FiscalPeriodType": "YTD",
            "sec:FiscalYear": 2013,
            "sec:Accepted": "20140221162554",
            "dei:LegalEntityAxis": "sec:DefaultLegalEntity"
        },
        "KeyAspects": [
            "xbrl:Concept",
            "xbrl:Entity",
            "xbrl:Period",
            "xbrl:Unit",
            "sec:Accepted"
        ],
        "Type": "NumericValue",
        "Value": -145082000000,
        "Decimals": -6,
        "Concept": {
            "Balance": "CREDIT",
            "PeriodType": "duration",
            "DataType": "xbrli:monetaryItemType"
        },
        "AuditTrails": [
            {
                "Id": "bf2d1587-491c-4492-b587-ddd00d762f2d",
                "Type": "xbrl28:formula",
                "Label": "Other Operating Income (Expenses)",
                "Message": "fac:OtherOperatingIncomeExpenses[-145,082,000,000 USD] = fac:OperatingIncomeLoss[30,479,000,000 USD] - fac:GrossProfit[77,288,000,000 USD] - fac:OperatingExpenses[98,273,000,000 USD]",
                "Data": {
                    "OutputConcept": "fac:OtherOperatingIncomeExpenses"
                }
            }
        ],
        "xbrl28:Type": "xbrl28:formula",
        "EntityRegistrantName": "AT&T INC.",
        "Unit": "iso4217:USD"
    }
};

declare function local:compare-audit-trails($expected as array?, $actual as array?) as object* {
    for $exp as object at $pos in $expected[]
    let $act as object? := $actual[][$pos]
    return
        if (exists($exp.Data.ValidatedFacts))
        then
            let $expM := copy $e := $exp modify ( delete json $e.Data.ValidatedFacts ) return $e
            let $actM := copy $a := $act modify ( delete json $a.Data.ValidatedFacts ) return $a
            return  (
                if(deep-equal($expM, $actM))
                then ()
                else
                    {
                        type: "unexpected-audittrails-value",
                        expected: $expM,
                        actual: $actM
                    },
                if(count($exp.Data.ValidatedFacts[]) eq count($act.Data.ValidatedFacts[]))
                then ()
                else
                    {
                        type: "number-of-validated-facts-differs",
                        expected: $exp,
                        actual: $act
                    }
            )
        else
            if(deep-equal($exp, $act))
            then ()
            else
                {
                    type: "unexpected-audittrails-value",
                    expected: $exp,
                    actual: $act
                }
};

declare function local:diff-facts($fact-expected as object, $fact-actual as object?) as object* {
    if(empty($fact-actual))
    then
        {
            type: "missing-fact-in-result"
        }
    else
        (
            for $key in distinct-values((keys($fact-expected), keys($fact-actual)))
            where not($key = ("Aspects", "KeyAspects", "Profiles", "AuditTrails"))
            let $exp-value := $fact-expected.$key
            let $act-value := $fact-actual.$key
            return
                if(deep-equal($exp-value, $act-value) or
                   (schema:schema-type($exp-value) eq schema:schema-type($act-value) and schema:schema-type($exp-value) eq xs:QName("xs:decimal") and fn:format-number(xs:decimal($exp-value),"#,##0.0000000000000") eq fn:format-number(xs:decimal($act-value),"#,##0.0000000000000"))
                )
                then ()
                else
                    {
                        type: "unexpected-fact-field-value",
                        field: $key,
                        expected: $exp-value,
                        actual: $act-value
                    },
            (: compare aspects :)
            for $key in distinct-values((keys($fact-expected.Aspects), keys($fact-actual.Aspects)))
            let $exp-value := $fact-expected.Aspects.$key
            let $act-value := $fact-actual.Aspects.$key
            return
                if(deep-equal($exp-value, $act-value))
                then ()
                else
                    {
                        type: "unexpected-aspect-value",
                        aspect: $key,
                        expected: $exp-value,
                        actual: $act-value
                    },
            (: compare keyaspects :)
            let $exp-value := $fact-expected.KeyAspects
            let $act-value := $fact-actual.KeyAspects
            return
                if(deep-equal($exp-value, $act-value))
                then ()
                else
                    {
                        type: "unexpected-keyaspects-value",
                        expected: $exp-value,
                        actual: $act-value
                    },
            (: compare Profiles :)
            let $exp-value := $fact-expected.Profiles
            let $act-value := $fact-actual.Profiles
            return
                if(deep-equal($exp-value, $act-value))
                then ()
                else
                    {
                        type: "unexpected-profiles-value",
                        expected: $exp-value,
                        actual: $act-value
                    },
            (: compare Audittrails :)
            let $exp-value := $fact-expected.AuditTrails
            let $act-value := $fact-actual.AuditTrails
            return
                local:compare-audit-trails($exp-value, $act-value)
        )
};

declare function local:compare-fact-tables($fact-table-expected as object, $fact-table-actual as object) as object*{
    let $actual-facts as object+ := $fact-table-actual.FactTable[]
    let $expected-facts as object+ := $fact-table-expected.FactTable[]
    let $errors :=
        (
            for $exp in $expected-facts
            let $act := $actual-facts[$$.Aspects."xbrl:Concept" eq $exp.Aspects."xbrl:Concept"
                                      and $$.Aspects."xbrl:Entity" eq $exp.Aspects."xbrl:Entity"
                                      and $$.Aspects."xbrl:Period" eq $exp.Aspects."xbrl:Period"
                                      and $$.Aspects."xbrl28:Archive" eq $exp.Aspects."xbrl28:Archive"]
            let $errors as object* := local:diff-facts($exp, $act)
            return
                if(empty($errors))
                then ()
                else {
                    expectedFact: $exp,
                    actualFact: $act,
                    errors: [$errors]
                },

            for $act in $actual-facts
            let $exp := $expected-facts[$$.Aspects."xbrl:Concept" eq $act.Aspects."xbrl:Concept"
                                      and $$.Aspects."xbrl:Entity" eq $act.Aspects."xbrl:Entity"
                                      and $$.Aspects."xbrl:Period" eq $act.Aspects."xbrl:Period"
                                      and $$.Aspects."xbrl28:Archive" eq $act.Aspects."xbrl28:Archive"]
            where empty($exp)
            return
                {
                    unexpectedFact: $act
                }
        )
    return
        if(empty($errors))
        then ()
        else (
                {
                    expectedNumberOfFacts: count($expected-facts),
                    actualNumberOfFacts: count($actual-facts)
                },
                $errors
            )
};

declare %an:nondeterministic function local:test-facttable($expected as integer, $params as object) as item
{
    let $endpoint := "facttable-for-report"
    let $request := test:invoke($endpoint, $params)
    let $actual as integer := count($request[2].FactTable[])
    let $status as integer := $request[1]
    return test:assert-eq($expected, $actual, $status, test:url($endpoint, $params))
};

declare %an:nondeterministic function local:test-facttable-fact($concept as string, $expected as object, $params as object) as item
{
    let $endpoint := "facttable-for-report"
    let $request := test:invoke($endpoint, $params)
    let $facts as object* := $request[2].FactTable[]
    let $actual := $facts[$$.Aspects."xbrl:Concept" eq $concept]
    let $diff :=
      for $f in $actual return local:diff-facts($expected, $f)
    return if (empty($diff)) then true else { url: test:url($endpoint, $params), factDiffErrors: [ $diff ], expectedFact: $expected, actualFact: $actual }
};

declare %an:nondeterministic function local:test-report-does-not-exist($params as object) as item
{
    let $endpoint := "facttable-for-report"
    let $request := test:invoke($endpoint, $params)
    let $status as integer := $request[1]
    return if ($status eq 404) then true else { url: test:url($endpoint, $params), unexpectedResponse: $request[2] }
};

declare %an:sequential function local:check($o as object) as object
{
    if (not(every $k in (keys($o) ! $o.$$) satisfies ($k instance of boolean and $k)))
    then {
            response:status-code(500);
            $o
    } else
            $o
};

declare %an:nondeterministic function local:test-values() as item*
{
    let $endpoint := "facttable-for-report"
    let $params := {ticker:"ko",fiscalYear:"2013",fiscalPeriod:"FY",fiscalPeriodType: ["instant", "YTD", "QTD"],report:"FundamentalAccountingConcepts"}
    let $request := test:invoke($endpoint, $params)
    let $actual as object := $request[2]
    let $expected := parse-json(
        http-client:get("http://" || request:server-name() || ":" || request:server-port() ||
                        "/test/facttable-for-report-expected1.jq").body.content)
    let $diff := local:compare-fact-tables($expected, $actual)
    return if (empty($diff)) then true else { url: test:url($endpoint, $params), factTableDiff: [ ({ params : $params },$diff) ], expectedFactTable: $expected, actualFactTable: $actual }
};

let $dow30 := test:is-dow30()
local:check({
    cocacola: local:test-facttable(95, {
        report:"FundamentalAccountingConcepts",
        ticker:"ko",
        fiscalYear:"2013",
        fiscalPeriod:"Q1"}),
    aid: local:test-facttable(if($dow30) then 0 else 95, {
        aid:"0001193125-14-157120",
        report:"FundamentalAccountingConcepts"}),
    aid2: local:test-facttable(96, {
        aid:"0000732717-14-000022",
        report:"FundamentalAccountingConcepts"}),
    tickerrole: local:test-facttable(95, {
        report:"FundamentalAccountingConcepts",
        ticker:"ko",
        fiscalYear:"2012",
        fiscalPeriod:"Q1"}),
    tickerfyfprole: local:test-facttable(246, {
        report:"FundamentalAccountingConcepts",
        ticker:["ko","wmt"],
        fiscalYear:"2013",
        fiscalPeriod:"FY",
        fiscalPeriodType:["instant", "QTD"]
    }),
    allvalues : local:test-values(),
    otheroperatingincometest: local:test-facttable-fact("fac:OtherOperatingIncomeExpenses",
                                                        local:expected-OtherOperatingIncomeExpenses-ATnT-2013(),
                                                        {
        report:"FundamentalAccountingConcepts",
        ticker:"t",
        fiscalYear:"2013",
        fiscalPeriod:["FY"]}),
    reportDoesntExist: local:test-report-does-not-exist({
        report:"report-not-found",
        ticker:"MSFT",
        fiscalYear:"ALL",
        fiscalPeriod:"FY"})
})


:bug: Fix label linkbase.

:bug: Fix label linkbase.

jsoniq version "1.0";
(:
 : Copyright 2015 28msec Inc.
 :)

(:~
 :
This module provides functionality for retrieving labels.

 :
 : @author Federico Cavalieri, Ghislain Fourny
 :)
module namespace labels = "http://28.io/modules/xbrl/labels";

import module namespace concepts = "http://28.io/modules/xbrl/concepts";
import module namespace entities = "http://28.io/modules/xbrl/entities";

declare namespace xbrli = "http://www.xbrl.org/2003/instance";
declare namespace xlink = "http://www.w3.org/1999/xlink";

declare namespace ver = "http://zorba.io/options/versioning";
declare option ver:module-version "1.0";

(:~
 : A helper variable holding the default language ("en-US")
 :)
declare variable $labels:AMERICAN_ENGLISH as xs:string := "en-US";

(:~
 : The standard label role.
 :)
declare variable $labels:STANDARD_LABEL_ROLE as xs:string :=
    "http://www.xbrl.org/2003/role/label";

(:~
 : The verbose label role.
 :)
declare variable $labels:VERBOSE_LABEL_ROLE as xs:string :=
    "http://www.xbrl.org/2003/role/verboseLabel";

declare variable $labels:standard-concepts as object* :=
(
    {
      Name: "xbrl:Concept",
      Label: "Concept [Axis]",
      Kind: "Dimension",
      IsNillable: true,
      IsAbstract: true,
      PeriodType: "duration",
      SubstitutionGroup: "xbrldt:dimensionItem",
      DataType: "nonnum:domainItemType",
      BaseType: "string",
      ClosestSchemaBuiltinType: "xs:string",
      IsTextBlock: false,
      Labels: [
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "fr",
          Value: "Concept [Axe]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "de",
          Value: "Konzept [Achse]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "en-us",
          Value: "Concept [Axis]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "ja",
          Value: "項目(Concept)"
        }
      ]
    },
    {
      Name: "xbrl:Period",
      Label: "Period [Axis]",
      Kind: "Dimension",
      IsNillable: true,
      IsAbstract: true,
      PeriodType: "duration",
      SubstitutionGroup: "xbrldt:dimensionItem",
      DataType: "nonnum:domainItemType",
      BaseType: "string",
      ClosestSchemaBuiltinType: "xs:string",
      IsTextBlock: false,
      Labels: [
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "fr",
          Value: "Période [Axe]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "en-us",
          Value: "Period [Axis]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "de",
          Value: "Periode [Achse]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "ja",
          Value: "期間(Period)"
        }
      ]
    },
    {
      Name: "xbrl:Entity",
      Label: "Entity [Axis]",
      Kind: "Dimension",
      IsNillable: true,
      IsAbstract: true,
      PeriodType: "duration",
      SubstitutionGroup: "xbrldt:dimensionItem",
      DataType: "nonnum:domainItemType",
      BaseType: "string",
      ClosestSchemaBuiltinType: "xs:string",
      IsTextBlock: false,
      Labels: [
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "de",
          Value: "Entität [Achse]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "fr",
          Value: "Entité [Axe]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "en-us",
          Value: "Reporting Entity [Axis]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "ja",
          Value: "企業名(Entity)"
        }
      ]
    },
    {
      Name: "xbrl28:Archive",
      Label: "Archiv [Achse]",
      Kind: "Dimension",
      IsNillable: true,
      IsAbstract: true,
      PeriodType: "duration",
      SubstitutionGroup: "xbrldt:dimensionItem",
      DataType: "nonnum:domainItemType",
      BaseType: "string",
      ClosestSchemaBuiltinType: "xs:string",
      IsTextBlock: false,
      Labels: [
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "fr",
          Value: "Archive [Axe]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "de",
          Value: "Archiv [Achse]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "en-us",
          Value: "Archive [Axis]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "ja",
          Value: "ファイル(Archive)"
        }
      ]
    },
    {
      Name: "fsa:FiscalYear",
      Label: "Fiscal Year [Axis]",
      Kind: "Dimension",
      IsNillable: true,
      IsAbstract: true,
      PeriodType: "duration",
      SubstitutionGroup: "xbrldt:dimensionItem",
      DataType: "nonnum:domainItemType",
      BaseType: "string",
      ClosestSchemaBuiltinType: "xs:string",
      IsTextBlock: false,
      Labels: [
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "fr",
          Value: "Année fiscale [Axe]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "de",
          Value: "Steuerjahr [Achse]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "ja",
          Value: "会計年度(Fiscal Year)"
        }
      ]
    },
    {
      Name: "fsa:FiscalPeriod",
      Label: "Fiscal Period [Axis]",
      Kind: "Dimension",
      IsNillable: true,
      IsAbstract: true,
      PeriodType: "duration",
      SubstitutionGroup: "xbrldt:dimensionItem",
      DataType: "nonnum:domainItemType",
      BaseType: "string",
      ClosestSchemaBuiltinType: "xs:string",
      IsTextBlock: false,
      Labels: [
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "ja",
          Value: "会計期間(Fiscal Period)"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "en-us",
          Value: "Fiscal Period [Axis]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "fr",
          Value: "Période fiscal [Axe]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "de",
          Value: "Steuerperiode [Achse]"
        }
      ]
    },
    {
      Name: "fsa:FiscalPeriodType",
      Label: "Fiscal Period Type [Axis]",
      Kind: "Dimension",
      IsNillable: true,
      IsAbstract: true,
      PeriodType: "duration",
      SubstitutionGroup: "xbrldt:dimensionItem",
      DataType: "nonnum:domainItemType",
      BaseType: "string",
      ClosestSchemaBuiltinType: "xs:string",
      IsTextBlock: false,
      Labels: [
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "ja",
          Value: "会計期間タイプ(Fiscal Period Type)"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "en-us",
          Value: "Fiscal Period Type [Axis]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "fr",
          Value: "Type de période fiscale [Axe]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "de",
          Value: "Steuerperiodeart [Achse]"
        }
      ]
    }
);

(:~
 :
Retrieves all the labels with the given label role and language in the
 : matching concepts, one label for each concept.

 :
 :
Matching concepts are those which:
 :  - concept name and archive number match a given one;
 :  - component role matches a given one or is the default
 :    component role.
 :

 :
 :
The set of concepts to search in is specified as a parameter.

 :
 :
Language matching can either be exact, if no options are given,
 : or approximated, if at least one of the following options is given:

 :

 :
MatchDown: whether to match a more specific language, e.g.:
 :       "en" will match labels which language is "en" or "en-US".

 :
MatchUp: whether to match a less specific language, e.g.:
 :       "en-US" will match labels which language is "en-US" or "en".

 :
MatchAnyVariant: whether to match a different variant of the same
 :       language, e.g.: "en-US" will match labels which language is "en-US"
 :       or "en-UK".

 :

 :
 : @param $concept-names the concepts names.
 : @param $label-roles the label role.
 : @param $languages the label language.
 : @param $concepts the concepts in which the labels will be
 :                  searched.
 : @param $entities the entities in which entity labels will be searched.
 : @param $options Optional parameters to control language matching.
 :
 : @return the matching labels (one associated with each input concept, as
 : an object).
 :)
declare function labels:labels(
    $concept-names as string*,
    $label-roles as string*,
    $languages as string*,
    $concepts as object*,
    $entities as object*,
    $options as object?
  ) as object
{
  let $concepts := ($labels:standard-concepts, $concepts)
  return {|
    let $normalized-languages as string* := $languages ! labels:normalize-language($$)
    return (
      for $concept as object in $concepts
      where ($concepts:ALL_CONCEPT_NAMES, $concept.$concepts:NAME) = $concept-names
      group by $concept.$concepts:NAME
      let $concept-labels as object* :=
        $concept.$concepts:LABELS[][$$.Role = $label-roles]
      let $available-languages as string* :=
        distinct-values($concept-labels.Language)
      let $approximate-languages as string* := labels:approximate-languages(
        $available-languages,
        $normalized-languages,
        $options
      )
      let $english-languages as string* := labels:approximate-languages(
        $available-languages,
        "en",
        $options
      )
      let $perfect-matches as object* :=
        $concept-labels[$$.Language = $normalized-languages]
      let $approximate-matches as object* :=
        $concept-labels[$$.Language = $approximate-languages]
      let $english-matches as object* :=
        $concept-labels[$$.Language = $english-languages]
      let $label as string? :=
        ($perfect-matches.Value,
         $approximate-matches.Value,
         $english-matches.Value,
         $concept-labels.Value,
         $concept.Label)[not $$ instance of null][1]
      where exists($label)
      return {
        $concept.Name : $label
      },

      for $concept in $concept-names
      where not (($concepts:ALL_CONCEPT_NAMES, $concepts.$concepts:NAME) = $concept)
      let $label as string* :=
          switch(true)
            case starts-with($concept, "iso4217:")
            return substring($concept, 9)
            case $concept castable as date
            return format-date(date($concept), "[MNn] [D], [Y]", "en", (), ())
            case (every $date in tokenize($concept, "/") satisfies $date castable as date)
            return "From " || string-join(
                     for $date in tokenize($concept, "/")
                     return format-date(date($date), "[MNn] [D], [Y]", "en", (), ()),
                   " to ")
            case contains($concept, " ")
            return
              switch(true)
              case $concept = entities:eid($entities) and $normalized-languages = ("ja")
              return ($entities[entities:eid($$) = $concept].Profiles.SEC.EntityRegistrantName,
                       $entities[entities:eid($$) = $concept].Profiles.FSA.SubmitterName)[1]
              case $concept = entities:eid($entities)
              return ($entities[entities:eid($$) = $concept].Profiles.SEC.CompanyName,
                       $entities[entities:eid($$) = $concept].Profiles.FSA.SubmitterNameAlphabetic)[1]
              default return ()
           default return ()
      where exists($label)
      return {
        $concept : $label
      }
    )
  |}
};

(:~
 :
Retrieves all the labels with the given label role and language for
 : all concepts used in the fact and matching a concept in the list of
 : concepts. Concepts used in a fact include not only those from the
 : 'xbrl:Concept' aspect, but also Members of any custom axis.

 :
 :
Matching concepts are those which:
 :  - concept name matches a given one,
 :  - archive number matches that of a given component,
 :  - component role matches that of a given component or is the default
 :    component role.
 :

 :
 :
The set of concepts to search in is specified as a parameter.

 :
 :
Language matching can either be exact, if no options are given,
 : or approximated, if at least one of the following options is given:

 :

 :
MatchDown: whether to match a more specific language, e.g.:
 :       "en" will match labels which language is "en" or "en-US".

 :
MatchUp: whether to match a less specific language, e.g.:
 :       "en-US" will match labels which language is "en-US" or "en".

 :
MatchAnyVariant: whether to match a different variant of the same
 :       language, e.g.: "en-US" will match labels which language is "en-US"
 :       or "en-UK".

 :

 :
 : @param $facts a sequence of facts.
 : @param $label-role the label role.
 : @param $language the label language.
 : @param $concepts the concepts in which the labels will be
 :                  searched (in the version-7 format).
 : @param $options optional parameters to control language matching.
 :
 : @return an object with matching concepts as keys and labels as values.
 :)
declare function labels:labels-for-facts(
    $facts as object*,
    $label-role as string,
    $language as string,
    $concepts as object*,
    $entities as object*,
    $options as object?
  ) as object?
{
    for $facts in $facts
    group by $archive := $facts."Aspects"."xbrl28:Archive"
    let $concept-names as string* :=
        distinct-values((
          values($facts.Aspects),
          keys($facts.Aspects)
    )[$$ instance of string])
    return
        {|
            labels:labels(
                    $concept-names,
                    $label-role,
                    $language,
                    $concepts,
                    $entities,
                    $options)
        |}
};

(:~
 :
Normalizes the language code. This normalized language code can then
 : be used to find the right labels in the concepts collection.

 :
 : @param $language the language identifier.
 :
 : @return the normalized language.
 :)
declare function labels:normalize-language($language as string) as string
{
  replace(lower-case($language), "_", "-")
};

declare %private function labels:approximate-languages(
    $all-languages as string*,
    $normalized-language as string,
    $options as object?
  ) as string*
{
    if(not $options.MatchDown cast as boolean? eq false)
    then $all-languages[starts-with($$, $normalized-language)]
    else (),
    if(not $options.MatchUp cast as boolean? eq false)
    then $all-languages[starts-with($normalized-language, $$)]
    else (),
    if ((not $options.MatchAnyVariant cast as boolean? eq false) and contains($normalized-language, "-"))
    then
      $all-languages[starts-with($$, substring-before($normalized-language, "-") || "-")]
    else ()
};

(:~
 :
Transforms concept labels into XBRL labelLink.

 :
 : @param $concepts the concepts to transform.
 :
 : @return the labelLink element to be put into a linkbase.
 :)
declare function labels:to-xml(
    $concepts as object*,
    $taxonomyName as string) as element()
{
  <link:labelLink xmlns:link="http://www.xbrl.org/2003/linkbase" xlink:type="extended" xlink:role="http://www.xbrl.org/2003/role/link">
  {
    for $concept as object in $concepts
    where not $concept.Name = ($concepts:CONCEPT_REPORT_ELEMENT,
                               $concepts:ENTITY_REPORT_ELEMENT,
                               $concepts:PERIOD_REPORT_ELEMENT,
                               $concepts:UNIT_REPORT_ELEMENT,
                               $concepts:ARCHIVE_REPORT_ELEMENT,
                               $concepts:IMPLIED_TABLE_REPORT_ELEMENT,
                               $concepts:NON_NUMERIC_REPORT_ELEMENT)
    let $name as string := substring-after($concept.Name, ":")
    group by $name := $concept.Name
    let $id as string := replace($name, ":", "_")
    return
      (
        <link:loc xlink:type="locator" xlink:href="{$taxonomyName}.xsd#{$id}" xlink:label="{$id}" />,
        for $label at $pos in $concept.Labels[]
        let $role as string := ($label.Role, "http://www.xbrl.org/2003/role/label")[1]
        let $lang as string := ($label.Language, "de")[1]
        group by $role, $lang
        let $value as string? := ($label.Value)[$$ instance of string][1]
        let $labelID as string := $id || "_label" || $pos[1]
        return (
            <link:label xlink:role="{$role}"
                   xlink:label="{$labelID}"
                   id="{$labelID}"
                   xml:lang="{$lang}"
                   xlink:type="resource">{$value}</link:label>,
            <link:labelArc xlink:type="arc"
                      xlink:arcrole="http://www.xbrl.org/2003/arcrole/concept-label"
                      xlink:from="{$id}"
                      xlink:to="{$labelID}" />
        )
      )
  }</link:labelLink>
};

jsoniq version "1.0";
(:
 : Copyright 2015 28msec Inc.
 :)

(:~
 :
This module provides functionality for retrieving labels.

 :
 : @author Federico Cavalieri, Ghislain Fourny
 :)
module namespace labels = "http://28.io/modules/xbrl/labels";

import module namespace concepts = "http://28.io/modules/xbrl/concepts";
import module namespace entities = "http://28.io/modules/xbrl/entities";

declare namespace xbrli = "http://www.xbrl.org/2003/instance";
declare namespace xlink = "http://www.w3.org/1999/xlink";

declare namespace ver = "http://zorba.io/options/versioning";
declare option ver:module-version "1.0";

(:~
 : A helper variable holding the default language ("en-US")
 :)
declare variable $labels:AMERICAN_ENGLISH as xs:string := "en-US";

(:~
 : The standard label role.
 :)
declare variable $labels:STANDARD_LABEL_ROLE as xs:string :=
    "http://www.xbrl.org/2003/role/label";

(:~
 : The verbose label role.
 :)
declare variable $labels:VERBOSE_LABEL_ROLE as xs:string :=
    "http://www.xbrl.org/2003/role/verboseLabel";

declare variable $labels:standard-concepts as object* :=
(
    {
      Name: "xbrl:Concept",
      Label: "Concept [Axis]",
      Kind: "Dimension",
      IsNillable: true,
      IsAbstract: true,
      PeriodType: "duration",
      SubstitutionGroup: "xbrldt:dimensionItem",
      DataType: "nonnum:domainItemType",
      BaseType: "string",
      ClosestSchemaBuiltinType: "xs:string",
      IsTextBlock: false,
      Labels: [
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "fr",
          Value: "Concept [Axe]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "de",
          Value: "Konzept [Achse]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "en-us",
          Value: "Concept [Axis]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "ja",
          Value: "項目(Concept)"
        }
      ]
    },
    {
      Name: "xbrl:Period",
      Label: "Period [Axis]",
      Kind: "Dimension",
      IsNillable: true,
      IsAbstract: true,
      PeriodType: "duration",
      SubstitutionGroup: "xbrldt:dimensionItem",
      DataType: "nonnum:domainItemType",
      BaseType: "string",
      ClosestSchemaBuiltinType: "xs:string",
      IsTextBlock: false,
      Labels: [
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "fr",
          Value: "Période [Axe]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "en-us",
          Value: "Period [Axis]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "de",
          Value: "Periode [Achse]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "ja",
          Value: "期間(Period)"
        }
      ]
    },
    {
      Name: "xbrl:Entity",
      Label: "Entity [Axis]",
      Kind: "Dimension",
      IsNillable: true,
      IsAbstract: true,
      PeriodType: "duration",
      SubstitutionGroup: "xbrldt:dimensionItem",
      DataType: "nonnum:domainItemType",
      BaseType: "string",
      ClosestSchemaBuiltinType: "xs:string",
      IsTextBlock: false,
      Labels: [
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "de",
          Value: "Entität [Achse]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "fr",
          Value: "Entité [Axe]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "en-us",
          Value: "Reporting Entity [Axis]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "ja",
          Value: "企業名(Entity)"
        }
      ]
    },
    {
      Name: "xbrl28:Archive",
      Label: "Archiv [Achse]",
      Kind: "Dimension",
      IsNillable: true,
      IsAbstract: true,
      PeriodType: "duration",
      SubstitutionGroup: "xbrldt:dimensionItem",
      DataType: "nonnum:domainItemType",
      BaseType: "string",
      ClosestSchemaBuiltinType: "xs:string",
      IsTextBlock: false,
      Labels: [
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "fr",
          Value: "Archive [Axe]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "de",
          Value: "Archiv [Achse]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "en-us",
          Value: "Archive [Axis]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "ja",
          Value: "ファイル(Archive)"
        }
      ]
    },
    {
      Name: "fsa:FiscalYear",
      Label: "Fiscal Year [Axis]",
      Kind: "Dimension",
      IsNillable: true,
      IsAbstract: true,
      PeriodType: "duration",
      SubstitutionGroup: "xbrldt:dimensionItem",
      DataType: "nonnum:domainItemType",
      BaseType: "string",
      ClosestSchemaBuiltinType: "xs:string",
      IsTextBlock: false,
      Labels: [
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "fr",
          Value: "Année fiscale [Axe]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "de",
          Value: "Steuerjahr [Achse]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "ja",
          Value: "会計年度(Fiscal Year)"
        }
      ]
    },
    {
      Name: "fsa:FiscalPeriod",
      Label: "Fiscal Period [Axis]",
      Kind: "Dimension",
      IsNillable: true,
      IsAbstract: true,
      PeriodType: "duration",
      SubstitutionGroup: "xbrldt:dimensionItem",
      DataType: "nonnum:domainItemType",
      BaseType: "string",
      ClosestSchemaBuiltinType: "xs:string",
      IsTextBlock: false,
      Labels: [
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "ja",
          Value: "会計期間(Fiscal Period)"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "en-us",
          Value: "Fiscal Period [Axis]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "fr",
          Value: "Période fiscal [Axe]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "de",
          Value: "Steuerperiode [Achse]"
        }
      ]
    },
    {
      Name: "fsa:FiscalPeriodType",
      Label: "Fiscal Period Type [Axis]",
      Kind: "Dimension",
      IsNillable: true,
      IsAbstract: true,
      PeriodType: "duration",
      SubstitutionGroup: "xbrldt:dimensionItem",
      DataType: "nonnum:domainItemType",
      BaseType: "string",
      ClosestSchemaBuiltinType: "xs:string",
      IsTextBlock: false,
      Labels: [
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "ja",
          Value: "会計期間タイプ(Fiscal Period Type)"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "en-us",
          Value: "Fiscal Period Type [Axis]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "fr",
          Value: "Type de période fiscale [Axe]"
        },
        {
          Role: "http://www.xbrl.org/2003/role/label",
          Language: "de",
          Value: "Steuerperiodeart [Achse]"
        }
      ]
    }
);

(:~
 :
Retrieves all the labels with the given label role and language in the
 : matching concepts, one label for each concept.

 :
 :
Matching concepts are those which:
 :  - concept name and archive number match a given one;
 :  - component role matches a given one or is the default
 :    component role.
 :

 :
 :
The set of concepts to search in is specified as a parameter.

 :
 :
Language matching can either be exact, if no options are given,
 : or approximated, if at least one of the following options is given:

 :

 :
MatchDown: whether to match a more specific language, e.g.:
 :       "en" will match labels which language is "en" or "en-US".

 :
MatchUp: whether to match a less specific language, e.g.:
 :       "en-US" will match labels which language is "en-US" or "en".

 :
MatchAnyVariant: whether to match a different variant of the same
 :       language, e.g.: "en-US" will match labels which language is "en-US"
 :       or "en-UK".

 :

 :
 : @param $concept-names the concepts names.
 : @param $label-roles the label role.
 : @param $languages the label language.
 : @param $concepts the concepts in which the labels will be
 :                  searched.
 : @param $entities the entities in which entity labels will be searched.
 : @param $options Optional parameters to control language matching.
 :
 : @return the matching labels (one associated with each input concept, as
 : an object).
 :)
declare function labels:labels(
    $concept-names as string*,
    $label-roles as string*,
    $languages as string*,
    $concepts as object*,
    $entities as object*,
    $options as object?
  ) as object
{
  let $concepts := ($labels:standard-concepts, $concepts)
  return {|
    let $normalized-languages as string* := $languages ! labels:normalize-language($$)
    return (
      for $concept as object in $concepts
      where ($concepts:ALL_CONCEPT_NAMES, $concept.$concepts:NAME) = $concept-names
      group by $concept.$concepts:NAME
      let $concept-labels as object* :=
        $concept.$concepts:LABELS[][$$.Role = $label-roles]
      let $available-languages as string* :=
        distinct-values($concept-labels.Language)
      let $approximate-languages as string* := labels:approximate-languages(
        $available-languages,
        $normalized-languages,
        $options
      )
      let $english-languages as string* := labels:approximate-languages(
        $available-languages,
        "en",
        $options
      )
      let $perfect-matches as object* :=
        $concept-labels[$$.Language = $normalized-languages]
      let $approximate-matches as object* :=
        $concept-labels[$$.Language = $approximate-languages]
      let $english-matches as object* :=
        $concept-labels[$$.Language = $english-languages]
      let $label as string? :=
        ($perfect-matches.Value,
         $approximate-matches.Value,
         $english-matches.Value,
         $concept-labels.Value,
         $concept.Label)[not $$ instance of null][1]
      where exists($label)
      return {
        $concept.Name : $label
      },

      for $concept in $concept-names
      where not (($concepts:ALL_CONCEPT_NAMES, $concepts.$concepts:NAME) = $concept)
      let $label as string* :=
          switch(true)
            case starts-with($concept, "iso4217:")
            return substring($concept, 9)
            case $concept castable as date
            return format-date(date($concept), "[MNn] [D], [Y]", "en", (), ())
            case (every $date in tokenize($concept, "/") satisfies $date castable as date)
            return "From " || string-join(
                     for $date in tokenize($concept, "/")
                     return format-date(date($date), "[MNn] [D], [Y]", "en", (), ()),
                   " to ")
            case contains($concept, " ")
            return
              switch(true)
              case $concept = entities:eid($entities) and $normalized-languages = ("ja")
              return ($entities[entities:eid($$) = $concept].Profiles.SEC.EntityRegistrantName,
                       $entities[entities:eid($$) = $concept].Profiles.FSA.SubmitterName)[1]
              case $concept = entities:eid($entities)
              return ($entities[entities:eid($$) = $concept].Profiles.SEC.CompanyName,
                       $entities[entities:eid($$) = $concept].Profiles.FSA.SubmitterNameAlphabetic)[1]
              default return ()
           default return ()
      where exists($label)
      return {
        $concept : $label
      }
    )
  |}
};

(:~
 :
Retrieves all the labels with the given label role and language for
 : all concepts used in the fact and matching a concept in the list of
 : concepts. Concepts used in a fact include not only those from the
 : 'xbrl:Concept' aspect, but also Members of any custom axis.

 :
 :
Matching concepts are those which:
 :  - concept name matches a given one,
 :  - archive number matches that of a given component,
 :  - component role matches that of a given component or is the default
 :    component role.
 :

 :
 :
The set of concepts to search in is specified as a parameter.

 :
 :
Language matching can either be exact, if no options are given,
 : or approximated, if at least one of the following options is given:

 :

 :
MatchDown: whether to match a more specific language, e.g.:
 :       "en" will match labels which language is "en" or "en-US".

 :
MatchUp: whether to match a less specific language, e.g.:
 :       "en-US" will match labels which language is "en-US" or "en".

 :
MatchAnyVariant: whether to match a different variant of the same
 :       language, e.g.: "en-US" will match labels which language is "en-US"
 :       or "en-UK".

 :

 :
 : @param $facts a sequence of facts.
 : @param $label-role the label role.
 : @param $language the label language.
 : @param $concepts the concepts in which the labels will be
 :                  searched (in the version-7 format).
 : @param $options optional parameters to control language matching.
 :
 : @return an object with matching concepts as keys and labels as values.
 :)
declare function labels:labels-for-facts(
    $facts as object*,
    $label-role as string,
    $language as string,
    $concepts as object*,
    $entities as object*,
    $options as object?
  ) as object?
{
    for $facts in $facts
    group by $archive := $facts."Aspects"."xbrl28:Archive"
    let $concept-names as string* :=
        distinct-values((
          values($facts.Aspects),
          keys($facts.Aspects)
    )[$$ instance of string])
    return
        {|
            labels:labels(
                    $concept-names,
                    $label-role,
                    $language,
                    $concepts,
                    $entities,
                    $options)
        |}
};

(:~
 :
Normalizes the language code. This normalized language code can then
 : be used to find the right labels in the concepts collection.

 :
 : @param $language the language identifier.
 :
 : @return the normalized language.
 :)
declare function labels:normalize-language($language as string) as string
{
  replace(lower-case($language), "_", "-")
};

declare %private function labels:approximate-languages(
    $all-languages as string*,
    $normalized-language as string,
    $options as object?
  ) as string*
{
    if(not $options.MatchDown cast as boolean? eq false)
    then $all-languages[starts-with($$, $normalized-language)]
    else (),
    if(not $options.MatchUp cast as boolean? eq false)
    then $all-languages[starts-with($normalized-language, $$)]
    else (),
    if ((not $options.MatchAnyVariant cast as boolean? eq false) and contains($normalized-language, "-"))
    then
      $all-languages[starts-with($$, substring-before($normalized-language, "-") || "-")]
    else ()
};

(:~
 :
Transforms concept labels into XBRL labelLink.

 :
 : @param $concepts the concepts to transform.
 :
 : @return the labelLink element to be put into a linkbase.
 :)
declare function labels:to-xml(
    $concepts as object*,
    $taxonomyName as string) as element()
{
  <link:labelLink xmlns:link="http://www.xbrl.org/2003/linkbase" xlink:type="extended" xlink:role="http://www.xbrl.org/2003/role/link">
  {
    for $concept as object in $concepts
    let $name as string := substring-after($concept.Name, ":")
    let $id as string := replace($concept.Name, ":", "_")
    return
      (
        <link:loc xlink:type="locator" xlink:href="{$taxonomyName}.xsd#{$id}" xlink:label="{$id}" />,
        for $label at $pos in $concept.Labels[]
        let $role as string := ($concept.Role, "http://www.xbrl.org/2003/role/label")[1]
        let $lang as string := ($concept.Language, "de")[1]
        let $value as string? := $concept.Value
        let $labelID as string := $id || "_label" || $pos
        return (
            <link:label xlink:role="{$role}"
                   xlink:label="{$labelID}"
                   id="{$labelID}"
                   xml:lang="{$lang}"
                   xlink:type="resource">{$value}</link:label>,
            <link:labelArc xlink:type="arc"
                      xlink:arcrole="http://www.xbrl.org/2003/arcrole/concept-label"
                      xlink:from="{$id}"
                      xlink:to="{$labelID}" />
        )
      )
  }</link:labelLink>
};