Example #1
0
    def validate(self):
        self.modelXbrl.info(
            "info",
            "Validating calculations inferring %(inferMode)s",
            inferMode=_("precision") if self.inferPrecision else _("decimals"),
        )

        # identify equal contexts
        self.modelXbrl.profileActivity()
        uniqueContextHashes = {}
        for context in self.modelXbrl.contexts.values():
            h = context.contextDimAwareHash
            if h in uniqueContextHashes:
                if context.isEqualTo(uniqueContextHashes[h]):
                    self.mapContext[context] = uniqueContextHashes[h]
            else:
                uniqueContextHashes[h] = context
        del uniqueContextHashes
        self.modelXbrl.profileActivity("... identify equal contexts", minTimeToShow=1.0)

        # identify equal contexts
        uniqueUnitHashes = {}
        for unit in self.modelXbrl.units.values():
            h = unit.hash
            if h in uniqueUnitHashes:
                if unit.isEqualTo(uniqueUnitHashes[h]):
                    self.mapUnit[unit] = uniqueUnitHashes[h]
            else:
                uniqueUnitHashes[h] = unit
        self.modelXbrl.profileActivity("... identify equal units", minTimeToShow=1.0)

        # identify concepts participating in essence-alias relationships
        # identify calcluation & essence-alias base sets (by key)
        for baseSetKey in self.modelXbrl.baseSets.keys():
            arcrole, ELR, linkqname, arcqname = baseSetKey
            if ELR and linkqname and arcqname:
                if arcrole in (XbrlConst.essenceAlias, XbrlConst.requiresElement):
                    conceptsSet = {
                        XbrlConst.essenceAlias: self.conceptsInEssencesAlias,
                        XbrlConst.requiresElement: self.conceptsInRequiresElement,
                    }[arcrole]
                    for modelRel in self.modelXbrl.relationshipSet(
                        arcrole, ELR, linkqname, arcqname
                    ).modelRelationships:
                        for concept in (modelRel.fromModelObject, modelRel.toModelObject):
                            conceptsSet.add(concept)
        self.modelXbrl.profileActivity("... identify requires-element and esseance-aliased concepts", minTimeToShow=1.0)

        self.bindFacts(self.modelXbrl.facts, [self.modelXbrl.modelDocument.xmlRootElement])
        self.modelXbrl.profileActivity("... bind facts", minTimeToShow=1.0)

        # identify calcluation & essence-alias base sets (by key)
        for baseSetKey in self.modelXbrl.baseSets.keys():
            arcrole, ELR, linkqname, arcqname = baseSetKey
            if ELR and linkqname and arcqname:
                if arcrole in (XbrlConst.summationItem, XbrlConst.essenceAlias, XbrlConst.requiresElement):
                    relsSet = self.modelXbrl.relationshipSet(arcrole, ELR, linkqname, arcqname)
                    if arcrole == XbrlConst.summationItem:
                        fromRelationships = relsSet.fromModelObjects()
                        for sumConcept, modelRels in fromRelationships.items():
                            sumBindingKeys = self.sumConceptBindKeys[sumConcept]
                            dupBindingKeys = set()
                            boundSumKeys = set()
                            # determine boundSums
                            for modelRel in modelRels:
                                itemBindingKeys = self.itemConceptBindKeys[modelRel.toModelObject]
                                boundSumKeys |= sumBindingKeys & itemBindingKeys
                            # add up rounded items
                            boundSums = defaultdict(decimal.Decimal)
                            for modelRel in modelRels:
                                weight = modelRel.weightDecimal
                                itemConcept = modelRel.toModelObject
                                for itemBindKey in boundSumKeys:
                                    ancestor, contextHash, unit = itemBindKey
                                    factKey = (itemConcept, ancestor, contextHash, unit)
                                    if factKey in self.itemFacts:
                                        for fact in self.itemFacts[factKey]:
                                            if fact in self.duplicatedFacts:
                                                dupBindingKeys.add(itemBindKey)
                                            else:
                                                boundSums[itemBindKey] += self.roundFact(fact) * weight
                            for sumBindKey in boundSumKeys:
                                ancestor, contextHash, unit = sumBindKey
                                factKey = (sumConcept, ancestor, contextHash, unit)
                                if factKey in self.sumFacts:
                                    for fact in self.sumFacts[factKey]:
                                        if fact in self.duplicatedFacts:
                                            dupBindingKeys.add(sumBindKey)
                                        elif sumBindKey not in dupBindingKeys:
                                            roundedSum = self.roundFact(fact)
                                            roundedItemsSum = self.roundFact(fact, vDecimal=boundSums[sumBindKey])
                                            if roundedItemsSum != self.roundFact(fact):
                                                self.modelXbrl.error(
                                                    "xbrl.5.2.5.2:calcInconsistency",
                                                    _(
                                                        "Calculation inconsistent from %(concept)s in link role %(linkrole)s reported sum %(reportedSum)s computed sum %(computedSum)s context %(contextID)s unit %(unitID)s"
                                                    ),
                                                    modelObject=sumConcept,
                                                    concept=sumConcept.qname,
                                                    linkrole=ELR,
                                                    reportedSum=roundedSum,
                                                    computedSum=roundedItemsSum,
                                                    contextID=context.id,
                                                    unitID=unit.id,
                                                )
                    elif arcrole == XbrlConst.essenceAlias:
                        for modelRel in relsSet.modelRelationships:
                            essenceConcept = modelRel.fromModelObject
                            aliasConcept = modelRel.toModelObject
                            essenceBindingKeys = self.esAlConceptBindKeys[essenceConcept]
                            aliasBindingKeys = self.esAlConceptBindKeys[aliasConcept]
                            for esAlBindKey in essenceBindingKeys & aliasBindingKeys:
                                ancestor, contextHash = esAlBindKey
                                essenceFactsKey = (essenceConcept, ancestor, contextHash)
                                aliasFactsKey = (aliasConcept, ancestor, contextHash)
                                if essenceFactsKey in self.esAlFacts and aliasFactsKey in self.esAlFacts:
                                    for eF in self.esAlFacts[essenceFactsKey]:
                                        for aF in self.esAlFacts[aliasFactsKey]:
                                            essenceUnit = self.mapUnit.get(eF.unit, eF.unit)
                                            aliasUnit = self.mapUnit.get(aF.unit, aF.unit)
                                            if essenceUnit != aliasUnit:
                                                self.modelXbrl.error(
                                                    "xbrl.5.2.6.2.2:essenceAliasUnitsInconsistency",
                                                    _(
                                                        "Essence-Alias inconsistent units from %(essenceConcept)s to %(aliasConcept)s in link role %(linkrole)s context %(contextID)s"
                                                    ),
                                                    modelObject=essenceConcept,
                                                    essenceConcept=essenceConcept.qname,
                                                    aliasConcept=aliasConcept.qname,
                                                    linkrole=ELR,
                                                    contextID=context.id,
                                                )
                                            if not XbrlUtil.vEqual(eF, aF):
                                                self.modelXbrl.error(
                                                    "xbrl.5.2.6.2.2:essenceAliasUnitsInconsistency",
                                                    _(
                                                        "Essence-Alias inconsistent value from %(essenceConcept)s to %(aliasConcept)s in link role %(linkrole)s context %(contextID)s"
                                                    ),
                                                    modelObject=essenceConcept,
                                                    essenceConcept=essenceConcept.qname,
                                                    aliasConcept=aliasConcept.qname,
                                                    linkrole=ELR,
                                                    contextID=context.id,
                                                )
                    elif arcrole == XbrlConst.requiresElement:
                        for modelRel in relsSet.modelRelationships:
                            sourceConcept = modelRel.fromModelObject
                            requiredConcept = modelRel.toModelObject
                            if (
                                sourceConcept in self.requiresElementFacts
                                and not requiredConcept in self.requiresElementFacts
                            ):
                                self.modelXbrl.error(
                                    "xbrl.5.2.6.2.4:requiresElementInconsistency",
                                    _(
                                        "Requires-Element %(requiringConcept)s missing required fact for %(requiredConcept)s in link role %(linkrole)s"
                                    ),
                                    modelObject=sourceConcept,
                                    requiringConcept=sourceConcept.qname,
                                    requiredConcept=requiredConcept.qname,
                                    linkrole=ELR,
                                )
        self.modelXbrl.profileActivity("... find inconsistencies", minTimeToShow=1.0)
        self.modelXbrl.profileActivity()  # reset
Example #2
0
    def validate(self):
        if not self.modelXbrl.contexts and not self.modelXbrl.facts:
            return # skip if no contexts or facts
        
        if not self.inferDecimals: # infering precision is now contrary to XBRL REC section 5.2.5.2
            self.modelXbrl.info("xbrl.5.2.5.2:inferringPrecision","Validating calculations inferring precision.")
            
        # identify equal contexts
        self.modelXbrl.profileActivity()
        uniqueContextHashes = {}
        for context in self.modelXbrl.contexts.values():
            h = context.contextDimAwareHash
            if h in uniqueContextHashes:
                if context.isEqualTo(uniqueContextHashes[h]):
                    self.mapContext[context] = uniqueContextHashes[h]
            else:
                uniqueContextHashes[h] = context
        del uniqueContextHashes
        self.modelXbrl.profileActivity("... identify equal contexts", minTimeToShow=1.0)

        # identify equal contexts
        uniqueUnitHashes = {}
        for unit in self.modelXbrl.units.values():
            h = unit.hash
            if h in uniqueUnitHashes:
                if unit.isEqualTo(uniqueUnitHashes[h]):
                    self.mapUnit[unit] = uniqueUnitHashes[h]
            else:
                uniqueUnitHashes[h] = unit
        self.modelXbrl.profileActivity("... identify equal units", minTimeToShow=1.0)
                    
        # identify concepts participating in essence-alias relationships
        # identify calcluation & essence-alias base sets (by key)
        for baseSetKey in self.modelXbrl.baseSets.keys():
            arcrole, ELR, linkqname, arcqname = baseSetKey
            if ELR and linkqname and arcqname:
                if arcrole in (XbrlConst.essenceAlias, XbrlConst.requiresElement):
                    conceptsSet = {XbrlConst.essenceAlias:self.conceptsInEssencesAlias,
                                   XbrlConst.requiresElement:self.conceptsInRequiresElement}[arcrole]
                    for modelRel in self.modelXbrl.relationshipSet(arcrole,ELR,linkqname,arcqname).modelRelationships:
                        for concept in (modelRel.fromModelObject, modelRel.toModelObject):
                            if concept is not None and concept.qname is not None:
                                conceptsSet.add(concept)
        self.modelXbrl.profileActivity("... identify requires-element and esseance-aliased concepts", minTimeToShow=1.0)

        self.bindFacts(self.modelXbrl.facts,[self.modelXbrl.modelDocument.xmlRootElement])
        self.modelXbrl.profileActivity("... bind facts", minTimeToShow=1.0)
        
        # identify calcluation & essence-alias base sets (by key)
        for baseSetKey in self.modelXbrl.baseSets.keys():
            arcrole, ELR, linkqname, arcqname = baseSetKey
            if ELR and linkqname and arcqname:
                if arcrole in (XbrlConst.summationItem, XbrlConst.essenceAlias, XbrlConst.requiresElement):
                    relsSet = self.modelXbrl.relationshipSet(arcrole,ELR,linkqname,arcqname)
                    if arcrole == XbrlConst.summationItem:
                        fromRelationships = relsSet.fromModelObjects()
                        for sumConcept, modelRels in fromRelationships.items():
                            sumBindingKeys = self.sumConceptBindKeys[sumConcept]
                            dupBindingKeys = set()
                            boundSumKeys = set()
                            # determine boundSums
                            for modelRel in modelRels:
                                itemConcept = modelRel.toModelObject
                                if itemConcept is not None and itemConcept.qname is not None:
                                    itemBindingKeys = self.itemConceptBindKeys[itemConcept]
                                    boundSumKeys |= sumBindingKeys & itemBindingKeys
                            # add up rounded items
                            boundSums = defaultdict(decimal.Decimal) # sum of facts meeting factKey
                            boundSummationItems = defaultdict(list) # corresponding fact refs for messages
                            for modelRel in modelRels:
                                weight = modelRel.weightDecimal
                                itemConcept = modelRel.toModelObject
                                if itemConcept is not None:
                                    for itemBindKey in boundSumKeys:
                                        ancestor, contextHash, unit = itemBindKey
                                        factKey = (itemConcept, ancestor, contextHash, unit)
                                        if factKey in self.itemFacts:
                                            for fact in self.itemFacts[factKey]:
                                                if fact in self.duplicatedFacts:
                                                    dupBindingKeys.add(itemBindKey)
                                                else:
                                                    roundedValue = roundFact(fact, self.inferDecimals)
                                                    boundSums[itemBindKey] += roundedValue * weight
                                                    boundSummationItems[itemBindKey].append(wrappedFactWithWeight(fact,weight,roundedValue))
                            for sumBindKey in boundSumKeys:
                                ancestor, contextHash, unit = sumBindKey
                                factKey = (sumConcept, ancestor, contextHash, unit)
                                if factKey in self.sumFacts:
                                    sumFacts = self.sumFacts[factKey]
                                    for fact in sumFacts:
                                        if fact in self.duplicatedFacts:
                                            dupBindingKeys.add(sumBindKey)
                                        elif sumBindKey not in dupBindingKeys:
                                            roundedSum = roundFact(fact, self.inferDecimals)
                                            roundedItemsSum = roundFact(fact, self.inferDecimals, vDecimal=boundSums[sumBindKey])
                                            if roundedItemsSum  != roundFact(fact, self.inferDecimals):
                                                d = inferredDecimals(fact)
                                                if isnan(d) or isinf(d): d = 4
                                                _boundSummationItems = boundSummationItems[sumBindKey]
                                                unreportedContribingItemQnames = [] # list the missing/unreported contributors in relationship order
                                                for modelRel in modelRels:
                                                    itemConcept = modelRel.toModelObject
                                                    if (itemConcept is not None and 
                                                        (itemConcept, ancestor, contextHash, unit) not in self.itemFacts):
                                                        unreportedContribingItemQnames.append(str(itemConcept.qname))
                                                self.modelXbrl.log('INCONSISTENCY', "xbrl.5.2.5.2:calcInconsistency",
                                                    _("Calculation inconsistent from %(concept)s in link role %(linkrole)s reported sum %(reportedSum)s computed sum %(computedSum)s context %(contextID)s unit %(unitID)s unreportedContributingItems %(unreportedContributors)s"),
                                                    modelObject=wrappedSummationAndItems(fact, roundedSum, _boundSummationItems),
                                                    concept=sumConcept.qname, linkrole=ELR, 
                                                    linkroleDefinition=self.modelXbrl.roleTypeDefinition(ELR),
                                                    reportedSum=Locale.format_decimal(self.modelXbrl.locale, roundedSum, 1, max(d,0)),
                                                    computedSum=Locale.format_decimal(self.modelXbrl.locale, roundedItemsSum, 1, max(d,0)), 
                                                    contextID=fact.context.id, unitID=fact.unit.id,
                                                    unreportedContributors=", ".join(unreportedContribingItemQnames) or "none")
                                                del unreportedContribingItemQnames[:]
                            boundSummationItems.clear() # dereference facts in list
                    elif arcrole == XbrlConst.essenceAlias:
                        for modelRel in relsSet.modelRelationships:
                            essenceConcept = modelRel.fromModelObject
                            aliasConcept = modelRel.toModelObject
                            essenceBindingKeys = self.esAlConceptBindKeys[essenceConcept]
                            aliasBindingKeys = self.esAlConceptBindKeys[aliasConcept]
                            for esAlBindKey in essenceBindingKeys & aliasBindingKeys:
                                ancestor, contextHash = esAlBindKey
                                essenceFactsKey = (essenceConcept, ancestor, contextHash)
                                aliasFactsKey = (aliasConcept, ancestor, contextHash)
                                if essenceFactsKey in self.esAlFacts and aliasFactsKey in self.esAlFacts:
                                    for eF in self.esAlFacts[essenceFactsKey]:
                                        for aF in self.esAlFacts[aliasFactsKey]:
                                            essenceUnit = self.mapUnit.get(eF.unit,eF.unit)
                                            aliasUnit = self.mapUnit.get(aF.unit,aF.unit)
                                            if essenceUnit != aliasUnit:
                                                self.modelXbrl.log('INCONSISTENCY', "xbrl.5.2.6.2.2:essenceAliasUnitsInconsistency",
                                                    _("Essence-Alias inconsistent units from %(essenceConcept)s to %(aliasConcept)s in link role %(linkrole)s context %(contextID)s"),
                                                    modelObject=(modelRel, eF, aF), 
                                                    essenceConcept=essenceConcept.qname, aliasConcept=aliasConcept.qname, 
                                                    linkrole=ELR, 
                                                    linkroleDefinition=self.modelXbrl.roleTypeDefinition(ELR),
                                                    contextID=eF.context.id)
                                            if not XbrlUtil.vEqual(eF, aF):
                                                self.modelXbrl.log('INCONSISTENCY', "xbrl.5.2.6.2.2:essenceAliasUnitsInconsistency",
                                                    _("Essence-Alias inconsistent value from %(essenceConcept)s to %(aliasConcept)s in link role %(linkrole)s context %(contextID)s"),
                                                    modelObject=(modelRel, eF, aF), 
                                                    essenceConcept=essenceConcept.qname, aliasConcept=aliasConcept.qname, 
                                                    linkrole=ELR,
                                                    linkroleDefinition=self.modelXbrl.roleTypeDefinition(ELR),
                                                    contextID=eF.context.id)
                    elif arcrole == XbrlConst.requiresElement:
                        for modelRel in relsSet.modelRelationships:
                            sourceConcept = modelRel.fromModelObject
                            requiredConcept = modelRel.toModelObject
                            if sourceConcept in self.requiresElementFacts and \
                               not requiredConcept in self.requiresElementFacts:
                                    self.modelXbrl.log('INCONSISTENCY', "xbrl.5.2.6.2.4:requiresElementInconsistency",
                                        _("Requires-Element %(requiringConcept)s missing required fact for %(requiredConcept)s in link role %(linkrole)s"),
                                        modelObject=sourceConcept, 
                                        requiringConcept=sourceConcept.qname, requiredConcept=requiredConcept.qname, 
                                        linkrole=ELR,
                                        linkroleDefinition=self.modelXbrl.roleTypeDefinition(ELR))
        self.modelXbrl.profileActivity("... find inconsistencies", minTimeToShow=1.0)
        self.modelXbrl.profileActivity() # reset
Example #3
0
    def validate(self):
        self.modelXbrl.error(_("Validating calculations inferring {0}")
                             .format(_("precision") if self.inferPrecision else _("decimals")))


        # identify equal contexts
        contexts = tuple(self.modelXbrl.contexts.values())
        for i in range(len(contexts)):
            cntx1 = contexts[i]
            for j in range(i+1, len(contexts)):
                cntx2 = contexts[j]
                if cntx1.isEqualTo(cntx2) and not cntx2 in self.mapContext:
                    self.mapContext[cntx2] = cntx1

        # identify equal contexts
        units = tuple(self.modelXbrl.units.values())
        for i in range(len(units)):
            unit1 = units[i]
            for j in range(i+1, len(units)):
                unit2 = units[j]
                if unit1.isEqualTo(unit2) and not unit2 in self.mapUnit:
                    self.mapUnit[unit2] = unit1
                    
        # identify concepts participating in essence-alias relationships
        # identify calcluation & essence-alias base sets (by key)
        for baseSetKey in self.modelXbrl.baseSets.keys():
            arcrole, ELR, linkqname, arcqname = baseSetKey
            if ELR and linkqname and arcqname:
                if arcrole in (XbrlConst.essenceAlias, XbrlConst.requiresElement):
                    conceptsSet = {XbrlConst.essenceAlias:self.conceptsInEssencesAlias,
                                   XbrlConst.requiresElement:self.conceptsInRequiresElement}[arcrole]
                    for modelRel in self.modelXbrl.relationshipSet(arcrole,ELR,linkqname,arcqname).modelRelationships:
                        for concept in (modelRel.fromModelObject, modelRel.toModelObject):
                            conceptsSet.add(concept)

        self.bindFacts(self.modelXbrl.facts,[self.modelXbrl.modelDocument.xmlRootElement])
        
        # identify calcluation & essence-alias base sets (by key)
        for baseSetKey in self.modelXbrl.baseSets.keys():
            arcrole, ELR, linkqname, arcqname = baseSetKey
            if ELR and linkqname and arcqname:
                if arcrole in (XbrlConst.summationItem, XbrlConst.essenceAlias, XbrlConst.requiresElement):
                    relsSet = self.modelXbrl.relationshipSet(arcrole,ELR,linkqname,arcqname)
                    if arcrole == XbrlConst.summationItem:
                        fromRelationships = relsSet.fromModelObjects()
                        for sumConcept, modelRels in fromRelationships.items():
                            sumBindingKeys = self.sumConceptBindKeys[sumConcept]
                            dupBindingKeys = set()
                            boundSumKeys = set()
                            # determine boundSums
                            for modelRel in modelRels:
                                itemBindingKeys = self.itemConceptBindKeys[modelRel.toModelObject]
                                boundSumKeys |= sumBindingKeys & itemBindingKeys
                            # add up rounded items
                            boundSums = defaultdict(float)
                            for modelRel in modelRels:
                                weight = modelRel.weight
                                itemConcept = modelRel.toModelObject
                                for itemBindKey in boundSumKeys:
                                    ancestor, context, unit = itemBindKey
                                    factKey = (itemConcept, ancestor, context, unit)
                                    if factKey in self.itemFacts:
                                        for fact in self.itemFacts[factKey]:
                                            if fact in self.duplicatedFacts:
                                                dupBindingKeys.add(itemBindKey)
                                            else:
                                                boundSums[itemBindKey] += self.roundFact(fact) * weight
                            for sumBindKey in boundSumKeys:
                                ancestor, context, unit = sumBindKey
                                factKey = (sumConcept, ancestor, context, unit)
                                if factKey in self.sumFacts:
                                    for fact in self.sumFacts[factKey]:
                                        if fact in self.duplicatedFacts:
                                            dupBindingKeys.add(sumBindKey)
                                        elif sumBindKey not in dupBindingKeys:
                                            roundedSum = self.roundFact(fact)
                                            roundedItemsSum = self.roundFact(fact, vFloat=boundSums[sumBindKey])
                                            if roundedItemsSum  != self.roundFact(fact):
                                                self.modelXbrl.error(
                                                    _("Calculation inconsistent from {0} in link role {1} reported sum {2} computed sum {3} context {4} unit {5}").format(
                                                          sumConcept.qname, ELR, roundedSum, roundedItemsSum, context.id, unit.id), 
                                                    "err", "xbrl.5.2.5.2:calcInconsistency")
                    elif arcrole == XbrlConst.essenceAlias:
                        for modelRel in relsSet.modelRelationships:
                            essenceConcept = modelRel.fromModelObject
                            aliasConcept = modelRel.toModelObject
                            essenceBindingKeys = self.esAlConceptBindKeys[essenceConcept]
                            aliasBindingKeys = self.esAlConceptBindKeys[aliasConcept]
                            for esAlBindKey in essenceBindingKeys & aliasBindingKeys:
                                ancestor, context = esAlBindKey
                                essenceFactsKey = (essenceConcept, ancestor, context)
                                aliasFactsKey = (aliasConcept, ancestor, context)
                                if essenceFactsKey in self.esAlFacts and aliasFactsKey in self.esAlFacts:
                                    for eF in self.esAlFacts[essenceFactsKey]:
                                        for aF in self.esAlFacts[aliasFactsKey]:
                                            essenceUnit = self.mapUnit.get(eF.unit,eF.unit)
                                            aliasUnit = self.mapUnit.get(aF.unit,aF.unit)
                                            if essenceUnit != aliasUnit:
                                                self.modelXbrl.error(
                                                    _("Essence-Alias inconsistent units from {0} to {1} in link role {2} context {3}").format(
                                                          essenceConcept.qname, aliasConcept.qname, ELR, context.id), 
                                                    "err", "xbrl.5.2.6.2.2:essenceAliasUnitsInconsistency")
                                            if not XbrlUtil.vEqual(essenceConcept, eF.element, aliasConcept, aF.element):
                                                self.modelXbrl.error(
                                                    _("Essence-Alias inconsistent value from {0} to {1} in link role {2} context {3}").format(
                                                          essenceConcept.qname, aliasConcept.qname, ELR, context.id), 
                                                    "err", "xbrl.5.2.6.2.2:essenceAliasUnitsInconsistency")
                    elif arcrole == XbrlConst.requiresElement:
                        for modelRel in relsSet.modelRelationships:
                            sourceConcept = modelRel.fromModelObject
                            requiredConcept = modelRel.toModelObject
                            if sourceConcept in self.requiresElementFacts and \
                               not requiredConcept in self.requiresElementFacts:
                                    self.modelXbrl.error(
                                        _("Requies-Element {0} missing required fact for {1} in link role {2}").format(
                                              sourceConcept.qname, requiredConcept.qname, ELR), 
                                        "err", "xbrl.5.2.6.2.4:requiresElementInconsistency")