Esempio n. 1
0
def uncovered_aspect(xc, p, args):
    from arelle.ModelFormulaObject import aspectFromToken, Aspect
    from arelle.FormulaEvaluator import uncoveredAspectValue
    if len(args) not in (1,2): raise XPathContext.FunctionNumArgs()
    aspect = aspectFromToken.get(stringArg(xc, args, 0, "xs:token").strip())
    if aspect == Aspect.DIMENSIONS:
        qn = qnameArg(xc, p, args, 1, 'QName', emptyFallback=None)
        
    # check function use after checking argument types
    if xc.progHeader is not None and xc.progHeader.element is not None:
        if xc.progHeader.element.localName not in ("formula", "consistencyAssertion", "valueAssertion", "message"):
            raise XPathContext.XPathException(p, 'xffe:invalidFunctionUse', _('Function xff:uncovered-aspect cannot be used on an XPath expression associated with a {0}').format(xc.progHeader.element.localName))
        if xc.variableSet is not None and xc.variableSet.implicitFiltering  == "false":
            raise XPathContext.XPathException(p, 'xffe:invalidFunctionUse', _('Function xff:uncovered-aspect cannot be used with implicitFiltering=false'))
        
    if aspect == Aspect.DIMENSIONS:
        if qn:
            modelConcept = xc.modelXbrl.qnameConcepts.get(qn)
            if modelConcept is not None and modelConcept.isDimensionItem:
                aspect = qn
            else:
                return ()   # not a dimension
            dimValue = uncoveredAspectValue(xc, aspect)
            if isinstance(dimValue, ModelDimensionValue):
                if dimValue.isExplicit: 
                    return dimValue.memberQname
                elif dimValue.isTyped:
                    return dimValue     # return the typedMember element, not its contents
            elif isinstance(dimValue, QName): # qname for explicit or node for typed
                return dimValue
            return ()
    aspectValue = uncoveredAspectValue(xc, aspect)
    if aspectValue is None:
        return ()
    return aspectValue
Esempio n. 2
0
def QName_functions(xc, p, args, prefix=False, localName=False, namespaceURI=False):
    qn = qnameArg(xc, p, args, 0, 'QName?', emptyFallback=())
    if qn != ():
        if prefix: return qn.prefix
        if localName: return qn.localName
        if namespaceURI: return qn.namespaceURI
    return ()
Esempio n. 3
0
def relationship_element_attribute(xc, p, args, elementParent=False):
    if len(args) != 2: raise XPathContext.FunctionNumArgs()
    modelRel = anytypeArg(xc, args, 0, "arelle:ModelRelationship", None)
    if modelRel is None: raise XPathContext.FunctionArgType(1,"arelle:modelRelationship")
    qnAttr = qnameArg(xc, p, args, 1, 'QName', emptyFallback=None)
    if qnAttr is None: raise XPathContext.FunctionArgType(2,"xs:QName")
    element = modelRel.arcElement
    if elementParent: element = element.getparent()
    return element_attribute(element, qnAttr)
Esempio n. 4
0
def conceptProperty(xc, p, args, property):
    if len(args) != 1: raise XPathContext.FunctionNumArgs()
    qn = qnameArg(xc, p, args, 0, 'QName', emptyFallback=None)
    if qn:
        modelConcept = xc.modelXbrl.qnameConcepts.get(qn)
        if modelConcept is not None:
            if property == "numeric": return modelConcept.isNumeric or modelConcept.isFraction
            if property == "non-numeric": return modelConcept.isItem and not (modelConcept.isNumeric or modelConcept.isFraction)
            if property == "fraction": return modelConcept.isFraction
    return False
Esempio n. 5
0
def fact_dim_value(xc, p, args, dimType):
    context = item_context(xc, args)
    qnDim = qnameArg(xc, p, args, 1, 'QName', emptyFallback=None)
    dimConcept = xc.modelXbrl.qnameConcepts.get(qnDim)
    if dimConcept is None or not dimConcept.isDimensionItem:
        raise XPathContext.XPathException(p, 
                                          'xfie:invalid{0}DimensionQName'.format(dimType), 
                                          _('Argument 1 {0} is not a dimension concept QName.').format(qnDim))
    if context is not None:
        return context.dimValue(qnDim)
    raise XPathContext.FunctionArgType(1,"xbrl:item")
Esempio n. 6
0
def fact_typed_dimension_value(xc, p, args):
    if len(args) != 2: raise XPathContext.FunctionNumArgs()
    context = item_context(xc, args)
    if context is not None:
        qn = qnameArg(xc, p, args, 1, 'QName', emptyFallback=())
        if qn == (): raise XPathContext.FunctionArgType(2,"xbrl:QName")
        modelConcept = xc.modelXbrl.qnameConcepts.get(qn) # check qname is explicit dimension
        if modelConcept is None or not modelConcept.isTypedDimension:
            raise XPathContext.XPathException(p, 'xfie:invalidTypedDimensionQName', _('dimension does not specify a typed dimension'))
        result = context.dimValue(qn)
        return result if result is not None else ()
    raise XPathContext.FunctionArgType(1,"xbrl:item")
Esempio n. 7
0
def concept_custom_attribute(xc, p, args):
    if len(args) != 2: raise XPathContext.FunctionNumArgs()
    qnAttr = qnameArg(xc, p, args, 1, 'QName', emptyFallback=None)
    if not qnAttr: raise XPathContext.FunctionArgType(2,"xs:QName")
    element = concept(xc,p,args).element
    if qnAttr.namespaceURI:
        if not element.hasAttributeNS(qnAttr.namespaceURI, qnAttr.localName):
            return ()
        return xc.atomize(p, element.getAttributeNodeNS(qnAttr.namespaceURI, qnAttr.localName))
    else:
        if not element.hasAttribute(qnAttr.localName):
            return ()
        return xc.atomize(p, element.getAttributeNode(qnAttr.localName))
Esempio n. 8
0
def filter_member_network_selection(xc, p, args):
    if len(args) != 5: raise XPathContext.FunctionNumArgs()
    qnDim = qnameArg(xc, p, args, 0, 'QName', emptyFallback=None)
    qnMem = qnameArg(xc, p, args, 1, 'QName', emptyFallback=None)
    linkroleURI = stringArg(xc, args, 2, "xs:string")
    arcroleURI = stringArg(xc, args, 3, "xs:string")
    axis = stringArg(xc, args, 4, "xs:string")
    if not axis in ('descendant-or-self', 'child-or-self', 'descendant', 'child'):
        return ()
    dimConcept = xc.modelXbrl.qnameConcepts.get(qnDim)
    if dimConcept is None or not dimConcept.isDimensionItem:
        raise XPathContext.XPathException(p, 'xfie:invalidDimensionQName', _('Argument 1 {0} is not a dimension concept QName.').format(qnDim))
    memConcept = xc.modelXbrl.qnameConcepts.get(qnMem)
    if memConcept is None or not memConcept.isDomainMember:
        # removed error 2011-03-10: raise XPathContext.XPathException(p, 'xfie:unrecognisedExplicitDimensionValueQName', _('Argument 1 {0} is not a member concept QName.').format(qnMem))
        return ()
    relationshipSet = xc.modelXbrl.relationshipSet(arcroleURI, linkroleURI)
    if relationshipSet is not None:
        members = set()
        linkQnames = set()
        arcQnames = set()
        if axis.endswith("-or-self"):
            members.add(qnMem)
        fromRels = relationshipSet.fromModelObject(memConcept)
        if fromRels is not None:
            filter_member_network_members(relationshipSet, fromRels, axis.startswith("descendant"), members, linkQnames, arcQnames)
            ''' removed 2011-03-10:
            if len(linkQnames) > 1 or len(arcQnames) > 1:
                raise XPathContext.XPathException(p, 'xfie:ambiguousFilterMemberNetwork', 
                          _('Network of linkrole {0} and arcrole {1} dimension {2} from {3} is ambiguous because of multiple link elements, {4}, or arc elements {5}').format(
                            linkroleURI, arcroleURI, qnDim, qnMem, linkQnames, arcQnames))
            '''
            return members
        # no fromRels, must be a toRel or else the qname is not in the member network
        if relationshipSet.toModelObject(memConcept):
            return members  # valid situation, the member exists as a leaf node
    # removed error 2011-03-10: raise XPathContext.XPathException(p, 'xfie:unrecognisedExplicitDimensionValueQName', _('Argument 1 {0} member is not in the network.').format(qnMem))
    return ()
Esempio n. 9
0
def  xfxc_element(xc, p, contextItem, args):
    if not 2 <= len(args) <= 4: raise XPathContext.FunctionNumArgs()
    qn = qnameArg(xc, p, args, 0, 'QName', emptyFallback=None)
    attrArg = args[1] if isinstance(args[1],(list,tuple)) else (args[1],)
    # attributes have to be pairs
    if attrArg:
        if len(attrArg) & 1 or any(not isinstance(attrArg[i], (QName, _STR_BASE))
                                   for i in range(0, len(attrArg),2)):
            raise XPathContext.FunctionArgType(1,"((xs:qname|xs:string),xs:anyAtomicValue)", errCode="xfxce:AttributesNotNameValuePairs")
        else:
            attrParam = [(attrArg[i],attrArg[i+1]) # need name-value pairs for XmlUtil function
                         for i in range(0, len(attrArg),2)]
    else:
        attrParam = None
         
    value = atomicArg(xc, p, args, 2, "xs:anyAtomicType", emptyFallback='') 
    if not value: # be sure '' is None so no text node is created
        value = None  
    if len(args) < 4:
        childElements = None
    else:
        childElements = xc.flattenSequence(args[3])
    
    # scratchpad instance document emulates fn:doc( ) to hold XML nodes
    scratchpadXmlDocUrl = "http://www.xbrl.org/2012/function/creation/xml_scratchpad.xml"
    if scratchpadXmlDocUrl in xc.modelXbrl.urlDocs:
        modelDocument = xc.modelXbrl.urlDocs[scratchpadXmlDocUrl]
    else:
        # create scratchpad xml document
        # this will get the fake instance document in the list of modelXbrl docs so that it is garbage collected
        from arelle import ModelDocument
        modelDocument = ModelDocument.create(xc.modelXbrl, 
                                             ModelDocument.Type.UnknownXML, 
                                             scratchpadXmlDocUrl,
                                             initialXml="<xfc:dummy xmlns:xfc='http://www.xbrl.org/2012/function/creation'/>")
        
    newElement = XmlUtil.addChild(modelDocument.xmlRootElement,
                                  qn,
                                  attributes=attrParam,
                                  text=value)
    if childElements:
        for element in childElements:
            if isinstance(element, etree.ElementBase):
                newElement.append(element)
                
    # node myst be validated for use in instance creation (typed dimension references)
    XmlValidate.validate(xc.modelXbrl, newElement)
                
    return newElement
Esempio n. 10
0
def element_attribute(xc, p, args, elementParent=False):
    if len(args) != 2: raise XPathContext.FunctionNumArgs()
    modelRel = anytypeArg(xc, args, 0, "arelle:ModelRelationship", None)
    if not modelRel: raise XPathContext.FunctionArgType(1,"arelle:modelRelationship")
    qnAttr = qnameArg(xc, p, args, 1, 'QName', emptyFallback=None)
    if not qnAttr: raise XPathContext.FunctionArgType(2,"xs:QName")
    element = modelRel.element
    if elementParent: element = element.parentNode
    if qnAttr.namespaceURI:
        if not element.hasAttributeNS(qnAttr.namespaceURI, qnAttr.localName):
            return ()
        return xc.atomize(p, element.getAttributeNodeNS(qnAttr.namespaceURI, qnAttr.localName))
    else:
        if not element.hasAttribute(qnAttr.localName):
            return ()
        return xc.atomize(p, element.getAttributeNode(qnAttr.localName))
Esempio n. 11
0
def concept_label(xc, p, args):
    if len(args) == 5: raise xfiFunctionNotAvailable()
    if len(args) != 4: raise XPathContext.FunctionNumArgs()
    qnSource = qnameArg(xc, p, args, 0, 'QName', emptyFallback=None)
    srcConcept = xc.modelXbrl.qnameConcepts.get(qnSource)
    if srcConcept is None:
        return ""
    linkroleURI = stringArg(xc, args, 1, "xs:string", emptyFallback='')
    if not linkroleURI: linkroleURI = XbrlConst.defaultLinkRole
    labelroleURI = stringArg(xc, args, 2, "xs:string", emptyFallback='')
    if not labelroleURI: labelroleURI = XbrlConst.standardLabel
    lang = stringArg(xc, args, 3, "xs:string", emptyFallback='')
    relationshipSet = xc.modelXbrl.relationshipSet(XbrlConst.conceptLabel,linkroleURI)
    if relationshipSet is not None:
        label = relationshipSet.label(srcConcept, labelroleURI, lang)
        if label is not None: return label
    return ""
Esempio n. 12
0
def fact_dimension_s_equal2(xc, p, args):
    if len(args) != 3: raise XPathContext.FunctionNumArgs()
    context1 = item_context(xc, args, i=0)
    context2 = item_context(xc, args, i=1)
    if context1 is not None:
        if context2 is not None:
            qn = qnameArg(xc, p, args, 2, 'QName', emptyFallback=())
            if qn == (): raise XPathContext.FunctionArgType(3,"xbrl:QName")
            modelConcept = xc.modelXbrl.qnameConcepts.get(qn) # check qname is explicit dimension
            if modelConcept is None or not modelConcept.isDimensionItem:
                # raise XPathContext.XPathException(p, 'xfie:invalidTypedDimensionQName', _('dimension does not specify a typed dimension'))
                return False
            dimValue1 = context1.dimValue(qn)
            dimValue2 = context2.dimValue(qn)
            if dimValue1 is not None and isinstance(dimValue1,ModelDimensionValue):
                return dimValue1.isEqualTo(dimValue2, equalMode=XbrlUtil.S_EQUAL2)
            elif dimValue2 is not None and isinstance(dimValue2,ModelDimensionValue):
                return dimValue2.isEqualTo(dimValue1, equalMode=XbrlUtil.S_EQUAL2)
            return dimValue1 == dimValue2
        raise XPathContext.FunctionArgType(2,"xbrl:item")
    raise XPathContext.FunctionArgType(1,"xbrl:item")
Esempio n. 13
0
def fact_explicit_dimension_value_value(xc, p, args):
    context = item_context(xc, args)
    if context is not None:
        qn = qnameArg(xc, p, args, 1, 'QName', emptyFallback=())
        if qn == (): raise XPathContext.FunctionArgType(2,"xbrl:QName")
        dimConcept = xc.modelXbrl.qnameConcepts.get(qn) # check qname is explicit dimension
        if dimConcept is None or not dimConcept.isExplicitDimension:
            raise XPathContext.XPathException(p, 'xfie:invalidExplicitDimensionQName', _('dimension does not specify an explicit dimension'))
        dimValue = context.dimValue(qn)
        if isinstance(dimValue, ModelDimensionValue) and dimValue.isExplicit:
            return dimValue.memberQname # known to be valid given instance is valid
        elif isinstance(dimValue, QName): #default, check if this is valid 
            ''' removed 2011-03-01 FWG clarification that default always applies
            modelItem = xc.modelItem(args[0][0])
            itemConcept = modelItem.concept
            from arelle.ValidateXbrlDimensions import checkPriItemDimValueValidity
            memConcept = xc.modelXbrl.qnameConcepts.get(dimValue)
            # remove check for pri item validity per FWG meeting notes 2011-01-13
            if itemConcept: # and checkPriItemDimValueValidity(xc, itemConcept, dimConcept, memConcept):
                return dimValue
            '''
            return dimValue
        return () # not an applicable primary item for default dimension
    raise XPathContext.FunctionArgType(1,"xbrl:item")
Esempio n. 14
0
def error(xc, p, contextItem, args):
    if len(args) > 2: raise XPathContext.FunctionNumArgs()
    qn = qnameArg(xc, p, args, 0, 'QName?', emptyFallback=None)
    msg = stringArg(xc, args, 1, "xs:string", emptyFallback='')
    raise XPathContext.XPathException(p, (qn or "err:FOER0000"), msg)
Esempio n. 15
0
def concept(xc, p, args):
    qnConcept = qnameArg(xc, p, args, 0, 'QName', emptyFallback=None)
    srcConcept = xc.modelXbrl.qnameConcepts.get(qnConcept)
    if srcConcept is None or not (srcConcept.isItem or srcConcept.isTuple): 
        raise XPathContext.XPathException(p, 'xfie:invalidConceptQName', _('Argument 1 {0} is not a concept in the DTS.').format(qnConcept))
    return srcConcept
Esempio n. 16
0
def concept_relationships(xc, p, args):
    lenArgs = len(args)
    if lenArgs < 4 or lenArgs > 8: raise XPathContext.FunctionNumArgs()
    qnSource = qnameArg(xc, p, args, 0, 'QName', emptyFallback=None)
    linkroleURI = stringArg(xc, args, 1, "xs:string")
    if not linkroleURI:
        linkroleURI = XbrlConst.defaultLinkRole
    arcroleURI = stringArg(xc, args, 2, "xs:string")
    axis = stringArg(xc, args, 3, "xs:string")
    if not axis in ('descendant', 'child', 'ancestor', 'parent', 'sibling', 'sibling-or-self'):
        return ()
    if qnSource != XbrlConst.qnXfiRoot:
        srcConcept = xc.modelXbrl.qnameConcepts.get(qnSource)
        if srcConcept is None:
            return ()
    if lenArgs > 4:
        generations = numericArg(xc, p, args, 4, "xs:integer", convertFallback=0)
    elif axis in ('child', 'parent', 'sibling', 'sibling-or-self'):
        generations = 1
    else:
        generations = 0
    if axis in ('child','parent','sibling', 'sibling-or-self'):
        generations = 1
    if axis == 'child':
        axis = 'descendant'
    elif axis == 'parent':
        axis = 'ancestor'
    if lenArgs > 5:
        qnLink = qnameArg(xc, p, args, 5, 'QName', emptyFallback=None)
    else:
        qnLink = None
    if lenArgs > 5:
        qnArc = qnameArg(xc, p, args, 6, 'QName', emptyFallback=None)
    else:
        qnArc = None
        
    removeSelf = axis == 'sibling'
    relationshipSet = xc.modelXbrl.relationshipSet(arcroleURI, linkroleURI, qnLink, qnArc)
    if relationshipSet:
        result = []
        visited = {qnSource}
        if qnSource == XbrlConst.qnXfiRoot:
            if axis in ('sibling', 'sibling-or-self', 'ancestor'):
                return []
            roots = relationshipSet.rootConcepts
            visited = {c.qname for c in roots}
            rels = [rel for c in roots for rel in relationshipSet.fromModelObject(c)]
            if generations == 1:
                return rels
            if generations > 1:
                generations -= 1
        elif axis == 'descendant':
            rels = relationshipSet.fromModelObject(srcConcept)
        elif axis == 'ancestor': # includes first pass on parents of object to get sibling
            rels = relationshipSet.toModelObject(srcConcept)
        elif axis in ('sibling', 'sibling-or-self'):
            rels = relationshipSet.toModelObject(srcConcept)
            if rels:
                rels = relationshipSet.fromModelObject(rels[0].fromModelObject)
                axis = 'descendant'
            else: # must be a root, never has any siblings
                return []
        if rels:
            concept_relationships_step(xc, relationshipSet, rels, axis, generations, result, visited)
            if removeSelf:
                for i, rel in enumerate(result):
                    if rel.toModelObject == srcConcept:
                        result.pop(i)
                        break
            return result
    return ()
Esempio n. 17
0
def concept_custom_attribute(xc, p, args):
    if len(args) != 2: raise XPathContext.FunctionNumArgs()
    qnAttr = qnameArg(xc, p, args, 1, 'QName', emptyFallback=None)
    if qnAttr is None: raise XPathContext.FunctionArgType(2,"xs:QName")
    element = concept(xc,p,args)
    return element_attribute(element, qnAttr)
Esempio n. 18
0
def fact_has_explicit_dimension_value(xc, p, args):
    if len(args) != 3: raise XPathContext.FunctionNumArgs()
    return qnameArg(xc, p, args, 2, 'QName', emptyFallback=()) == fact_explicit_dimension_value_value(xc, p, args)
Esempio n. 19
0
def concept_data_type_derived_from(xc, p, args):
    if len(args) != 2: raise XPathContext.FunctionNumArgs()
    qnType = qnameArg(xc, p, args, 1, 'QName', emptyFallback=None)
    if qnType is None: raise XPathContext.FunctionArgType(2,"xs:QName")
    return concept(xc,p,args).instanceOfType(qnType)