Update facttable-for-component.jq

Update facttable-for-component.jq

jsoniq version "1.0";

import module namespace components = "http://28.io/modules/xbrl/components";
import module namespace filings = "http://28.io/modules/xbrl/profiles/sec/filings";
import module namespace sec = "http://28.io/modules/xbrl/profiles/sec/core";
import module namespace entities = "http://28.io/modules/xbrl/entities";
import module namespace hypercubes = "http://28.io/modules/xbrl/hypercubes";
import module namespace conversion = "http://28.io/modules/xbrl/conversion";
import module namespace networks = "http://28.io/modules/xbrl/networks";
import module namespace concept-maps = "http://28.io/modules/xbrl/concept-maps";
import module namespace concepts = "http://28.io/modules/xbrl/concepts";
import module namespace facts = "http://28.io/modules/xbrl/facts";
import module namespace rules = "http://28.io/modules/xbrl/rules";

import module namespace fiscal-core = "http://28.io/modules/xbrl/profiles/sec/fiscal/core";
import module namespace companies = "http://28.io/modules/xbrl/profiles/sec/companies";
import module namespace sec-networks = "http://28.io/modules/xbrl/profiles/sec/networks";

import module namespace response = "http://www.28msec.com/modules/http-response";

import module namespace session = "http://apps.28.io/session";
import module namespace api = "http://apps.28.io/api";

(: Query parameters :)
declare  %rest:case-insensitive                 variable $token              as string? external;
declare  %rest:env                              variable $request-uri        as string  external;
declare  %rest:case-insensitive                 variable $format             as string? external;
declare  %rest:case-insensitive %rest:distinct  variable $cik                as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $tag                as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $ticker             as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $sic                as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $fiscalYear         as string* external := "LATEST";
declare  %rest:case-insensitive %rest:distinct  variable $fiscalPeriod       as string* external := "FY";
declare  %rest:case-insensitive %rest:distinct  variable $aid                as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $networkIdentifier  as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $cid                as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $concept            as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $reportElement      as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $disclosure         as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $label              as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $rollup             as string* external;
declare  %rest:case-insensitive                 variable $map                as string? external;
declare  %rest:case-insensitive                 variable $validate           as boolean external := false;
declare  %rest:case-insensitive                 variable $labels             as boolean external := false;
declare  %rest:case-insensitive                 variable $additional-rules   as string? external;
declare  %rest:case-insensitive                 variable $profile-name  as string  external := "sec";
declare  %rest:case-insensitive %rest:distinct  variable $role               as string* external;

session:audit-call($token);

(: Post-processing :)
let $format as string? := api:preprocess-format($format, $request-uri)
let $fiscalYear as integer* := api:preprocess-fiscal-years($fiscalYear)
let $fiscalPeriod as string* := api:preprocess-fiscal-periods($fiscalPeriod)
let $tag as string* := api:preprocess-tags($tag)
let $reportElement := ($reportElement, $concept)
let $networkIdentifier := distinct-values(($networkIdentifier, $role))

(: Object resolution :)
let $entities as object* :=
    companies:companies(
        $cik,
        $tag,
        $ticker,
        $sic)
let $archive as object? := fiscal-core:filings(
    $entities,
    $fiscalPeriod,
    $fiscalYear,
    $aid)
let $entity    := entities:entities($archive.Entity)
let $components  :=
    switch($profile-name)
    case "sec" return sec-networks:components(
        $archive,
        $cid,
        $reportElement,
        $disclosure,
        $networkIdentifier,
        $label)
    default return
        switch(true)
        case (exists($networkIdentifier) and exists($aid))
        return components:components-for-archives-and-roles($aid, $networkIdentifier)
        case exists($aid)
        return components:components-for-archives($aid)
        default
        return {
          response:status-code(400);
          session:error("Archive ID missing.", $format)
        }
let $component as object? := $components[1] (: only one for know :)
let $cid as string? := components:cid($component)
let $rules as object* := if(exists($additional-rules)) then rules:rules($additional-rules) else ()

(: Fact resolution :)
let $facts :=
    if (exists($rollup) and $profile-name eq "sec")
         then
             let $calc-network := networks:networks-for-components-and-short-names($component, $networks:CALCULATION_NETWORK)
             let $hc := hypercubes:hypercubes-for-components($component, "xbrl:DefaultHypercube")
             let $hc := hypercubes:modify-hypercube($hc, {
                 "sec:FiscalYear" : { Type: "integer", Default: null },
                 "sec:FiscalPeriod" : { Type: "string", Default: null },
                 "sec:FiscalPeriodType" : { Type: "string", Default: null }
             })
             let $options as object? := if(exists($rules)) then { Rules: [ $rules ] } else ()
             let $p := hypercubes:populate-networks-with-facts($calc-network, $hc, $archive, $options)
             let $map := concept-maps:concept-maps($map)
             let $concepts :=
                if (not $map instance of null)
                then
                    for $d in $rollup[]
                    return
                        keys(descendant-objects($p)[$$.Name = keys($map.Trees($d).To)][1].To)
                else
                    for $d in $rollup[]
                    return ($d, keys(descendant-objects($p)[$$.Name eq $d].To))
             return sec:facts-for-archives-and-concepts($archive, $concepts, { Hypercube: $hc })
         else components:facts(
            $component,
            {|
                {
                    FilterOverride : {
                        "sec:FiscalPeriod" : { Type: "string", Default: null },
                        "sec:FiscalYear" : { Type: "string", Default: null }
                    }
                }[$profile-name eq "sec"],
                { Validate: $validate },
                { Rules : [ $rules ] }[exists($rules)]
            |}
        )

let $facts :=
    if(not $labels)
    then $facts
    else
        (: if labels are requested by the labels=true parameter then also add labels for concepts :)
        let $concepts as object* :=
            concepts:concepts-for-components($concepts:ALL_CONCEPT_NAMES, $component)
        for $fact in $facts
        let $labels :=
            facts:labels($fact, $component.Role, $concepts:STANDARD_LABEL_ROLE,$concepts:AMERICAN_ENGLISH, $concepts, ())
        return
            {|
                trim($fact, "Labels"),
                { Labels : $labels }
            |}
let $facts := api:normalize-facts($facts)

let $results :=
    switch ($format)
    case "xml" return {
        response:serialization-parameters({"omit-xml-declaration" : false, indent : true });
        (session:comment("xml", {
                    NumFacts : count($facts),
                    TotalNumFacts: session:num-facts(),
                    TotalNumArchives: session:num-archives(),
                    TotalNumEntities: session:num-entities()
                }),
        switch($profile-name)
        case "sec" return <FactTable entityRegistrantName="{$entity.Profiles.SEC.CompanyName}"
            cik="{$entity._id}"
            tableName="{sec-networks:tables($component, {IncludeImpliedTable: true}).Name}"
            label="{$component.Label}"
            accessionNumber="{$component.Archive}"
            networkIdentifier="{$component.Role}"
            formType="{$archive.Profiles.SEC.FormType}"
            fiscalPeriod="{$archive.Profiles.SEC.Fiscal.DocumentFiscalPeriodFocus}"
            fiscalYear="{$archive.Profiles.SEC.Fiscal.DocumentFiscalYearFocus}"
            acceptanceDatetime="{filings:acceptance-dateTimes($archive)}"
            disclosure="{$component.Profiles.SEC.Disclosure}"
            >{
            conversion:facts-to-xml($facts, { Caller: "Component" })
        }</FactTable>
        default return <FactTable
            tableName="{sec-networks:tables($component, {IncludeImpliedTable: true}).Name}"
            label="{$component.Label}"
            archive="{$component.Archive}"
            role="{$component.Role}"
            >{
            conversion:facts-to-xml($facts, { Caller: "Component" })
        }</FactTable>)
    }
    case "text" case "csv" return {
        response:content-type("text/csv");
        response:header("Content-Disposition", "attachment; filename=facttable-" || $cid || ".csv");
        conversion:facts-to-csv($facts, { Caller: "Component"})
    }
    case "excel" return {
        response:content-type("application/vnd.ms-excel");
        response:header("Content-Disposition", "attachment; filename=facttable-" || $cid || ".csv");
        conversion:facts-to-csv($facts, { Caller: "Component"})
    }
    default return {
        response:content-type("application/json");
        response:serialization-parameters({"indent" : true});
        {|
            {
                CIK : $entity._id,
                EntityRegistrantName : $entity.Profiles.SEC.CompanyName,
                TableName : sec-networks:tables($component, {IncludeImpliedTable: true}).Name,
                Label : $component.Label,
                AccessionNumber : $component.Archive,
                FormType : $archive.Profiles.SEC.FormType,
                FiscalPeriod : $archive.Profiles.SEC.Fiscal.DocumentFiscalPeriodFocus,
                FiscalYear : $archive.Profiles.SEC.Fiscal.DocumentFiscalYearFocus,
                AcceptanceDatetime : filings:acceptance-dateTimes($archive),
                NetworkIdentifier: $component.Role,
                Disclosure : $component.Profiles.SEC.Disclosure,
                FactTable : [ $facts ]
            }[$profile-name eq "sec"],
            {
                Archive : $component.Archive,
                Role: $component.Role,
                TableName : keys($component.Hypercubes),
                Label : $component.Label,
                FactTable : [ $facts ]
            }[$profile-name ne "sec"],
            session:comment(
                "json",
                {
                    NumFacts : count($facts),
                    TotalNumFacts: session:num-facts(),
                    TotalNumArchives: session:num-archives(),
                    TotalNumEntities: session:num-entities()
                }
            )
        |}
    }
return api:check-and-return-results($token, $results, $format)

jsoniq version "1.0";

import module namespace components = "http://28.io/modules/xbrl/components";
import module namespace filings = "http://28.io/modules/xbrl/profiles/sec/filings";
import module namespace sec = "http://28.io/modules/xbrl/profiles/sec/core";
import module namespace entities = "http://28.io/modules/xbrl/entities";
import module namespace hypercubes = "http://28.io/modules/xbrl/hypercubes";
import module namespace conversion = "http://28.io/modules/xbrl/conversion";
import module namespace networks = "http://28.io/modules/xbrl/networks";
import module namespace concept-maps = "http://28.io/modules/xbrl/concept-maps";
import module namespace concepts = "http://28.io/modules/xbrl/concepts";
import module namespace facts = "http://28.io/modules/xbrl/facts";
import module namespace rules = "http://28.io/modules/xbrl/rules";

import module namespace fiscal-core = "http://28.io/modules/xbrl/profiles/sec/fiscal/core";
import module namespace companies = "http://28.io/modules/xbrl/profiles/sec/companies";
import module namespace sec-networks = "http://28.io/modules/xbrl/profiles/sec/networks";

import module namespace response = "http://www.28msec.com/modules/http-response";

import module namespace session = "http://apps.28.io/session";
import module namespace api = "http://apps.28.io/api";

(: Query parameters :)
declare  %rest:case-insensitive                 variable $token              as string? external;
declare  %rest:env                              variable $request-uri        as string  external;
declare  %rest:case-insensitive                 variable $format             as string? external;
declare  %rest:case-insensitive %rest:distinct  variable $cik                as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $tag                as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $ticker             as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $sic                as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $fiscalYear         as string* external := "LATEST";
declare  %rest:case-insensitive %rest:distinct  variable $fiscalPeriod       as string* external := "FY";
declare  %rest:case-insensitive %rest:distinct  variable $aid                as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $networkIdentifier  as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $cid                as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $concept            as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $reportElement      as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $disclosure         as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $label              as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $rollup             as string* external;
declare  %rest:case-insensitive                 variable $map                as string? external;
declare  %rest:case-insensitive                 variable $validate           as boolean external := false;
declare  %rest:case-insensitive                 variable $labels             as boolean external := false;
declare  %rest:case-insensitive                 variable $additional-rules   as string? external;
declare  %rest:case-insensitive                 variable $profile-name  as string  external := "sec";
declare  %rest:case-insensitive %rest:distinct  variable $role               as string* external;

session:audit-call($token);

(: Post-processing :)
let $format as string? := api:preprocess-format($format, $request-uri)
let $fiscalYear as integer* := api:preprocess-fiscal-years($fiscalYear)
let $fiscalPeriod as string* := api:preprocess-fiscal-periods($fiscalPeriod)
let $tag as string* := api:preprocess-tags($tag)
let $reportElement := ($reportElement, $concept)
let $networkIdentifier := distinct-values(($networkIdentifier, $role))

(: Object resolution :)
let $entities as object* :=
    companies:companies(
        $cik,
        $tag,
        $ticker,
        $sic)
let $archive as object? := fiscal-core:filings(
    $entities,
    $fiscalPeriod,
    $fiscalYear,
    $aid)
let $entity    := entities:entities($archive.Entity)
let $components  :=
    switch($profile-name)
    case "sec" return sec-networks:components(
        $archive,
        $cid,
        $reportElement,
        $disclosure,
        $networkIdentifier,
        $label)
    default return
        switch(true)
        case (exists($networkIdentifier) and exists($aid))
        return components:components-for-archives-and-roles($aid, $networkIdentifier)
        case exists($aid)
        return components:components-for-archives($aid)
        default
        return {
          response:status-code(400);
          session:error("Archive ID missing.", $format)
        }
let $component as object? := $components[1] (: only one for know :)
let $cid as string? := components:cid($component)
let $rules as object* := if(exists($additional-rules)) then rules:rules($additional-rules) else ()

(: Fact resolution :)
let $facts :=
    if (exists($rollup) and $profile-name eq "sec")
         then
             let $calc-network := networks:networks-for-components-and-short-names($component, $networks:CALCULATION_NETWORK)
             let $hc := hypercubes:hypercubes-for-components($component, "xbrl:DefaultHypercube")
             let $hc := hypercubes:modify-hypercube($hc, {
                 "sec:FiscalYear" : { Type: "integer", Default: null },
                 "sec:FiscalPeriod" : { Type: "string", Default: null }
             })
             let $options as object? := if(exists($rules)) then { Rules: [ $rules ] } else ()
             let $p := hypercubes:populate-networks-with-facts($calc-network, $hc, $archive, $options)
             let $map := concept-maps:concept-maps($map)
             let $concepts :=
                if (not $map instance of null)
                then
                    for $d in $rollup[]
                    return
                        keys(descendant-objects($p)[$$.Name = keys($map.Trees($d).To)][1].To)
                else
                    for $d in $rollup[]
                    return ($d, keys(descendant-objects($p)[$$.Name eq $d].To))
             return sec:facts-for-archives-and-concepts($archive, $concepts, { Hypercube: $hc })
         else components:facts(
            $component,
            {|
                {
                    FilterOverride : {
                        "sec:FiscalPeriod" : { Type: "string", Default: null },
                        "sec:FiscalYear" : { Type: "string", Default: null }
                    }
                }[$profile-name eq "sec"],
                { Validate: $validate },
                { Rules : [ $rules ] }[exists($rules)]
            |}
        )

let $facts :=
    if(not $labels)
    then $facts
    else
        (: if labels are requested by the labels=true parameter then also add labels for concepts :)
        let $concepts as object* :=
            concepts:concepts-for-components($concepts:ALL_CONCEPT_NAMES, $component)
        for $fact in $facts
        let $labels :=
            facts:labels($fact, $component.Role, $concepts:STANDARD_LABEL_ROLE,$concepts:AMERICAN_ENGLISH, $concepts, ())
        return
            {|
                trim($fact, "Labels"),
                { Labels : $labels }
            |}
let $facts := api:normalize-facts($facts)

let $results :=
    switch ($format)
    case "xml" return {
        response:serialization-parameters({"omit-xml-declaration" : false, indent : true });
        (session:comment("xml", {
                    NumFacts : count($facts),
                    TotalNumFacts: session:num-facts(),
                    TotalNumArchives: session:num-archives(),
                    TotalNumEntities: session:num-entities()
                }),
        switch($profile-name)
        case "sec" return <FactTable entityRegistrantName="{$entity.Profiles.SEC.CompanyName}"
            cik="{$entity._id}"
            tableName="{sec-networks:tables($component, {IncludeImpliedTable: true}).Name}"
            label="{$component.Label}"
            accessionNumber="{$component.Archive}"
            networkIdentifier="{$component.Role}"
            formType="{$archive.Profiles.SEC.FormType}"
            fiscalPeriod="{$archive.Profiles.SEC.Fiscal.DocumentFiscalPeriodFocus}"
            fiscalYear="{$archive.Profiles.SEC.Fiscal.DocumentFiscalYearFocus}"
            acceptanceDatetime="{filings:acceptance-dateTimes($archive)}"
            disclosure="{$component.Profiles.SEC.Disclosure}"
            >{
            conversion:facts-to-xml($facts, { Caller: "Component" })
        }</FactTable>
        default return <FactTable
            tableName="{sec-networks:tables($component, {IncludeImpliedTable: true}).Name}"
            label="{$component.Label}"
            archive="{$component.Archive}"
            role="{$component.Role}"
            >{
            conversion:facts-to-xml($facts, { Caller: "Component" })
        }</FactTable>)
    }
    case "text" case "csv" return {
        response:content-type("text/csv");
        response:header("Content-Disposition", "attachment; filename=facttable-" || $cid || ".csv");
        conversion:facts-to-csv($facts, { Caller: "Component"})
    }
    case "excel" return {
        response:content-type("application/vnd.ms-excel");
        response:header("Content-Disposition", "attachment; filename=facttable-" || $cid || ".csv");
        conversion:facts-to-csv($facts, { Caller: "Component"})
    }
    default return {
        response:content-type("application/json");
        response:serialization-parameters({"indent" : true});
        {|
            {
                CIK : $entity._id,
                EntityRegistrantName : $entity.Profiles.SEC.CompanyName,
                TableName : sec-networks:tables($component, {IncludeImpliedTable: true}).Name,
                Label : $component.Label,
                AccessionNumber : $component.Archive,
                FormType : $archive.Profiles.SEC.FormType,
                FiscalPeriod : $archive.Profiles.SEC.Fiscal.DocumentFiscalPeriodFocus,
                FiscalYear : $archive.Profiles.SEC.Fiscal.DocumentFiscalYearFocus,
                AcceptanceDatetime : filings:acceptance-dateTimes($archive),
                NetworkIdentifier: $component.Role,
                Disclosure : $component.Profiles.SEC.Disclosure,
                FactTable : [ $facts ]
            }[$profile-name eq "sec"],
            {
                Archive : $component.Archive,
                Role: $component.Role,
                TableName : keys($component.Hypercubes),
                Label : $component.Label,
                FactTable : [ $facts ]
            }[$profile-name ne "sec"],
            session:comment(
                "json",
                {
                    NumFacts : count($facts),
                    TotalNumFacts: session:num-facts(),
                    TotalNumArchives: session:num-archives(),
                    TotalNumEntities: session:num-entities()
                }
            )
        |}
    }
return api:check-and-return-results($token, $results, $format)


:pencil: Implement Dennis' comment.

:pencil: Implement Dennis' comment.

jsoniq version "1.0";

import module namespace components = "http://28.io/modules/xbrl/components";
import module namespace filings = "http://28.io/modules/xbrl/profiles/sec/filings";
import module namespace sec = "http://28.io/modules/xbrl/profiles/sec/core";
import module namespace entities = "http://28.io/modules/xbrl/entities";
import module namespace hypercubes = "http://28.io/modules/xbrl/hypercubes";
import module namespace conversion = "http://28.io/modules/xbrl/conversion";
import module namespace networks = "http://28.io/modules/xbrl/networks";
import module namespace concept-maps = "http://28.io/modules/xbrl/concept-maps";
import module namespace rules = "http://28.io/modules/xbrl/rules";
import module namespace labels = "http://28.io/modules/xbrl/labels";

import module namespace multiplexer = "http://28.io/modules/xbrl/profiles/multiplexer";
import module namespace fiscal-core = "http://28.io/modules/xbrl/profiles/sec/fiscal/core";

import module namespace config = "http://apps.28.io/config";
import module namespace session = "http://apps.28.io/session";
import module namespace api = "http://apps.28.io/api";

declare option rest:response "first-item";

(: Query parameters :)
declare  %rest:env                              variable $request-uri        as string  external;
declare  %rest:case-insensitive                 variable $format             as string? external;
declare  %rest:case-insensitive %rest:distinct  variable $cik                as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $edinetcode         as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $tag                as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $ticker             as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $sic                as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $fiscalYear         as string* external := "ALL";
declare  %rest:case-insensitive %rest:distinct  variable $fiscalPeriod       as string* external := "ALL";
declare  %rest:case-insensitive %rest:distinct  variable $fiscalPeriodType   as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $filingKind         as string* external := ();
declare  %rest:case-insensitive %rest:distinct  variable $eid                as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $aid                as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $networkIdentifier  as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $cid                as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $concept            as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $reportElement      as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $disclosure         as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $label              as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $rollup             as string* external;
declare  %rest:case-insensitive                 variable $map                as string? external;
declare  %rest:case-insensitive                 variable $validate           as boolean external := false;
declare  %rest:case-insensitive                 variable $labels             as boolean external := false;
declare  %rest:case-insensitive                 variable $merge              as boolean external := false;
declare  %rest:case-insensitive                 variable $additional-rules   as string? external;
declare  %rest:case-insensitive                 variable $profile-name       as string  external := $config:profile-name;
declare  %rest:case-insensitive %rest:distinct  variable $role               as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $hypercube          as string* external;
declare  %rest:case-insensitive                 variable $language           as string  external := "en-US";
declare  %rest:case-insensitive                 variable $count              as boolean external := false;
declare  %rest:case-insensitive                 variable $override           as boolean external := false;

(: Post-processing :)
let $format as string? := api:preprocess-format($format, $request-uri)
let $fiscalYear as integer* := api:preprocess-fiscal-years($fiscalYear)
let $fiscalPeriod as string* := api:preprocess-fiscal-periods($fiscalPeriod)
let $tag as string* := api:preprocess-tags($tag)
let $reportElement := ($reportElement, $concept)
let $networkIdentifier := distinct-values(($networkIdentifier, $role))

let $cik as string* :=
    switch($profile-name)
    case "sec" return $cik
    case "japan" return $edinetcode
    default return ()

(: Entity resolution :)
let $entities as object* := multiplexer:entities(
  $profile-name,
  $eid,
  $cik,
  $tag,
  $ticker,
  $sic,
  (),
  (),
  (),
  ())

let $archives as object* := multiplexer:filings(
  $profile-name,
  $entities,
  $fiscalPeriod,
  $fiscalYear,
  $filingKind,
  $aid)

let $archives-not-found as boolean :=
  exists(($entities, $fiscalPeriod, $fiscalYear, $filingKind, $aid)) and empty($archives)

let $entities as object* :=
    ($entities[entities:eid($$) = $archives.Entity],
    let $not-found := $archives.Entity[not entities:eid($entities) = $$]
    where exists($not-found)
    return entities:entities($not-found))

let $entities-not-found as boolean :=
  exists(($eid, $cik, $tag, $ticker, $sic)) and empty($entities)

let $components as object* :=
    multiplexer:components(
      $profile-name,
      $archives,
      $cid,
      $reportElement,
      $disclosure,
      $networkIdentifier,
      $label[$profile-name ne "sec"],
      $label[$profile-name eq "sec"]
    )

let $component as object? := if($merge) then components:merge($components) else $components[1]

let $hypercubes as string* := components:hypercubes($component)

let $hypercubes as string* := if(empty($hypercube))
                              then $hypercubes
                              else $hypercubes[$$ = $hypercube]

let $components-not-found as boolean :=
  exists(($archives, $cid, $reportElement, $disclosure, $networkIdentifier, $label, $hypercube)) and empty($hypercubes)

let $cid as string? := string-join($components ! string(components:cid($$)), "--")
let $rules as object* := if(exists($additional-rules)) then rules:rules($additional-rules) else ()

let $filter-override as object? :=
    if($profile-name eq "sec")
    then fiscal-core:filter-override(
        $entities,
        $fiscalYear,
        $fiscalPeriod,
        $fiscalPeriodType,
        $aid)
    else components:filter-override($entities, $aid)

(: Fact resolution :)
let $facts :=
    if (exists($rollup) and $profile-name eq "sec")
         then
             let $calc-network := networks:networks-for-components-and-short-names($component, $networks:CALCULATION_NETWORK)
             let $hc := hypercubes:hypercubes-for-components($component)[][$$.Name = $hypercubes]
             let $hc := hypercubes:modify-hypercube($hc, {
                 "sec:FiscalYear" : { Type: "integer", Default: null },
                 "sec:FiscalPeriod" : { Type: "string", Default: null },
                 "sec:FiscalPeriodType" : { Type: "string", Default: null }
             })
             let $options as object? := if(exists($rules)) then { Rules: [ $rules ] } else ()
             let $p := hypercubes:populate-networks-with-facts($calc-network, $hc, $archives, $options)
             let $map := concept-maps:concept-maps($map)
             let $concepts :=
                if (not $map instance of null)
                then
                    for $d in $rollup[]
                    return
                        descendant-objects($p)[$$.Name = ($map.Trees[])[$$.Name eq $d].To[].Name][1].To[].Name
                else
                    for $d in $rollup[]
                    return ($d, keys(descendant-objects($p)[$$.Name eq $d].To))
             return sec:facts-for-archives-and-concepts($archives, $concepts, { Hypercube: $hc })
         else components:facts(
            $component,
            {|
                { FilterOverride: $filter-override }[$override],
                { Validate: $validate },
                { Rules : [ $rules ] }[exists($rules)],
                { HypercubeName: $hypercubes[1] }[exists($hypercube)]
            |}
        )

let $facts :=
    if(not $labels)
    then $facts
    else
        (: if labels are requested by the labels=true parameter then also add labels for concepts :)
        let $concepts as object* := $component.Concepts[]
        for $fact in $facts
        let $labels := labels:labels-for-facts(
          $fact,
          $labels:STANDARD_LABEL_ROLE,
          $language,
          $concepts,
          $entities,
          ()
        )
        return
            {|
                trim($fact, "Labels"),
                { Labels : $labels }
            |}
let $facts :=
  if($profile-name eq "sec")
  then api:normalize-facts($facts)
  else $facts

let $result :=
  switch($profile-name)
  case "sec" return {
    CIK : entities:eid($entities),
    EntityRegistrantName : $entities.Profiles.SEC.CompanyName,
    TableName : $hypercubes,
    Label : $component.Label,
    AccessionNumber : $component.Archive,
    FormType : $archives.Profiles.SEC.FormType,
    FiscalPeriod : $archives.Profiles.SEC.Fiscal.DocumentFiscalPeriodFocus,
    FiscalYear : $archives.Profiles.SEC.Fiscal.DocumentFiscalYearFocus,
    AcceptanceDatetime : ($archives ! filings:acceptance-dateTimes($$)),
    NetworkIdentifier: $component.Role,
    Disclosure : $component.Profiles.SEC.Disclosure,
    FactTable : [ if($count) then () else $facts ]
  } default return {
    Archive : $component.Archive,
    Role: $component.Role,
    TableName : $hypercubes,
    Label : $component.Label,
    FactTable : [ if($count) then () else $facts ]
  }

let $comment := {
    NumFacts : count($facts),
    TotalNumFacts: session:num-facts(),
    TotalNumArchives: session:num-archives(),
    TotalNumEntities: session:num-entities()
}

let $serializers := {
    to-xml : function($res as object) as node() {
        switch($profile-name)
        case "sec" return <FactTable entityRegistrantName="{$res.EntityRegistrantName}"
            cik="{$res.CIK}"
            tableName="{$res.TableName}"
            label="{$res.Label}"
            accessionNumber="{$res.AccessionNumber}"
            networkIdentifier="{$res.NetworkIdentifier}"
            formType="{$res.FormType}"
            fiscalPeriod="{$res.FiscalPeriod}"
            fiscalYear="{$res.FiscalYear}"
            acceptanceDatetime="{$res.AcceptanceDatetime}"
            disclosure="{$res.Disclosure}"
            >{
            conversion:facts-to-xml($res.FactTable[], { Caller: "Component" })
        }</FactTable>
        default return <FactTable
            tableName="{$res.TableName}"
            label="{$res.Label}"
            archive="{$res.Archive}"
            role="{$res.Role}"
            >{
            conversion:facts-to-xml($res.FactTable[], { Caller: "Component" })
        }</FactTable>
    },
    to-csv : function($res as object) as string {
        string-join(conversion:facts-to-csv($res.FactTable[], { Caller: "Component"}))
    }
}
return switch(true)
       case $entities-not-found return api:not-found("entity")
       case $archives-not-found return api:not-found("archive")
       case $components-not-found return api:not-found("components")
       default return api:serialize($result, $comment, $serializers, $format, "facttable-" || $cid)

jsoniq version "1.0";

import module namespace components = "http://28.io/modules/xbrl/components";
import module namespace filings = "http://28.io/modules/xbrl/profiles/sec/filings";
import module namespace sec = "http://28.io/modules/xbrl/profiles/sec/core";
import module namespace entities = "http://28.io/modules/xbrl/entities";
import module namespace hypercubes = "http://28.io/modules/xbrl/hypercubes";
import module namespace conversion = "http://28.io/modules/xbrl/conversion";
import module namespace networks = "http://28.io/modules/xbrl/networks";
import module namespace concept-maps = "http://28.io/modules/xbrl/concept-maps";
import module namespace rules = "http://28.io/modules/xbrl/rules";
import module namespace labels = "http://28.io/modules/xbrl/labels";

import module namespace multiplexer = "http://28.io/modules/xbrl/profiles/multiplexer";
import module namespace fiscal-core = "http://28.io/modules/xbrl/profiles/sec/fiscal/core";

import module namespace config = "http://apps.28.io/config";
import module namespace session = "http://apps.28.io/session";
import module namespace api = "http://apps.28.io/api";

declare option rest:response "first-item";

(: Query parameters :)
declare  %rest:env                              variable $request-uri        as string  external;
declare  %rest:case-insensitive                 variable $format             as string? external;
declare  %rest:case-insensitive %rest:distinct  variable $cik                as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $edinetcode         as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $tag                as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $ticker             as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $sic                as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $fiscalYear         as string* external := "ALL";
declare  %rest:case-insensitive %rest:distinct  variable $fiscalPeriod       as string* external := "ALL";
declare  %rest:case-insensitive %rest:distinct  variable $fiscalPeriodType   as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $filingKind         as string* external := ();
declare  %rest:case-insensitive %rest:distinct  variable $eid                as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $aid                as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $networkIdentifier  as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $cid                as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $concept            as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $reportElement      as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $disclosure         as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $label              as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $rollup             as string* external;
declare  %rest:case-insensitive                 variable $map                as string? external;
declare  %rest:case-insensitive                 variable $validate           as boolean external := false;
declare  %rest:case-insensitive                 variable $labels             as boolean external := false;
declare  %rest:case-insensitive                 variable $merge              as boolean external := false;
declare  %rest:case-insensitive                 variable $additional-rules   as string? external;
declare  %rest:case-insensitive                 variable $profile-name       as string  external := $config:profile-name;
declare  %rest:case-insensitive %rest:distinct  variable $role               as string* external;
declare  %rest:case-insensitive %rest:distinct  variable $hypercube          as string* external;
declare  %rest:case-insensitive                 variable $language           as string  external := "en-US";
declare  %rest:case-insensitive                 variable $count              as boolean external := false;
declare  %rest:case-insensitive                 variable $override           as boolean external := false;

(: Post-processing :)
let $format as string? := api:preprocess-format($format, $request-uri)
let $fiscalYear as integer* := api:preprocess-fiscal-years($fiscalYear)
let $fiscalPeriod as string* := api:preprocess-fiscal-periods($fiscalPeriod)
let $tag as string* := api:preprocess-tags($tag)
let $reportElement := ($reportElement, $concept)
let $networkIdentifier := distinct-values(($networkIdentifier, $role))

let $cik as string* :=
    switch($profile-name)
    case "sec" return $cik
    case "japan" return $edinetcode
    default return ()

(: Entity resolution :)
let $entities as object* := multiplexer:entities(
  $profile-name,
  $eid,
  $cik,
  $tag,
  $ticker,
  $sic,
  (),
  (),
  (),
  ())

let $archives as object* := multiplexer:filings(
  $profile-name,
  $entities,
  $fiscalPeriod,
  $fiscalYear,
  $filingKind,
  $aid)

let $archives-not-found as boolean :=
  exists(($entities, $fiscalPeriod, $fiscalYear, $filingKind, $aid)) and empty($archives)

let $entities as object* :=
    ($entities[entities:eid($$) = $archives.Entity],
    let $not-found := $archives.Entity[not entities:eid($entities) = $$]
    where exists($not-found)
    return entities:entities($not-found))

let $entities-not-found as boolean :=
  exists(($eid, $cik, $tag, $ticker, $sic)) and empty($entities)

let $components as object* :=
    multiplexer:components(
      $profile-name,
      $archives,
      $cid,
      $reportElement,
      $disclosure,
      $networkIdentifier,
      $label[$profile-name ne "sec"],
      $label[$profile-name eq "sec"]
    )

let $component as object? := if($merge) then components:merge($components) else $components[1]

let $hypercubes as string* := components:hypercubes($component)

let $hypercubes as string* := if(empty($hypercube))
                              then $hypercubes
                              else $hypercubes[$$ = $hypercube]

let $components-not-found as boolean :=
  exists(($archives, $cid, $reportElement, $disclosure, $networkIdentifier, $label, $hypercube)) and empty($hypercubes)

let $cid as string? := string-join($components ! string(components:cid($$)), "--")
let $rules as object* := if(exists($additional-rules)) then rules:rules($additional-rules) else ()

let $filter-override as object? :=
    if($profile-name eq "sec")
    then fiscal-core:filter-override(
        $entities,
        $fiscalYear,
        $fiscalPeriod,
        $fiscalPeriodType,
        $aid)
    else components:filter-override($entities, $aid)

(: Fact resolution :)
let $facts :=
    if (exists($rollup) and $profile-name eq "sec")
         then
             let $calc-network := networks:networks-for-components-and-short-names($component, $networks:CALCULATION_NETWORK)
             let $hc := hypercubes:hypercubes-for-components($component)[]
             let $hc := hypercubes:modify-hypercube($hc, {
                 "sec:FiscalYear" : { Type: "integer", Default: null },
                 "sec:FiscalPeriod" : { Type: "string", Default: null },
                 "sec:FiscalPeriodType" : { Type: "string", Default: null }
             })
             let $options as object? := if(exists($rules)) then { Rules: [ $rules ] } else ()
             let $p := hypercubes:populate-networks-with-facts($calc-network, $hc, $archives, $options)
             let $map := concept-maps:concept-maps($map)
             let $concepts :=
                if (not $map instance of null)
                then
                    for $d in $rollup[]
                    return
                        descendant-objects($p)[$$.Name = ($map.Trees[])[$$.Name eq $d].To[].Name][1].To[].Name
                else
                    for $d in $rollup[]
                    return ($d, keys(descendant-objects($p)[$$.Name eq $d].To))
             return sec:facts-for-archives-and-concepts($archives, $concepts, { Hypercube: $hc })
         else components:facts(
            $component,
            {|
                { FilterOverride: $filter-override }[$override],
                { Validate: $validate },
                { Rules : [ $rules ] }[exists($rules)],
                { HypercubeName: $hypercubes[1] }[exists($hypercube)]
            |}
        )

let $facts :=
    if(not $labels)
    then $facts
    else
        (: if labels are requested by the labels=true parameter then also add labels for concepts :)
        let $concepts as object* := $component.Concepts[]
        for $fact in $facts
        let $labels := labels:labels-for-facts(
          $fact,
          $labels:STANDARD_LABEL_ROLE,
          $language,
          $concepts,
          $entities,
          ()
        )
        return
            {|
                trim($fact, "Labels"),
                { Labels : $labels }
            |}
let $facts :=
  if($profile-name eq "sec")
  then api:normalize-facts($facts)
  else $facts

let $result :=
  switch($profile-name)
  case "sec" return {
    CIK : entities:eid($entities),
    EntityRegistrantName : $entities.Profiles.SEC.CompanyName,
    TableName : components:hypercubes($component),
    Label : $component.Label,
    AccessionNumber : $component.Archive,
    FormType : $archives.Profiles.SEC.FormType,
    FiscalPeriod : $archives.Profiles.SEC.Fiscal.DocumentFiscalPeriodFocus,
    FiscalYear : $archives.Profiles.SEC.Fiscal.DocumentFiscalYearFocus,
    AcceptanceDatetime : ($archives ! filings:acceptance-dateTimes($$)),
    NetworkIdentifier: $component.Role,
    Disclosure : $component.Profiles.SEC.Disclosure,
    FactTable : [ if($count) then () else $facts ]
  } default return {
    Archive : $component.Archive,
    Role: $component.Role,
    TableName : keys($component.Hypercubes),
    Label : $component.Label,
    FactTable : [ if($count) then () else $facts ]
  }

let $comment := {
    NumFacts : count($facts),
    TotalNumFacts: session:num-facts(),
    TotalNumArchives: session:num-archives(),
    TotalNumEntities: session:num-entities()
}

let $serializers := {
    to-xml : function($res as object) as node() {
        switch($profile-name)
        case "sec" return <FactTable entityRegistrantName="{$res.EntityRegistrantName}"
            cik="{$res.CIK}"
            tableName="{$res.TableName}"
            label="{$res.Label}"
            accessionNumber="{$res.AccessionNumber}"
            networkIdentifier="{$res.NetworkIdentifier}"
            formType="{$res.FormType}"
            fiscalPeriod="{$res.FiscalPeriod}"
            fiscalYear="{$res.FiscalYear}"
            acceptanceDatetime="{$res.AcceptanceDatetime}"
            disclosure="{$res.Disclosure}"
            >{
            conversion:facts-to-xml($res.FactTable[], { Caller: "Component" })
        }</FactTable>
        default return <FactTable
            tableName="{$res.TableName}"
            label="{$res.Label}"
            archive="{$res.Archive}"
            role="{$res.Role}"
            >{
            conversion:facts-to-xml($res.FactTable[], { Caller: "Component" })
        }</FactTable>
    },
    to-csv : function($res as object) as string {
        string-join(conversion:facts-to-csv($res.FactTable[], { Caller: "Component"}))
    }
}
return switch(true)
       case $entities-not-found return api:not-found("entity")
       case $archives-not-found return api:not-found("archive")
       case $components-not-found return api:not-found("components")
       default return api:serialize($result, $comment, $serializers, $format, "facttable-" || $cid)


:pencil: Add test.

:pencil: Add test.

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
};

if(not $config:content[] = ("SEC-big", "SEC-small"))
then true
else
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($config:content[] = "SEC-small") then true else local:test-generic-components(66, {
      profile-name: "generic",
      aid: "0001214659-13-001731"
    }),
    platinumre: if($config:content[] = "SEC-small") then true else test:invoke-and-assert-deep-equal(
      "sections",
      {aid:"0001171500-15-000007"},
      function($b as item*) as item* { count($b.Sections[]) },
      72
    ),
    example1: test:invoke-and-assert-deep-equal(
      "sections",
      {aid:"0000021344-13-000039"},
      function($b as item*) as item* { [ trim($b.Sections[], ("ReportElements", "Components", "Validation")) ] },
      test:get-expected-result("secxbrl/sections-expected1.jq"),
      { NoArrayOrder: true }
    ),
    example1-validate: test:invoke-and-assert-deep-equal(
      "sections",
      {aid:"0000021344-13-000039", validate: "true"},
      function($b as item*) as item* { count($b.Sections[].Validation[]) },
      0
    ),
    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", "Validation")
        ) ]
      },
      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",
            language: "en-US"
            }),
        "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",
            validate: "true",
            language: "en-US"
            })
      },
      { 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
};

if(not $config:content[] = ("SEC-big", "SEC-small"))
then true
else
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($config:content[] = "SEC-small") then true else local:test-generic-components(66, {
      profile-name: "generic",
      aid: "0001214659-13-001731"
    }),
    platinumre: if($config:content[] = "SEC-small") then true else test:invoke-and-assert-deep-equal(
      "sections",
      {aid:"0001171500-15-000007"},
      function($b as item*) as item* { count($b.Sections[]) },
      72
    ),
    example1: test:invoke-and-assert-deep-equal(
      "sections",
      {aid:"0000021344-13-000039"},
      function($b as item*) as item* { [ trim($b.Sections[], ("ReportElements", "Components", "Validation")) ] },
      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", "Validation")
        ) ]
      },
      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",
            language: "en-US"
            }),
        "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",
            validate: "true",
            language: "en-US"
            })
      },
      { NoArrayOrder: true }
    )
})


:arrow_up: Migrate archives module.

:arrow_up: Migrate archives module.

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

(:~
 :
This module provides functions for retrieving metadata about archives.

 :
 :
Archives represent the granularity of "report shipping", i.e., an entity
 : reports one archive at a time. An archive is identified with an AID (archive ID).

 :
 :
Archives are made of reported facts (see facts module),
 : which are structured and organized in components (see components module).

 :
 :
With this module, you can retrieve all archives, or a certain number of archives
 : with their AIDs, or obtain the AID of archives you already have. You can also retrieve
 : all archives submitted by one or several entities.

 :
 :
Archive information is stored in a MongoDB datasource called xbrl.

 :
 : @author Charles Hoffman
 : @author Matthias Brantner
 : @author Dennis Knochenwefel
 : @author Ghislain Fourny
 :
 :)
module namespace archives = "http://28.io/modules/xbrl/archives";

import module namespace mw = "http://28.io/modules/xbrl/data-source-wrapper";

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

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

(:~
 : Name of the collection the archives are stored in.
 :)
declare variable $archives:col as string := "archives";

(:~
 : Name of the field which points to the reporting entity.
 :)
declare variable $archives:ENTITY as string:= "Entity";

(:~
 :
Retrieves all archives.

 :
 : @return all archives.
 :)
declare function archives:archives() as object*
{
  mw:find($archives:col,{})
};

(:~
 :
Retrieves the archives with the given AIDs.

 :
 : @param $id the ids of the archives (AIDs) or the archives themselves.
 :
 : @return the archives with the given AIDs
 :         the empty sequence if no archive was found or if the input is an
 : empty sequence.
 :)
declare function archives:archives($archive-or-ids as item*) as object*
{
  let $ids as string* :=
    for $s in $archive-or-ids
    where $s instance of string
    return $s
  let $archives as object* :=
    for $s in $archive-or-ids
    where $s instance of object
    return $s
  return
    (
      $archives,
      if (exists($ids))
      then mw:find($archives:col,{ "_id" : [ archives:aid($ids) ] })
      else ()
    )
};

(:~
 :
 :
Returns the entities that submitted the supplied archives.

 :
 : @param $archives-or-ids a sequence of archives or their identifiers (AID).
 : @return the submitting entities.
 :
 :)
declare function archives:entities($archives-or-ids as item*) as object*
{
  let $archives := archives:archives($archives-or-ids)
  let $eids := $archives.Entity
  return entities:entities($eids)
};

(:~
 :
Return all archives created by the supplied entities.

 :
 : @param $entities-or-ids arbitrary number of entity objects or EIDs.
 :
 : @return all archives created by these entities.
 :)
declare function archives:archives-for-entities($entities-or-ids as item*) as object*
{
  let $eids as string* := entities:eid($entities-or-ids)
  return mw:find($archives:col,{ $archives:ENTITY : [ $eids ] })
};

(:~
 : Return the number of hypercubes in each of the given archives.
 :
 : @param $archives-or-ids list of archives or IDs
 :
 : @return the number of hypercubes
 :)
declare function archives:num-hypercubes($archives-or-ids as item*) as integer*
{
  archives:archives($archives-or-ids) ! $$.Statistics.NumHypercubes
};

(:~
 : Return the number of report elements in each of the given archives.
 :
 : @param $archives-or-ids list of archives or IDs
 :
 : @return the number of report elements
 :)
declare function archives:num-report-elements($archives-or-ids as item*) as integer*
{
  archives:archives($archives-or-ids) ! $$.Statistics.NumReportElements
};

(:~
 : Return the number of (distinct) dimensions in each of the given archives.
 :
 : @param $archives-or-ids list of archives or IDs
 :
 : @return the number of dimensions
 :)
declare function archives:num-dimensions($archives-or-ids as item*) as integer*
{
  archives:archives($archives-or-ids) ! $$.Statistics.NumDimensions
};

(:~
 : Return the number of (distinct) members in each of the given archives.
 :
 : @param $archives-or-ids list of archives or IDs
 :
 : @return the number of members
 :)
declare function archives:num-members($archives-or-ids as item*) as integer*
{
  archives:archives($archives-or-ids) ! $$.Statistics.NumMembers
};

(:~
 : Return the number of (distinct) concrete concepts in each of the given archives.
 :
 : @param $archives-or-ids list of archives or IDs
 :
 : @return the number of concepts
 :)
declare function archives:num-concepts($archives-or-ids as item*) as integer*
{
  archives:archives($archives-or-ids) ! $$.Statistics.NumConcepts
};

(:~
 : Return the number of (distinct) abstracts in each of the given archives.
 :
 : @param $archives-or-ids list of archives or IDs
 :
 : @return the number of abstracts
 :)
declare function archives:num-abstracts($archives-or-ids as item*) as integer*
{
  archives:archives($archives-or-ids) ! $$.Statistics.NumAbstracts
};

(:~
 : Return the number of (distinct) line items report elements in each of the given archives.
 :
 : @param $archives-or-ids list of archives or IDs
 :
 : @return the number of line items
 :)
declare function archives:num-line-items($archives-or-ids as item*) as integer*
{
  archives:archives($archives-or-ids) ! $$.Statistics.NumLineItems
};

(:~
 : Return the number of facts of each of the given archives.
 :
 : @param $archives-or-ids list of archives or IDs
 :
 : @return the said number of facts
 :)
declare function archives:num-facts($archives-or-ids as item*) as integer*
{
  archives:archives($archives-or-ids) ! $$.Statistics.NumFacts
};

(:~
 : Return the number of XBRL footnotes of each of the given archives.
 :
 : @param $archives-or-ids list of archives or IDs
 :
 : @return the said number of footnotes
 :)
declare function archives:num-footnotes($archives-or-ids as item*) as integer*
{
  archives:archives($archives-or-ids) ! $$.Statistics.NumFootnotes
};

(:~
 : Return the number of components of each of the given archives.
 :
 : @param $archives-or-ids list of archives or IDs
 :
 : @return the said number of components
 :)
declare function archives:num-components($archives-or-ids as item*) as integer*
{
  archives:archives($archives-or-ids) ! $$.Statistics.NumComponents
};

(:~
 :
 :
Converts the input to a normalized archive identifier (AID). The input
 : can be either a pure AID, or an archive object which contains an AID.

 :
 : @param $archives-or-ids a sequence of archive objects or identifiers (AID).
 :
 : @error archives:INVALID_PARAMETER if the AID or archive is not valid
 :
 : @return the normalized AIDs.
 :)
declare function archives:aid($archives-or-ids as item*) as atomic*
{
  for $archive-or-id in $archives-or-ids
  return
  typeswitch ($archive-or-id)
  case object return
    let $aid := $archive-or-id._id
    return if(exists($aid))
           then $aid
           else error(QName("archives:INVALID_PARAMETER"),
                      "Invalid archive provided (no _id field)")
  case $aid as atomic return $aid
  default return error(
      QName("archives:INVALID_PARAMETER"),
      "Invalid archive or AID (must be an object or an atomic): "
      || serialize($archive-or-id))
};

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

(:~
 :
This module provides functions for retrieving metadata about archives.

 :
 :
Archives represent the granularity of "report shipping", i.e., an entity
 : reports one archive at a time. An archive is identified with an AID (archive ID).

 :
 :
Archives are made of reported facts (see facts module),
 : which are structured and organized in components (see components module).

 :
 :
With this module, you can retrieve all archives, or a certain number of archives
 : with their AIDs, or obtain the AID of archives you already have. You can also retrieve
 : all archives submitted by one or several entities.

 :
 :
Archive information is stored in a MongoDB datasource called xbrl.

 :
 : @author Charles Hoffman
 : @author Matthias Brantner
 : @author Dennis Knochenwefel
 : @author Ghislain Fourny
 :
 :)
module namespace archives = "http://28.io/modules/xbrl/archives";

import module namespace mw = "http://28.io/modules/xbrl/mongo-wrapper";

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

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

(:~
 : Name of the collection the archives are stored in.
 :)
declare variable $archives:col as string := "archives";

(:~
 : Name of the field which points to the reporting entity.
 :)
declare variable $archives:ENTITY as string:= "Entity";

(:~
 :
Retrieves all archives.

 :
 : @return all archives.
 :)
declare function archives:archives() as object*
{
  mw:find($archives:col,{})
};

(:~
 :
Retrieves the archives with the given AIDs.

 :
 : @param $id the ids of the archives (AIDs) or the archives themselves.
 :
 : @return the archives with the given AIDs
 :         the empty sequence if no archive was found or if the input is an
 : empty sequence.
 :)
declare function archives:archives($archive-or-ids as item*) as object*
{
  let $ids as string* :=
    for $s in $archive-or-ids
    where $s instance of string
    return $s
  let $archives as object* :=
    for $s in $archive-or-ids
    where $s instance of object
    return $s
  return
    (
      $archives,
      if (exists($ids))
      then mw:find($archives:col,{ "_id" : [ archives:aid($ids) ] })
      else ()
    )
};

(:~
 :
 :
Returns the entities that submitted the supplied archives.

 :
 : @param $archives-or-ids a sequence of archives or their identifiers (AID).
 : @return the submitting entities.
 :
 :)
declare function archives:entities($archives-or-ids as item*) as object*
{
  let $archives := archives:archives($archives-or-ids)
  let $eids := $archives.Entity
  return entities:entities($eids)
};

(:~
 :
Return all archives created by the supplied entities.

 :
 : @param $entities-or-ids arbitrary number of entity objects or EIDs.
 :
 : @return all archives created by these entities.
 :)
declare function archives:archives-for-entities($entities-or-ids as item*) as object*
{
  let $eids as string* := entities:eid($entities-or-ids)
  return mw:find($archives:col,{ $archives:ENTITY : [ $eids ] })
};

(:~
 : Return the number of hypercubes in each of the given archives.
 :
 : @param $archives-or-ids list of archives or IDs
 :
 : @return the number of hypercubes
 :)
declare function archives:num-hypercubes($archives-or-ids as item*) as integer*
{
  archives:archives($archives-or-ids) ! $$.Statistics.NumHypercubes
};

(:~
 : Return the number of report elements in each of the given archives.
 :
 : @param $archives-or-ids list of archives or IDs
 :
 : @return the number of report elements
 :)
declare function archives:num-report-elements($archives-or-ids as item*) as integer*
{
  archives:archives($archives-or-ids) ! $$.Statistics.NumReportElements
};

(:~
 : Return the number of (distinct) dimensions in each of the given archives.
 :
 : @param $archives-or-ids list of archives or IDs
 :
 : @return the number of dimensions
 :)
declare function archives:num-dimensions($archives-or-ids as item*) as integer*
{
  archives:archives($archives-or-ids) ! $$.Statistics.NumDimensions
};

(:~
 : Return the number of (distinct) members in each of the given archives.
 :
 : @param $archives-or-ids list of archives or IDs
 :
 : @return the number of members
 :)
declare function archives:num-members($archives-or-ids as item*) as integer*
{
  archives:archives($archives-or-ids) ! $$.Statistics.NumMembers
};

(:~
 : Return the number of (distinct) concrete concepts in each of the given archives.
 :
 : @param $archives-or-ids list of archives or IDs
 :
 : @return the number of concepts
 :)
declare function archives:num-concepts($archives-or-ids as item*) as integer*
{
  archives:archives($archives-or-ids) ! $$.Statistics.NumConcepts
};

(:~
 : Return the number of (distinct) abstracts in each of the given archives.
 :
 : @param $archives-or-ids list of archives or IDs
 :
 : @return the number of abstracts
 :)
declare function archives:num-abstracts($archives-or-ids as item*) as integer*
{
  archives:archives($archives-or-ids) ! $$.Statistics.NumAbstracts
};

(:~
 : Return the number of (distinct) line items report elements in each of the given archives.
 :
 : @param $archives-or-ids list of archives or IDs
 :
 : @return the number of line items
 :)
declare function archives:num-line-items($archives-or-ids as item*) as integer*
{
  archives:archives($archives-or-ids) ! $$.Statistics.NumLineItems
};

(:~
 : Return the number of facts of each of the given archives.
 :
 : @param $archives-or-ids list of archives or IDs
 :
 : @return the said number of facts
 :)
declare function archives:num-facts($archives-or-ids as item*) as integer*
{
  archives:archives($archives-or-ids) ! $$.Statistics.NumFacts
};

(:~
 : Return the number of XBRL footnotes of each of the given archives.
 :
 : @param $archives-or-ids list of archives or IDs
 :
 : @return the said number of footnotes
 :)
declare function archives:num-footnotes($archives-or-ids as item*) as integer*
{
  archives:archives($archives-or-ids) ! $$.Statistics.NumFootnotes
};

(:~
 : Return the number of components of each of the given archives.
 :
 : @param $archives-or-ids list of archives or IDs
 :
 : @return the said number of components
 :)
declare function archives:num-components($archives-or-ids as item*) as integer*
{
  archives:archives($archives-or-ids) ! $$.Statistics.NumComponents
};

(:~
 :
 :
Converts the input to a normalized archive identifier (AID). The input
 : can be either a pure AID, or an archive object which contains an AID.

 :
 : @param $archives-or-ids a sequence of archive objects or identifiers (AID).
 :
 : @error archives:INVALID_PARAMETER if the AID or archive is not valid
 :
 : @return the normalized AIDs.
 :)
declare function archives:aid($archives-or-ids as item*) as atomic*
{
  for $archive-or-id in $archives-or-ids
  return
  typeswitch ($archive-or-id)
  case object return
    let $aid := $archive-or-id._id
    return if(exists($aid))
           then $aid
           else error(QName("archives:INVALID_PARAMETER"),
                      "Invalid archive provided (no _id field)")
  case $aid as atomic return $aid
  default return error(
      QName("archives:INVALID_PARAMETER"),
      "Invalid archive or AID (must be an object or an atomic): "
      || serialize($archive-or-id))
};


Remove unused module

Remove unused module

import module namespace report-schemas = "http://28.io/modules/xbrl/report-schemas";

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 session = "http://apps.28.io/session";

session:audit-call();

let $name := request:param-values("name")
let $schema := report-schemas:report-schemas($name)
return
    if (exists($schema))
    then {
        response:content-type("application/json");
        response:serialization-parameters({"indent" : true});
        $schema
    }
    else {
        response:status-code(404);
        session:error($name || "schema not found", "json")
    }