Example #1
0
 def bodyCells(self, row, yParentStructuralNode, xStructuralNodes, zAspects, yChildrenFirst):
     if yParentStructuralNode is not None:
         rendrCntx = getattr(self.modelXbrl, "rendrCntx", None) # none for EU 2010 tables
         dimDefaults = self.modelXbrl.qnameDimensionDefaults
         for yStructuralNode in yParentStructuralNode.childStructuralNodes:
             if yChildrenFirst:
                 row = self.bodyCells(row, yStructuralNode, xStructuralNodes, zAspects, yChildrenFirst)
             if not yStructuralNode.isAbstract:
                 yAspects = defaultdict(set)
                 for aspect in aspectModels[self.aspectModel]:
                     for ruleAspect in aspectRuleAspects.get(aspect, (aspect,)):
                         if yStructuralNode.hasAspect(ruleAspect):
                             if ruleAspect == Aspect.DIMENSIONS:
                                 for dim in (yStructuralNode.aspectValue(Aspect.DIMENSIONS) or emptyList):
                                     yAspects[dim].add(yStructuralNode)
                             else:
                                 yAspects[ruleAspect].add(yStructuralNode)
                     
                 gridSpacer(self.gridBody, self.dataFirstCol, row, LEFTBORDER)
                 # data for columns of row
                 ignoreDimValidity = self.ignoreDimValidity.get()
                 for i, xStructuralNode in enumerate(xStructuralNodes):
                     xAspects = defaultdict(set)
                     for aspect in aspectModels[self.aspectModel]:
                         for ruleAspect in aspectRuleAspects.get(aspect, (aspect,)):
                             if xStructuralNode.hasAspect(ruleAspect):
                                 if ruleAspect == Aspect.DIMENSIONS:
                                     for dim in (xStructuralNode.aspectValue(Aspect.DIMENSIONS) or emptyList):
                                         xAspects[dim].add(xStructuralNode)
                                 else:
                                     xAspects[ruleAspect].add(xStructuralNode)
                     cellAspectValues = {}
                     matchableAspects = set()
                     for aspect in _DICT_SET(xAspects.keys()) | _DICT_SET(yAspects.keys()) | _DICT_SET(zAspects.keys()):
                         aspectValue = inheritedAspectValue(self, aspect, xAspects, yAspects, zAspects, xStructuralNode, yStructuralNode)
                         if dimDefaults.get(aspect) != aspectValue: # don't include defaulted dimensions
                             cellAspectValues[aspect] = aspectValue
                         matchableAspects.add(aspectModelAspect.get(aspect,aspect)) #filterable aspect from rule aspect
                     cellDefaultedDims = _DICT_SET(dimDefaults) - _DICT_SET(cellAspectValues.keys())
                     priItemQname = cellAspectValues.get(Aspect.CONCEPT)
                         
                     concept = self.modelXbrl.qnameConcepts.get(priItemQname)
                     conceptNotAbstract = concept is None or not concept.isAbstract
                     from arelle.ValidateXbrlDimensions import isFactDimensionallyValid
                     value = None
                     objectId = None
                     justify = None
                     fp = FactPrototype(self, cellAspectValues)
                     if conceptNotAbstract:
                         # reduce set of matchable facts to those with pri item qname and have dimension aspects
                         facts = self.modelXbrl.factsByQname[priItemQname] if priItemQname else self.modelXbrl.factsInInstance
                         for aspect in matchableAspects:  # trim down facts with explicit dimensions match or just present
                             if isinstance(aspect, QName):
                                 aspectValue = cellAspectValues.get(aspect, None)
                                 if isinstance(aspectValue, ModelDimensionValue):
                                     if aspectValue.isExplicit:
                                         dimMemQname = aspectValue.memberQname # match facts with this explicit value
                                     else:
                                         dimMemQname = None  # match facts that report this dimension
                                 elif isinstance(aspectValue, QName): 
                                     dimMemQname = aspectValue  # match facts that have this explicit value
                                 else:
                                     dimMemQname = None # match facts that report this dimension
                                 facts = facts & self.modelXbrl.factsByDimMemQname(aspect, dimMemQname)
                         for fact in facts:
                             if (all(aspectMatches(rendrCntx, fact, fp, aspect) 
                                     for aspect in matchableAspects) and
                                 all(fact.context.dimMemberQname(dim,includeDefaults=True) in (dimDefaults[dim], None)
                                     for dim in cellDefaultedDims)):
                                 if yStructuralNode.hasValueExpression(xStructuralNode):
                                     value = yStructuralNode.evalValueExpression(fact, xStructuralNode)
                                 else:
                                     value = fact.effectiveValue
                                 objectId = fact.objectId()
                                 justify = "right" if fact.isNumeric else "left"
                                 break
                     if (conceptNotAbstract and
                         (value is not None or ignoreDimValidity or isFactDimensionallyValid(self, fp))):
                         if objectId is None:
                             objectId = "f{0}".format(len(self.factPrototypes))
                             self.factPrototypes.append(fp)  # for property views
                         gridCell(self.gridBody, self.dataFirstCol + i, row, value, justify=justify, 
                                  width=12, # width is in characters, not screen units
                                  objectId=objectId, onClick=self.onClick)
                     else:
                         fp.clear()  # dereference
                         gridSpacer(self.gridBody, self.dataFirstCol + i, row, CENTERCELL)
                     gridSpacer(self.gridBody, self.dataFirstCol + i, row, RIGHTBORDER)
                     gridSpacer(self.gridBody, self.dataFirstCol + i, row, BOTTOMBORDER)
                 row += 1
             if not yChildrenFirst:
                 row = self.bodyCells(row, yStructuralNode, xStructuralNodes, zAspects, yChildrenFirst)
         return row
    def bodyCells(self, row, yParentStructuralNode, xStructuralNodes, zAspects,
                  yChildrenFirst):
        if yParentStructuralNode is not None:
            rendrCntx = getattr(self.modelXbrl, "rendrCntx",
                                None)  # none for EU 2010 tables
            dimDefaults = self.modelXbrl.qnameDimensionDefaults
            for yStructuralNode in yParentStructuralNode.childStructuralNodes:
                if yChildrenFirst:
                    row = self.bodyCells(row, yStructuralNode,
                                         xStructuralNodes, zAspects,
                                         yChildrenFirst)
                if not yStructuralNode.isAbstract:
                    yAspects = defaultdict(set)
                    for aspect in aspectModels[self.aspectModel]:
                        for ruleAspect in aspectRuleAspects.get(
                                aspect, (aspect, )):
                            if yStructuralNode.hasAspect(ruleAspect):
                                if ruleAspect == Aspect.DIMENSIONS:
                                    for dim in (yStructuralNode.aspectValue(
                                            Aspect.DIMENSIONS) or emptyList):
                                        yAspects[dim].add(yStructuralNode)
                                else:
                                    yAspects[ruleAspect].add(yStructuralNode)

                    gridSpacer(self.gridBody, self.dataFirstCol, row,
                               LEFTBORDER)
                    # data for columns of row
                    ignoreDimValidity = self.ignoreDimValidity.get()
                    for i, xStructuralNode in enumerate(xStructuralNodes):
                        xAspects = defaultdict(set)
                        for aspect in aspectModels[self.aspectModel]:
                            for ruleAspect in aspectRuleAspects.get(
                                    aspect, (aspect, )):
                                if xStructuralNode.hasAspect(ruleAspect):
                                    if ruleAspect == Aspect.DIMENSIONS:
                                        for dim in (
                                                xStructuralNode.aspectValue(
                                                    Aspect.DIMENSIONS)
                                                or emptyList):
                                            xAspects[dim].add(xStructuralNode)
                                    else:
                                        xAspects[ruleAspect].add(
                                            xStructuralNode)
                        cellAspectValues = {}
                        matchableAspects = set()
                        for aspect in _DICT_SET(xAspects.keys()) | _DICT_SET(
                                yAspects.keys()) | _DICT_SET(zAspects.keys()):
                            aspectValue = inheritedAspectValue(
                                self, aspect, xAspects, yAspects, zAspects,
                                xStructuralNode, yStructuralNode)
                            if dimDefaults.get(
                                    aspect
                            ) != aspectValue:  # don't include defaulted dimensions
                                cellAspectValues[aspect] = aspectValue
                            matchableAspects.add(
                                aspectModelAspect.get(aspect, aspect)
                            )  #filterable aspect from rule aspect
                        cellDefaultedDims = _DICT_SET(dimDefaults) - _DICT_SET(
                            cellAspectValues.keys())
                        priItemQname = cellAspectValues.get(Aspect.CONCEPT)

                        concept = self.modelXbrl.qnameConcepts.get(
                            priItemQname)
                        conceptNotAbstract = concept is None or not concept.isAbstract
                        from arelle.ValidateXbrlDimensions import isFactDimensionallyValid
                        value = None
                        objectId = None
                        justify = None
                        fp = FactPrototype(self, cellAspectValues)
                        if conceptNotAbstract:
                            # reduce set of matchable facts to those with pri item qname and have dimension aspects
                            facts = self.modelXbrl.factsByQname[
                                priItemQname] if priItemQname else self.modelXbrl.factsInInstance
                            for aspect in matchableAspects:  # trim down facts with explicit dimensions match or just present
                                if isinstance(aspect, QName):
                                    aspectValue = cellAspectValues.get(
                                        aspect, None)
                                    if isinstance(aspectValue,
                                                  ModelDimensionValue):
                                        if aspectValue.isExplicit:
                                            dimMemQname = aspectValue.memberQname  # match facts with this explicit value
                                        else:
                                            dimMemQname = None  # match facts that report this dimension
                                    elif isinstance(aspectValue, QName):
                                        dimMemQname = aspectValue  # match facts that have this explicit value
                                    else:
                                        dimMemQname = None  # match facts that report this dimension
                                    facts = facts & self.modelXbrl.factsByDimMemQname(
                                        aspect, dimMemQname)
                            for fact in facts:
                                if (all(
                                        aspectMatches(rendrCntx, fact, fp,
                                                      aspect)
                                        for aspect in matchableAspects)
                                        and all(
                                            fact.context.dimMemberQname(
                                                dim, includeDefaults=True) in (
                                                    dimDefaults[dim], None)
                                            for dim in cellDefaultedDims)):
                                    if yStructuralNode.hasValueExpression(
                                            xStructuralNode):
                                        value = yStructuralNode.evalValueExpression(
                                            fact, xStructuralNode)
                                    else:
                                        value = fact.effectiveValue
                                    objectId = fact.objectId()
                                    justify = "right" if fact.isNumeric else "left"
                                    break
                        if (conceptNotAbstract
                                and (value is not None or ignoreDimValidity
                                     or isFactDimensionallyValid(self, fp))):
                            if objectId is None:
                                objectId = "f{0}".format(
                                    len(self.factPrototypes))
                                self.factPrototypes.append(
                                    fp)  # for property views
                            gridCell(
                                self.gridBody,
                                self.dataFirstCol + i,
                                row,
                                value,
                                justify=justify,
                                width=
                                12,  # width is in characters, not screen units
                                objectId=objectId,
                                onClick=self.onClick)
                        else:
                            fp.clear()  # dereference
                            gridSpacer(self.gridBody, self.dataFirstCol + i,
                                       row, CENTERCELL)
                        gridSpacer(self.gridBody, self.dataFirstCol + i, row,
                                   RIGHTBORDER)
                        gridSpacer(self.gridBody, self.dataFirstCol + i, row,
                                   BOTTOMBORDER)
                    row += 1
                if not yChildrenFirst:
                    row = self.bodyCells(row, yStructuralNode,
                                         xStructuralNodes, zAspects,
                                         yChildrenFirst)
            return row
Example #3
0
    def bodyCells(self, row, yParentStructuralNode, xStructuralNodes, zAspectStructuralNodes, yChildrenFirst, tblELR):
        if yParentStructuralNode is not None:
            dimDefaults = self.modelXbrl.qnameDimensionDefaults
            for yStructuralNode in yParentStructuralNode.childStructuralNodes:
                if yChildrenFirst:
                    row = self.bodyCells(row, yStructuralNode, xStructuralNodes, zAspectStructuralNodes, yChildrenFirst, tblELR)
                if not (yStructuralNode.isAbstract or 
                        (yStructuralNode.childStructuralNodes and
                         not isinstance(yStructuralNode.definitionNode, (ModelClosedDefinitionNode, ModelEuAxisCoord)))) and yStructuralNode.isLabeled:
                    yAspectStructuralNodes = defaultdict(set)
                    for aspect in aspectModels[self.aspectModel]:
                        if yStructuralNode.hasAspect(aspect):
                            if aspect == Aspect.DIMENSIONS:
                                for dim in (yStructuralNode.aspectValue(Aspect.DIMENSIONS) or emptyList):
                                    yAspectStructuralNodes[dim].add(yStructuralNode)
                            else:
                                yAspectStructuralNodes[aspect].add(yStructuralNode)
                    yTagSelectors = yStructuralNode.tagSelectors
                    # data for columns of rows
                    for _, xStructuralNode in enumerate(xStructuralNodes):
                        xAspectStructuralNodes = defaultdict(set)
                        for aspect in aspectModels[self.aspectModel]:
                            if xStructuralNode.hasAspect(aspect):
                                if aspect == Aspect.DIMENSIONS:
                                    for dim in (xStructuralNode.aspectValue(Aspect.DIMENSIONS) or emptyList):
                                        xAspectStructuralNodes[dim].add(xStructuralNode)
                                else:
                                    xAspectStructuralNodes[aspect].add(xStructuralNode)
                        cellTagSelectors = yTagSelectors | xStructuralNode.tagSelectors
                        cellAspectValues = {}
                        matchableAspects = set()
                        for aspect in _DICT_SET(xAspectStructuralNodes.keys()) | _DICT_SET(yAspectStructuralNodes.keys()) | _DICT_SET(zAspectStructuralNodes.keys()):  # @UndefinedVariable
                            aspectValue = xStructuralNode.inheritedAspectValue(yStructuralNode,
                                               self, aspect, cellTagSelectors, 
                                               xAspectStructuralNodes, yAspectStructuralNodes, zAspectStructuralNodes)
                            # value is None for a dimension whose value is to be not reported in this slice
                            if (isinstance(aspect, _INT) or  # not a dimension @UndefinedVariable
                                dimDefaults.get(aspect) != aspectValue or # explicit dim defaulted will equal the value
                                aspectValue is not None): # typed dim absent will be none
                                cellAspectValues[aspect] = aspectValue
                            matchableAspects.add(aspectModelAspect.get(aspect,aspect)) #filterable aspect from rule aspect
                        cellDefaultedDims = _DICT_SET(dimDefaults) - _DICT_SET(cellAspectValues.keys())  # @UndefinedVariable
                        priItemQname = cellAspectValues.get(Aspect.CONCEPT)
                            
                        concept = self.modelXbrl.qnameConcepts.get(priItemQname)
                        conceptNotAbstract = concept is None or not concept.isAbstract
                        fact = None
                        value = None
                        fp = FactPrototype(self, cellAspectValues)
                        if conceptNotAbstract:
                            # reduce set of matchable facts to those with pri item qname and have dimension aspects
                            facts = self.modelXbrl.factsByQname(priItemQname, set()) if priItemQname else self.modelXbrl.factsInInstance
                            if self.hasTableFilters:
                                facts = self.modelTable.filterFacts(self.rendrCntx, facts)
                            for aspect in matchableAspects:  # trim down facts with explicit dimensions match or just present
                                if isinstance(aspect, QName):
                                    aspectValue = cellAspectValues.get(aspect, None)
                                    if isinstance(aspectValue, ModelDimensionValue):
                                        if aspectValue.isExplicit:
                                            dimMemQname = aspectValue.memberQname # match facts with this explicit value
                                        else:
                                            dimMemQname = None  # match facts that report this dimension
                                    elif isinstance(aspectValue, QName): 
                                        dimMemQname = aspectValue  # match facts that have this explicit value
                                    elif aspectValue is None: # match typed dims that don't report this value
                                        dimMemQname = DEFAULT
                                    else:
                                        dimMemQname = None # match facts that report this dimension
                                    facts = facts & self.modelXbrl.factsByDimMemQname(aspect, dimMemQname)
                                    if len(facts)==0:
                                        break;
                            for fact in facts:
                                if (all(aspectMatches(self.rendrCntx, fact, fp, aspect) 
                                        for aspect in matchableAspects) and
                                    all(fact.context.dimMemberQname(dim,includeDefaults=True) in (dimDefaults[dim], None)
                                        for dim in cellDefaultedDims) and
                                    len(fp.context.qnameDims) == len(fact.context.qnameDims)):
                                    if yStructuralNode.hasValueExpression(xStructuralNode):
                                        value = yStructuralNode.evalValueExpression(fact, xStructuralNode)
                                    else:
                                        value = fact.effectiveValue
                                    self.factWalkingAction.onFactEvent(fact, value, tblELR)
                                    break

                        fp.clear()  # dereference
                    row += 1
                if not yChildrenFirst:
                    row = self.bodyCells(row, yStructuralNode, xStructuralNodes, zAspectStructuralNodes, yChildrenFirst, tblELR)
        return row
            
Example #4
0
 def bodyCells(self, row, yParentStructuralNode, xStructuralNodes, zAspectStructuralNodes, yChildrenFirst):
     if yParentStructuralNode is not None:
         rendrCntx = getattr(self.modelXbrl, "rendrCntx", None) # none for EU 2010 tables
         dimDefaults = self.modelXbrl.qnameDimensionDefaults
         for yStructuralNode in yParentStructuralNode.childStructuralNodes:
             if yChildrenFirst:
                 row = self.bodyCells(row, yStructuralNode, xStructuralNodes, zAspectStructuralNodes, yChildrenFirst)
             if not (yStructuralNode.isAbstract or 
                     (yStructuralNode.childStructuralNodes and
                      not isinstance(yStructuralNode.definitionNode, (ModelClosedDefinitionNode, ModelEuAxisCoord)))) and yStructuralNode.isLabeled:
                 isEntryPrototype = yStructuralNode.isEntryPrototype(default=False) # row to enter open aspects
                 yAspectStructuralNodes = defaultdict(set)
                 for aspect in aspectModels[self.aspectModel]:
                     if yStructuralNode.hasAspect(aspect):
                         if aspect == Aspect.DIMENSIONS:
                             for dim in (yStructuralNode.aspectValue(Aspect.DIMENSIONS) or emptyList):
                                 yAspectStructuralNodes[dim].add(yStructuralNode)
                         else:
                             yAspectStructuralNodes[aspect].add(yStructuralNode)
                 yTagSelectors = yStructuralNode.tagSelectors
                 gridSpacer(self.gridBody, self.dataFirstCol, row, LEFTBORDER)
                 # data for columns of row
                 #print ("row " + str(row) + "yNode " + yStructuralNode.definitionNode.objectId() )
                 ignoreDimValidity = self.ignoreDimValidity.get()
                 for i, xStructuralNode in enumerate(xStructuralNodes):
                     xAspectStructuralNodes = defaultdict(set)
                     for aspect in aspectModels[self.aspectModel]:
                         if xStructuralNode.hasAspect(aspect):
                             if aspect == Aspect.DIMENSIONS:
                                 for dim in (xStructuralNode.aspectValue(Aspect.DIMENSIONS) or emptyList):
                                     xAspectStructuralNodes[dim].add(xStructuralNode)
                             else:
                                 xAspectStructuralNodes[aspect].add(xStructuralNode)
                     cellTagSelectors = yTagSelectors | xStructuralNode.tagSelectors
                     cellAspectValues = {}
                     matchableAspects = set()
                     for aspect in _DICT_SET(xAspectStructuralNodes.keys()) | _DICT_SET(yAspectStructuralNodes.keys()) | _DICT_SET(zAspectStructuralNodes.keys()):
                         aspectValue = xStructuralNode.inheritedAspectValue(yStructuralNode,
                                            self, aspect, cellTagSelectors, 
                                            xAspectStructuralNodes, yAspectStructuralNodes, zAspectStructuralNodes)
                         # value is None for a dimension whose value is to be not reported in this slice
                         if (isinstance(aspect, _INT) or  # not a dimension
                             dimDefaults.get(aspect) != aspectValue or # explicit dim defaulted will equal the value
                             aspectValue is not None): # typed dim absent will be none
                             cellAspectValues[aspect] = aspectValue
                         matchableAspects.add(aspectModelAspect.get(aspect,aspect)) #filterable aspect from rule aspect
                     cellDefaultedDims = _DICT_SET(dimDefaults) - _DICT_SET(cellAspectValues.keys())
                     priItemQname = cellAspectValues.get(Aspect.CONCEPT)
                         
                     concept = self.modelXbrl.qnameConcepts.get(priItemQname)
                     conceptNotAbstract = concept is None or not concept.isAbstract
                     from arelle.ValidateXbrlDimensions import isFactDimensionallyValid
                     value = None
                     objectId = None
                     justify = None
                     fp = FactPrototype(self, cellAspectValues)
                     if conceptNotAbstract:
                         # reduce set of matchable facts to those with pri item qname and have dimension aspects
                         facts = self.modelXbrl.factsByQname[priItemQname] if priItemQname else self.modelXbrl.factsInInstance
                         for aspect in matchableAspects:  # trim down facts with explicit dimensions match or just present
                             if isinstance(aspect, QName):
                                 aspectValue = cellAspectValues.get(aspect, None)
                                 if isinstance(aspectValue, ModelDimensionValue):
                                     if aspectValue.isExplicit:
                                         dimMemQname = aspectValue.memberQname # match facts with this explicit value
                                     else:
                                         dimMemQname = None  # match facts that report this dimension
                                 elif isinstance(aspectValue, QName): 
                                     dimMemQname = aspectValue  # match facts that have this explicit value
                                 elif aspectValue is None: # match typed dims that don't report this value
                                     dimMemQname = ModelXbrl.DEFAULT
                                 else:
                                     dimMemQname = None # match facts that report this dimension
                                 facts = facts & self.modelXbrl.factsByDimMemQname(aspect, dimMemQname)
                         for fact in facts:
                             if (all(aspectMatches(rendrCntx, fact, fp, aspect) 
                                     for aspect in matchableAspects) and
                                 all(fact.context.dimMemberQname(dim,includeDefaults=True) in (dimDefaults[dim], None)
                                     for dim in cellDefaultedDims)):
                                 if yStructuralNode.hasValueExpression(xStructuralNode):
                                     value = yStructuralNode.evalValueExpression(fact, xStructuralNode)
                                 else:
                                     value = fact.effectiveValue
                                 objectId = fact.objectId()
                                 justify = "right" if fact.isNumeric else "left"
                                 break
                     if (conceptNotAbstract and
                         (value is not None or ignoreDimValidity or isFactDimensionallyValid(self, fp) or
                          isEntryPrototype)):
                         if objectId is None:
                             objectId = "f{0}".format(len(self.factPrototypes))
                             self.factPrototypes.append(fp)  # for property views
                             for aspect, aspectValue in cellAspectValues.items():
                                 if isinstance(aspectValue, str) and aspectValue.startswith(OPEN_ASPECT_ENTRY_SURROGATE):
                                     self.factPrototypeAspectEntryObjectIds[objectId].add(aspectValue) 
                         gridCell(self.gridBody, self.dataFirstCol + i, row, value, justify=justify, 
                                  width=12, # width is in characters, not screen units
                                  objectId=objectId, onClick=self.onClick)
                     else:
                         fp.clear()  # dereference
                         gridSpacer(self.gridBody, self.dataFirstCol + i, row, CENTERCELL)
                     gridSpacer(self.gridBody, self.dataFirstCol + i, row, RIGHTBORDER)
                     gridSpacer(self.gridBody, self.dataFirstCol + i, row, BOTTOMBORDER)
                 row += 1
             if not yChildrenFirst:
                 row = self.bodyCells(row, yStructuralNode, xStructuralNodes, zAspectStructuralNodes, yChildrenFirst)
         return row
Example #5
0
    def createContext(self,
                      entityIdentScheme,
                      entityIdentValue,
                      periodType,
                      periodStart,
                      periodEndInstant,
                      priItem,
                      dims,
                      segOCCs,
                      scenOCCs,
                      afterSibling=None,
                      beforeSibling=None):
        xbrlElt = self.modelDocument.xmlRootElement
        if afterSibling == AUTO_LOCATE_ELEMENT:
            afterSibling = XmlUtil.lastChild(
                xbrlElt, XbrlConst.xbrli,
                ("schemaLocation", "roleType", "arcroleType", "context"))
        cntxId = 'c-{0:02n}'.format(len(self.contexts) + 1)
        newCntxElt = XmlUtil.addChild(xbrlElt,
                                      XbrlConst.xbrli,
                                      "context",
                                      attributes=("id", cntxId),
                                      afterSibling=afterSibling,
                                      beforeSibling=beforeSibling)
        entityElt = XmlUtil.addChild(newCntxElt, XbrlConst.xbrli, "entity")
        XmlUtil.addChild(entityElt,
                         XbrlConst.xbrli,
                         "identifier",
                         attributes=("scheme", entityIdentScheme),
                         text=entityIdentValue)
        periodElt = XmlUtil.addChild(newCntxElt, XbrlConst.xbrli, "period")
        if periodType == "forever":
            XmlUtil.addChild(periodElt, XbrlConst.xbrli, "forever")
        elif periodType == "instant":
            XmlUtil.addChild(periodElt,
                             XbrlConst.xbrli,
                             "instant",
                             text=XmlUtil.dateunionValue(periodEndInstant,
                                                         subtractOneDay=True))
        elif periodType == "duration":
            XmlUtil.addChild(periodElt,
                             XbrlConst.xbrli,
                             "startDate",
                             text=XmlUtil.dateunionValue(periodStart))
            XmlUtil.addChild(periodElt,
                             XbrlConst.xbrli,
                             "endDate",
                             text=XmlUtil.dateunionValue(periodEndInstant,
                                                         subtractOneDay=True))
        segmentElt = None
        scenarioElt = None
        from arelle.ModelInstanceObject import ModelDimensionValue
        if dims:  # requires primary item to determin ambiguous concepts
            ''' in theory we have to check full set of dimensions for validity in source or any other
                context element, but for shortcut will see if each dimension is already reported in an
                unambiguous valid contextElement
            '''
            from arelle.PrototypeInstanceObject import FactPrototype, ContextPrototype, DimValuePrototype
            fp = FactPrototype(self, priItem, dims.items())
            # force trying a valid prototype's context Elements
            if not isFactDimensionallyValid(
                    self, fp, setPrototypeContextElements=True):
                self.info(
                    "arelleLinfo",
                    _("Create context for %(priItem)s, cannot determine valid context elements, no suitable hypercubes"
                      ),
                    modelObject=self,
                    priItem=priItem)
            fpDims = fp.context.qnameDims
            for dimQname in sorted(fpDims.keys()):
                dimValue = fpDims[dimQname]
                if isinstance(dimValue, DimValuePrototype):
                    dimMemberQname = dimValue.memberQname  # None if typed dimension
                    contextEltName = dimValue.contextElement
                else:  # qname for explicit or node for typed
                    dimMemberQname = None
                    contextEltName = None
                if contextEltName == "segment":
                    if segmentElt is None:
                        segmentElt = XmlUtil.addChild(entityElt,
                                                      XbrlConst.xbrli,
                                                      "segment")
                    contextElt = segmentElt
                elif contextEltName == "scenario":
                    if scenarioElt is None:
                        scenarioElt = XmlUtil.addChild(newCntxElt,
                                                       XbrlConst.xbrli,
                                                       "scenario")
                    contextElt = scenarioElt
                else:
                    self.info(
                        "arelleLinfo",
                        _("Create context, %(dimension)s, cannot determine context element, either no all relationship or validation issue"
                          ),
                        modelObject=self,
                        dimension=dimQname),
                    continue
                dimConcept = self.qnameConcepts[dimQname]
                dimAttr = ("dimension",
                           XmlUtil.addQnameValue(xbrlElt, dimConcept.qname))
                if dimConcept.isTypedDimension:
                    dimElt = XmlUtil.addChild(contextElt,
                                              XbrlConst.xbrldi,
                                              "xbrldi:typedMember",
                                              attributes=dimAttr)
                    if isinstance(dimValue,
                                  (ModelDimensionValue,
                                   DimValuePrototype)) and dimValue.isTyped:
                        XmlUtil.copyNodes(dimElt, dimValue.typedMember)
                elif dimMemberQname:
                    dimElt = XmlUtil.addChild(contextElt,
                                              XbrlConst.xbrldi,
                                              "xbrldi:explicitMember",
                                              attributes=dimAttr,
                                              text=XmlUtil.addQnameValue(
                                                  xbrlElt, dimMemberQname))
        if segOCCs:
            if segmentElt is None:
                segmentElt = XmlUtil.addChild(entityElt, XbrlConst.xbrli,
                                              "segment")
            XmlUtil.copyNodes(segmentElt, segOCCs)
        if scenOCCs:
            if scenarioElt is None:
                scenarioElt = XmlUtil.addChild(newCntxElt, XbrlConst.xbrli,
                                               "scenario")
            XmlUtil.copyNodes(scenarioElt, scenOCCs)

        self.modelDocument.contextDiscover(newCntxElt)
        XmlValidate.validate(self, newCntxElt)
        return newCntxElt
Example #6
0
    def bodyCells(self, row, yAxisParentObj, xFilters, zFilters,
                  yChildrenFirst):
        dimDefaults = self.modelXbrl.qnameDimensionDefaults
        priItemQnameErrors = set()
        dimQnameErrors = set()
        memQnameErrors = set()
        for axisMbrRel in self.axisMbrRelSet.fromModelObject(yAxisParentObj):
            yAxisHdrObj = axisMbrRel.toModelObject
            if yChildrenFirst:
                row = self.bodyCells(row, yAxisHdrObj, xFilters, zFilters,
                                     yChildrenFirst)
            if yAxisHdrObj.abstract == "false":
                yAxisPriItemQname = inheritedPrimaryItemQname(
                    self, yAxisHdrObj)
                yAxisExplicitDims = inheritedExplicitDims(self, yAxisHdrObj)

                gridSpacer(self.gridBody, self.dataFirstCol, row, LEFTBORDER)
                # data for columns of row
                ignoreDimValidity = self.ignoreDimValidity.get()
                zPriItemQname = None
                zDims = set()
                for zIndex in self.zFilterIndex:
                    zFilter = zFilters[zIndex]
                    if zFilter[0]:
                        zPriItemQname = zFilter[0]  # inherit pri item
                    zDims |= zFilter[1]  # or in z-dims
                for i, colFilter in enumerate(xFilters):
                    colPriItemQname = colFilter[0]  # y axis pri item
                    if not colPriItemQname:
                        colPriItemQname = yAxisPriItemQname  # y axis
                    if not colPriItemQname:
                        colPriItemQname = zPriItemQname  # z axis
                    fp = FactPrototype(
                        self, colPriItemQname,
                        yAxisExplicitDims | colFilter[1] | zDims)
                    from arelle.ValidateXbrlDimensions import isFactDimensionallyValid
                    value = None
                    objectId = None
                    justify = None
                    for fact in self.modelXbrl.facts:
                        if fact.qname == fp.qname:
                            factDimMem = fact.context.dimMemberQname
                            defaultedDims = _DICT_SET(
                                dimDefaults.keys()) - fp.dimKeys
                            if (all(
                                    factDimMem(dim, includeDefaults=True) ==
                                    mem for dim, mem in fp.dims) and all(
                                        factDimMem(dim, includeDefaults=True)
                                        in (dimDefaults[dim], None)
                                        for dim in defaultedDims)):
                                value = fact.effectiveValue
                                objectId = fact.objectId()
                                justify = "right" if fact.isNumeric else "left"
                                break
                    if value is not None or ignoreDimValidity or isFactDimensionallyValid(
                            self, fp):
                        if objectId is None:
                            objectId = "f{0}".format(len(self.factPrototypes))
                            self.factPrototypes.append(
                                fp)  # for property views
                        gridCell(
                            self.gridBody,
                            self.dataFirstCol + i,
                            row,
                            value,
                            justify=justify,
                            width=12,  # width is in characters, not screen units
                            objectId=objectId,
                            onClick=self.onClick)
                    else:
                        gridSpacer(self.gridBody, self.dataFirstCol + i, row,
                                   CENTERCELL)
                    gridSpacer(self.gridBody, self.dataFirstCol + i, row,
                               RIGHTBORDER)
                    gridSpacer(self.gridBody, self.dataFirstCol + i, row,
                               BOTTOMBORDER)
                row += 1
            if not yChildrenFirst:
                row = self.bodyCells(row, yAxisHdrObj, xFilters, zFilters,
                                     yChildrenFirst)
        return row
Example #7
0
 def bodyCells(self, row, yParentStructuralNode, xStructuralNodes, zAspects, yChildrenFirst):
     if yParentStructuralNode is not None:
         rendrCntx = getattr(self.modelXbrl, "rendrCntx", None) # none for EU 2010 tables
         dimDefaults = self.modelXbrl.qnameDimensionDefaults
         for yStructuralNode in yParentStructuralNode.childStructuralNodes:
             if yChildrenFirst:
                 row = self.bodyCells(row, yStructuralNode, xStructuralNodes, zAspects, yChildrenFirst)
             if not yStructuralNode.isAbstract:
                 if self.type == XML:
                     self.xCells = etree.SubElement(self.yCells, tableModelQName("cells"),
                                                    attrib={"disposition": "x"})
                 yAspects = defaultdict(set)
                 for aspect in aspectModels[self.aspectModel]:
                     for ruleAspect in aspectRuleAspects.get(aspect, (aspect,)):
                         if yStructuralNode.hasAspect(ruleAspect):
                             if ruleAspect == Aspect.DIMENSIONS:
                                 for dim in (yStructuralNode.aspectValue(Aspect.DIMENSIONS) or emptyList):
                                     yAspects[dim].add(yStructuralNode)
                             else:
                                 yAspects[ruleAspect].add(yStructuralNode)
                 # data for columns of rows
                 ignoreDimValidity = self.ignoreDimValidity.get()
                 for i, xStructuralNode in enumerate(xStructuralNodes):
                     xAspects = defaultdict(set)
                     for aspect in aspectModels[self.aspectModel]:
                         for ruleAspect in aspectRuleAspects.get(aspect, (aspect,)):
                             if xStructuralNode.hasAspect(ruleAspect):
                                 if ruleAspect == Aspect.DIMENSIONS:
                                     for dim in (xStructuralNode.aspectValue(Aspect.DIMENSIONS) or emptyList):
                                         xAspects[dim].add(xStructuralNode)
                                 else:
                                     xAspects[ruleAspect].add(xStructuralNode)
                     cellAspectValues = {}
                     matchableAspects = set()
                     for aspect in _DICT_SET(xAspects.keys()) | _DICT_SET(yAspects.keys()) | _DICT_SET(zAspects.keys()):
                         aspectValue = inheritedAspectValue(self, aspect, xAspects, yAspects, zAspects, xStructuralNode, yStructuralNode)
                         if dimDefaults.get(aspect) != aspectValue: # don't include defaulted dimensions
                             cellAspectValues[aspect] = aspectValue
                         matchableAspects.add(aspectModelAspect.get(aspect,aspect)) #filterable aspect from rule aspect
                     cellDefaultedDims = _DICT_SET(dimDefaults) - _DICT_SET(cellAspectValues.keys())
                     priItemQname = cellAspectValues.get(Aspect.CONCEPT)
                         
                     concept = self.modelXbrl.qnameConcepts.get(priItemQname)
                     conceptNotAbstract = concept is None or not concept.isAbstract
                     from arelle.ValidateXbrlDimensions import isFactDimensionallyValid
                     value = None
                     objectId = None
                     justify = None
                     fp = FactPrototype(self, cellAspectValues)
                     if conceptNotAbstract:
                         # reduce set of matchable facts to those with pri item qname and have dimension aspects
                         facts = self.modelXbrl.factsByQname[priItemQname] if priItemQname else self.modelXbrl.factsInInstance
                         for aspect in matchableAspects:  # trim down facts with explicit dimensions match or just present
                             if isinstance(aspect, QName):
                                 aspectValue = cellAspectValues.get(aspect, None)
                                 if isinstance(aspectValue, ModelDimensionValue):
                                     if aspectValue.isExplicit:
                                         dimMemQname = aspectValue.memberQname # match facts with this explicit value
                                     else:
                                         dimMemQname = None  # match facts that report this dimension
                                 elif isinstance(aspectValue, QName): 
                                     dimMemQname = aspectValue  # match facts that have this explicit value
                                 else:
                                     dimMemQname = None # match facts that report this dimension
                                 facts = facts & self.modelXbrl.factsByDimMemQname(aspect, dimMemQname)
                         for fact in facts:
                             if (all(aspectMatches(rendrCntx, fact, fp, aspect) 
                                     for aspect in matchableAspects) and
                                 all(fact.context.dimMemberQname(dim,includeDefaults=True) in (dimDefaults[dim], None)
                                     for dim in cellDefaultedDims)):
                                 if yStructuralNode.hasValueExpression(xStructuralNode):
                                     value = yStructuralNode.evalValueExpression(fact, xStructuralNode)
                                 else:
                                     value = fact.effectiveValue
                                 justify = "right" if fact.isNumeric else "left"
                                 break
                     if conceptNotAbstract:
                         if value is not None or ignoreDimValidity or isFactDimensionallyValid(self, fp):
                             if self.type == HTML:
                                 etree.SubElement(self.rowElts[row - 1], 
                                                  "{http://www.w3.org/1999/xhtml}td",
                                                  attrib={"class":"cell",
                                                          "style":"text-align:{0};width:8em".format(justify)}
                                                  ).text = value or "\u00A0"
                             elif self.type == XML:
                                 if value is not None and fact is not None:
                                     self.xCells.append(etree.Comment("{0}: context {1}, value {2}, file {3}, line {4}"
                                                                      .format(fact.qname,
                                                                              fact.contextID,
                                                                              value,
                                                                              fact.modelDocument.basename, 
                                                                              fact.sourceline)))
 
                                 cellElt = etree.SubElement(self.xCells, tableModelQName("cell"))
                                 etree.SubElement(cellElt, tableModelQName("fact")
                                                  ).text = '#' + elementFragmentIdentifier(fact)
                         else:
                             if self.type == HTML:
                                 etree.SubElement(self.rowElts[row - 1], 
                                                  "{http://www.w3.org/1999/xhtml}td",
                                                  attrib={"class":"blockedCell",
                                                          "style":"text-align:{0};width:8em".format(justify)}
                                                  ).text = "\u00A0\u00A0"
                             elif self.type == XML:
                                 etree.SubElement(self.xCells, tableModelQName("cell"),
                                                  attrib={"blocked":"true"})
                     else: # concept is abstract
                         if self.type == HTML:
                             etree.SubElement(self.rowElts[row - 1], 
                                              "{http://www.w3.org/1999/xhtml}td",
                                              attrib={"class":"abstractCell",
                                                      "style":"text-align:{0};width:8em".format(justify)}
                                              ).text = "\u00A0\u00A0"
                         elif self.type == XML:
                             etree.SubElement(self.xCells, tableModelQName("cell"),
                                              attrib={"abstract":"true"})
                     fp.clear()  # dereference
                 row += 1
             if not yChildrenFirst:
                 row = self.bodyCells(row, yStructuralNode, xStructuralNodes, zAspects, yChildrenFirst)
     return row
         
Example #8
0
    def bodyCells(self, row, yAxisParentObj, xFilters, zFilters,
                  yChildrenFirst):
        dimDefaults = self.modelXbrl.qnameDimensionDefaults
        for axisMbrRel in self.axisMbrRelSet.fromModelObject(yAxisParentObj):
            yAxisHdrObj = axisMbrRel.toModelObject
            if yChildrenFirst:
                row = self.bodyCells(row, yAxisHdrObj, xFilters, zFilters,
                                     yChildrenFirst)
            if yAxisHdrObj.abstract == "false":
                yAxisPriItemQname = inheritedPrimaryItemQname(
                    self, yAxisHdrObj)
                yAxisExplicitDims = inheritedExplicitDims(self, yAxisHdrObj)

                # data for columns of row
                ignoreDimValidity = self.ignoreDimValidity.get()
                zPriItemQname = None
                zDims = set()
                for zIndex in self.zFilterIndex:
                    zFilter = zFilters[zIndex]
                    if zFilter[0]:
                        zPriItemQname = zFilter[0]  # inherit pri item
                    zDims |= zFilter[1]  # or in z-dims
                for i, colFilter in enumerate(xFilters):
                    colPriItemQname = colFilter[0]  # y axis pri item
                    if not colPriItemQname:
                        colPriItemQname = yAxisPriItemQname  # y axis
                    if not colPriItemQname:
                        colPriItemQname = zPriItemQname  # z axis
                    fp = FactPrototype(
                        self, colPriItemQname,
                        yAxisExplicitDims | colFilter[1] | zDims)
                    from arelle.ValidateXbrlDimensions import isFactDimensionallyValid
                    value = None
                    objectId = None
                    justify = None
                    for fact in self.modelXbrl.facts:
                        if fact.qname == fp.qname:
                            factDimMem = fact.context.dimMemberQname
                            defaultedDims = dimDefaults.keys() - fp.dimKeys
                            if (all(
                                    factDimMem(dim, includeDefaults=True) ==
                                    mem for dim, mem in fp.dims) and all(
                                        factDimMem(dim, includeDefaults=True)
                                        in (dimDefaults[dim], None)
                                        for dim in defaultedDims)):
                                value = fact.effectiveValue
                                objectId = fact.objectId()
                                justify = "right" if fact.isNumeric else "left"
                                break
                    if value is not None or ignoreDimValidity or isFactDimensionallyValid(
                            self, fp):
                        etree.SubElement(
                            self.rowElts[row - 1],
                            "{http://www.w3.org/1999/xhtml}td",
                            attrib={
                                "class": "cell",
                                "style":
                                "text-align:{0};width:8em".format(justify)
                            }).text = value if value else "\u00A0"
                    else:
                        etree.SubElement(
                            self.rowElts[row - 1],
                            "{http://www.w3.org/1999/xhtml}td",
                            attrib={
                                "class": "blockedCell",
                                "style":
                                "text-align:{0};width:8em".format(justify)
                            }).text = "\u00A0\u00A0"
                row += 1
            if not yChildrenFirst:
                row = self.bodyCells(row, yAxisHdrObj, xFilters, zFilters,
                                     yChildrenFirst)
        return row
Example #9
0
def expandDefinition(view,
                     structuralNode,
                     breakdownNode,
                     definitionNode,
                     depth,
                     axisDisposition,
                     facts,
                     i=None,
                     tblAxisRels=None,
                     processOpenDefinitionNode=True):
    subtreeRelationships = view.axisSubtreeRelSet.fromModelObject(
        definitionNode)

    def checkLabelWidth(structuralNode, checkBoundFact=False):
        if axisDisposition == "y":
            # messages can't be evaluated, just use the text portion of format string
            label = structuralNode.header(
                lang=view.lang,
                returnGenLabel=not checkBoundFact,
                returnMsgFormatString=not checkBoundFact)
            if label:
                # need to et more exact word length in screen units
                widestWordLen = max(
                    len(w) * RENDER_UNITS_PER_CHAR for w in label.split())
                # abstract only pertains to subtree of closed nodesbut not cartesian products or open nodes
                while structuralNode.depth >= len(view.rowHdrColWidth):
                    view.rowHdrColWidth.append(0)
                if definitionNode.isAbstract or not subtreeRelationships:  # isinstance(definitionNode, ModelOpenDefinitionNode):
                    if widestWordLen > view.rowHdrColWidth[
                            structuralNode.depth]:
                        view.rowHdrColWidth[
                            structuralNode.depth] = widestWordLen
                else:
                    if widestWordLen > view.rowNonAbstractHdrSpanMin[
                            structuralNode.depth]:
                        view.rowNonAbstractHdrSpanMin[
                            structuralNode.depth] = widestWordLen

    if structuralNode and isinstance(
            definitionNode,
        (ModelBreakdown, ModelEuAxisCoord, ModelDefinitionNode)):
        try:
            #cartesianProductNestedArgs = (view, depth, axisDisposition, facts, tblAxisRels, i)
            ordCardinality, ordDepth = definitionNode.cardinalityAndDepth(
                structuralNode)
            if (not definitionNode.isAbstract
                    and isinstance(definitionNode, ModelClosedDefinitionNode)
                    and ordCardinality == 0):
                view.modelXbrl.error(
                    "xbrlte:closedDefinitionNodeZeroCardinality",
                    _("Closed definition node %(xlinkLabel)s does not contribute at least one structural node"
                      ),
                    modelObject=(view.modelTable, definitionNode),
                    xlinkLabel=definitionNode.xlinkLabel,
                    axis=definitionNode.localName)
            nestedDepth = depth + ordDepth
            # HF test
            cartesianProductNestedArgs = [
                view, nestedDepth, axisDisposition, facts, tblAxisRels, i
            ]
            if axisDisposition == "z":
                if depth == 1:  # choices (combo boxes) don't add to z row count
                    view.zAxisRows += 1
            elif axisDisposition == "x":
                if ordDepth:
                    if nestedDepth - 1 > view.colHdrRows:
                        view.colHdrRows = nestedDepth - 1
                    '''
                    if not view.colHdrDocRow:
                        if definitionNode.header(role="http://www.xbrl.org/2008/role/documentation",
                                                       lang=view.lang): 
                            view.colHdrDocRow = True
                    if not view.colHdrCodeRow:
                        if definitionNode.header(role="http://www.eurofiling.info/role/2010/coordinate-code"): 
                            view.colHdrCodeRow = True
                    '''
                hdrNonStdRoles = view.colHdrNonStdRoles
            elif axisDisposition == "y":
                if ordDepth:
                    #if not definitionNode.isAbstract:
                    #    view.dataRows += ordCardinality
                    if nestedDepth - 1 > view.rowHdrCols:
                        view.rowHdrCols = nestedDepth - 1
                        for j in range(1 + ordDepth):
                            view.rowHdrColWidth.append(
                                RENDER_UNITS_PER_CHAR
                            )  # min width for 'tail' of nonAbstract coordinate
                            view.rowNonAbstractHdrSpanMin.append(0)
                    checkLabelWidth(structuralNode, checkBoundFact=False)
                    ''' 
                    if not view.rowHdrDocCol:
                        if definitionNode.header(role="http://www.xbrl.org/2008/role/documentation",
                                             lang=view.lang): 
                            view.rowHdrDocCol = True
                    if not view.rowHdrCodeCol:
                        if definitionNode.header(role="http://www.eurofiling.info/role/2010/coordinate-code"): 
                            view.rowHdrCodeCol = True
                    '''
                hdrNonStdRoles = view.rowHdrNonStdRoles
            if axisDisposition in ("x", "y"):
                hdrNonStdPosition = -1  # where a match last occured
                for rel in view.modelXbrl.relationshipSet(
                        XbrlConst.elementLabel).fromModelObject(
                            definitionNode):
                    if rel.toModelObject is not None and rel.toModelObject.role != XbrlConst.genStandardLabel:
                        labelLang = rel.toModelObject.xmlLang
                        labelRole = rel.toModelObject.role
                        if (labelLang == view.lang
                                or labelLang.startswith(view.lang)
                                or view.lang.startswith(labelLang)
                                or ("code" in labelRole)):
                            labelRole = rel.toModelObject.role
                            if labelRole in hdrNonStdRoles:
                                hdrNonStdPosition = hdrNonStdRoles.index(
                                    labelRole)
                            else:
                                hdrNonStdRoles.insert(hdrNonStdPosition + 1,
                                                      labelRole)
            isCartesianProductExpanded = False
            if not isinstance(definitionNode, ModelFilterDefinitionNode):
                isCartesianProductExpanded = True
                # note: reduced set of facts should always be passed to subsequent open nodes
                for axisSubtreeRel in subtreeRelationships:
                    childDefinitionNode = axisSubtreeRel.toModelObject
                    if childDefinitionNode.isRollUp:
                        structuralNode.rollUpStructuralNode = StructuralNode(
                            structuralNode,
                            breakdownNode,
                            childDefinitionNode,
                        )
                        if not structuralNode.childStructuralNodes:  # first sub ordinate is the roll up
                            structuralNode.subtreeRollUp = CHILD_ROLLUP_FIRST
                        else:
                            structuralNode.subtreeRollUp = CHILD_ROLLUP_LAST
                        if not view.topRollup.get(axisDisposition):
                            view.topRollup[
                                axisDisposition] = structuralNode.subtreeRollUp
                    else:
                        if (
                                isinstance(definitionNode,
                                           (ModelBreakdown,
                                            ModelCompositionDefinitionNode))
                                and isinstance(
                                    childDefinitionNode,
                                    ModelRelationshipDefinitionNode)
                        ):  # append list products to composititionAxes subObjCntxs
                            childStructuralNode = structuralNode
                        else:
                            childStructuralNode = StructuralNode(
                                structuralNode, breakdownNode,
                                childDefinitionNode
                            )  # others are nested structuralNode
                            if axisDisposition != "z":
                                structuralNode.childStructuralNodes.append(
                                    childStructuralNode)
                        if axisDisposition != "z":
                            expandDefinition(view, childStructuralNode,
                                             breakdownNode,
                                             childDefinitionNode,
                                             depth + ordDepth, axisDisposition,
                                             facts, i, tblAxisRels)  #recurse
                            cartesianProductExpander(
                                childStructuralNode,
                                *cartesianProductNestedArgs)
                        else:
                            childStructuralNode.indent = depth - 1
                            if structuralNode.choiceStructuralNodes is not None:
                                structuralNode.choiceStructuralNodes.append(
                                    childStructuralNode)
                            expandDefinition(view, childStructuralNode,
                                             breakdownNode,
                                             childDefinitionNode, depth + 1,
                                             axisDisposition, facts)  #recurse
                    # required when switching from abstract to roll up to determine abstractness
                    #if not structuralNode.subtreeRollUp and structuralNode.childStructuralNodes and definitionNode.tag.endswith("Node"):
                    #    structuralNode.subtreeRollUp = CHILDREN_BUT_NO_ROLLUP

            #if not hasattr(structuralNode, "indent"): # probably also for multiple open axes
            if processOpenDefinitionNode:
                if isinstance(definitionNode, ModelRelationshipDefinitionNode):
                    structuralNode.isLabeled = False
                    selfStructuralNodes = {} if definitionNode.axis.endswith(
                        '-or-self') else None
                    for rel in definitionNode.relationships(structuralNode):
                        if not isinstance(rel, list):
                            relChildStructuralNode = addRelationship(
                                breakdownNode, definitionNode, rel,
                                structuralNode, cartesianProductNestedArgs,
                                selfStructuralNodes)
                        else:
                            addRelationships(breakdownNode, definitionNode,
                                             rel, relChildStructuralNode,
                                             cartesianProductNestedArgs)
                    if axisDisposition == "z":
                        # if definitionNode is first structural node child remove it
                        if structuralNode.choiceStructuralNodes and structuralNode.choiceStructuralNodes[
                                0].definitionNode == definitionNode:
                            del structuralNode.choiceStructuralNodes[0]
                        # flatten hierarchy of nested structural nodes inot choice nodes (for single listbox)
                        def flattenChildNodesToChoices(childStructuralNodes,
                                                       indent):
                            while childStructuralNodes:
                                choiceStructuralNode = childStructuralNodes.pop(
                                    0)
                                choiceStructuralNode.indent = indent
                                structuralNode.choiceStructuralNodes.append(
                                    choiceStructuralNode)
                                flattenChildNodesToChoices(
                                    choiceStructuralNode.childStructuralNodes,
                                    indent + 1)

                        if structuralNode.childStructuralNodes:
                            flattenChildNodesToChoices(
                                structuralNode.childStructuralNodes, 0)
                    # set up by definitionNode.relationships
                    if isinstance(definitionNode,
                                  ModelConceptRelationshipDefinitionNode):
                        if (definitionNode._sourceQname != XbrlConst.qnXfiRoot
                                and definitionNode._sourceQname
                                not in view.modelXbrl.qnameConcepts):
                            view.modelXbrl.error(
                                "xbrlte:invalidConceptRelationshipSource",
                                _("Concept relationship rule node %(xlinkLabel)s source %(source)s does not refer to an existing concept."
                                  ),
                                modelObject=definitionNode,
                                xlinkLabel=definitionNode.xlinkLabel,
                                source=definitionNode._sourceQname)
                    elif isinstance(definitionNode,
                                    ModelDimensionRelationshipDefinitionNode):
                        dim = view.modelXbrl.qnameConcepts.get(
                            definitionNode._dimensionQname)
                        if dim is None or not dim.isExplicitDimension:
                            view.modelXbrl.error(
                                "xbrlte:invalidExplicitDimensionQName",
                                _("Dimension relationship rule node %(xlinkLabel)s dimension %(dimension)s does not refer to an existing explicit dimension."
                                  ),
                                modelObject=definitionNode,
                                xlinkLabel=definitionNode.xlinkLabel,
                                dimension=definitionNode._dimensionQname)
                        domMbr = view.modelXbrl.qnameConcepts.get(
                            definitionNode._sourceQname)
                        if domMbr is None or not domMbr.isDomainMember:
                            view.modelXbrl.error(
                                "xbrlte:invalidDimensionRelationshipSource",
                                _("Dimension relationship rule node %(xlinkLabel)s source %(source)s does not refer to an existing domain member."
                                  ),
                                modelObject=definitionNode,
                                xlinkLabel=definitionNode.xlinkLabel,
                                source=definitionNode._sourceQname)
                    if (definitionNode._axis
                            in ("child", "child-or-self", "parent",
                                "parent-or-self", "sibling", "sibling-or-self")
                            and (not isinstance(definitionNode._generations,
                                                _NUM_TYPES)
                                 or definitionNode._generations > 1)):
                        view.modelXbrl.error(
                            "xbrlte:relationshipNodeTooManyGenerations ",
                            _("Relationship rule node %(xlinkLabel)s formulaAxis %(axis)s implies a single generation tree walk but generations %(generations)s is greater than one."
                              ),
                            modelObject=definitionNode,
                            xlinkLabel=definitionNode.xlinkLabel,
                            axis=definitionNode._axis,
                            generations=definitionNode._generations)

                elif isinstance(definitionNode, ModelSelectionDefinitionNode):
                    structuralNode.setHasOpenNode()
                    structuralNode.isLabeled = False
                    isCartesianProductExpanded = True
                    varQn = definitionNode.variableQname
                    if varQn:
                        selections = sorted(structuralNode.evaluate(
                            definitionNode, definitionNode.evaluate) or [],
                                            key=lambda obj: sortkey(obj))
                        if isinstance(
                                selections,
                            (list, set, tuple)) and len(selections) > 1:
                            for selection in selections:  # nested choices from selection list
                                childStructuralNode = StructuralNode(
                                    structuralNode,
                                    breakdownNode,
                                    definitionNode,
                                    contextItemFact=selection)
                                childStructuralNode.variables[
                                    varQn] = selection
                                childStructuralNode.indent = 0
                                if axisDisposition == "z":
                                    structuralNode.choiceStructuralNodes.append(
                                        childStructuralNode)
                                    childStructuralNode.zSelection = True
                                else:
                                    structuralNode.childStructuredNodeList.append(
                                        childStructuralNode)
                                    expandDefinition(
                                        view,
                                        childStructuralNode,
                                        breakdownNode,
                                        definitionNode,
                                        depth,
                                        axisDisposition,
                                        facts,
                                        processOpenDefinitionNode=False
                                    )  #recurse
                                    cartesianProductExpander(
                                        childStructuralNode,
                                        *cartesianProductNestedArgs)
                        else:
                            structuralNode.variables[varQn] = selections
                elif isinstance(definitionNode, ModelFilterDefinitionNode):
                    structuralNode.setHasOpenNode()
                    structuralNode.isLabeled = False
                    isCartesianProductExpanded = True
                    structuralNode.abstract = True  # spanning ordinate acts as a subtitle
                    filteredFactsPartitions = structuralNode.evaluate(
                        definitionNode,
                        definitionNode.filteredFactsPartitions,
                        evalArgs=(facts, ))
                    if structuralNode._rendrCntx.formulaOptions.traceVariableFilterWinnowing:
                        view.modelXbrl.info(
                            "table:trace",
                            _("Filter node %(xlinkLabel)s facts partitions: %(factsPartitions)s"
                              ),
                            modelObject=definitionNode,
                            xlinkLabel=definitionNode.xlinkLabel,
                            factsPartitions=str(filteredFactsPartitions))

                    # ohly for fact entry (true if no parent open nodes or all are on entry prototype row)
                    if axisDisposition != "z":
                        childList = structuralNode.childStructuralNodes
                        if structuralNode.isEntryPrototype(default=True):
                            for i in range(
                                    getattr(
                                        view,
                                        "openBreakdownLines",
                                        # for file output, 1 entry row if no facts
                                        0 if filteredFactsPartitions else 1)):
                                view.aspectEntryObjectId += 1
                                filteredFactsPartitions.append([
                                    FactPrototype(
                                        view, {
                                            "aspectEntryObjectId":
                                            OPEN_ASPECT_ENTRY_SURROGATE +
                                            str(view.aspectEntryObjectId)
                                        })
                                ])
                                if structuralNode.isEntryPrototype(
                                        default=False):
                                    break  # only one node per cartesian product under outermost nested open entry row
                    else:
                        childList = structuralNode.choiceStructuralNodes
                    for factsPartition in filteredFactsPartitions:
                        childStructuralNode = StructuralNode(
                            structuralNode,
                            breakdownNode,
                            definitionNode,
                            contextItemFact=factsPartition[0])
                        childStructuralNode.indent = 0
                        childStructuralNode.depth -= 1  # for label width; parent is merged/invisible
                        childList.append(childStructuralNode)
                        checkLabelWidth(childStructuralNode,
                                        checkBoundFact=True)
                        #expandDefinition(view, childStructuralNode, breakdownNode, definitionNode, depth, axisDisposition, factsPartition, processOpenDefinitionNode=False) #recurse
                        cartesianProductNestedArgs[3] = factsPartition
                        # note: reduced set of facts should always be passed to subsequent open nodes
                        if subtreeRelationships:
                            for axisSubtreeRel in subtreeRelationships:
                                child2DefinitionNode = axisSubtreeRel.toModelObject
                                child2StructuralNode = StructuralNode(
                                    childStructuralNode, breakdownNode,
                                    child2DefinitionNode
                                )  # others are nested structuralNode
                                childStructuralNode.childStructuredNodeList.append(
                                    child2StructuralNode)
                                expandDefinition(view, child2StructuralNode,
                                                 breakdownNode,
                                                 child2DefinitionNode,
                                                 depth + ordDepth,
                                                 axisDisposition,
                                                 factsPartition)  #recurse
                                cartesianProductExpander(
                                    child2StructuralNode,
                                    *cartesianProductNestedArgs)
                        else:
                            cartesianProductExpander(
                                childStructuralNode,
                                *cartesianProductNestedArgs)
                    # sort by header (which is likely to be typed dim value, for example)
                    childList.sort(
                        key=lambda childStructuralNode: childStructuralNode.
                        header(lang=view.lang,
                               returnGenLabel=False,
                               returnMsgFormatString=False) or ''
                    )  # exception on trying to sort if header returns None

                    # TBD if there is no abstract 'sub header' for these subOrdCntxs, move them in place of parent structuralNode
                elif isinstance(definitionNode, ModelTupleDefinitionNode):
                    structuralNode.abstract = True  # spanning ordinate acts as a subtitle
                    matchingTupleFacts = structuralNode.evaluate(
                        definitionNode,
                        definitionNode.filteredFacts,
                        evalArgs=(facts, ))
                    for tupleFact in matchingTupleFacts:
                        childStructuralNode = StructuralNode(
                            structuralNode,
                            breakdownNode,
                            definitionNode,
                            contextItemFact=tupleFact)
                        childStructuralNode.indent = 0
                        structuralNode.childStructuredNodeList.append(
                            childStructuralNode)
                        expandDefinition(view, childStructuralNode,
                                         breakdownNode, definitionNode, depth,
                                         axisDisposition,
                                         [tupleFact])  #recurse
                    # sort by header (which is likely to be typed dim value, for example)
                    if (structuralNode.childStructuralNodes and any(
                            sOC.header(lang=view.lang)
                            for sOC in structuralNode.childStructuralNodes)):
                        structuralNode.childStructuralNodes.sort(
                            key=lambda childStructuralNode: childStructuralNode
                            .header(lang=view.lang) or '')
                elif isinstance(definitionNode, ModelRuleDefinitionNode):
                    for constraintSet in definitionNode.constraintSets.values(
                    ):
                        for aspect in constraintSet.aspectsCovered():
                            if not constraintSet.aspectValueDependsOnVars(
                                    aspect):
                                if aspect == Aspect.CONCEPT:
                                    conceptQname = definitionNode.aspectValue(
                                        view.rendrCntx, Aspect.CONCEPT)
                                    concept = view.modelXbrl.qnameConcepts.get(
                                        conceptQname)
                                    if concept is None or not concept.isItem or concept.isDimensionItem or concept.isHypercubeItem:
                                        view.modelXbrl.error(
                                            "xbrlte:invalidQNameAspectValue",
                                            _("Rule node %(xlinkLabel)s specifies concept %(concept)s does not refer to an existing primary item concept."
                                              ),
                                            modelObject=definitionNode,
                                            xlinkLabel=definitionNode.
                                            xlinkLabel,
                                            concept=conceptQname)
                                elif isinstance(aspect, QName):
                                    dim = view.modelXbrl.qnameConcepts.get(
                                        aspect)
                                    memQname = definitionNode.aspectValue(
                                        view.rendrCntx, aspect)
                                    mem = view.modelXbrl.qnameConcepts.get(
                                        memQname)
                                    if dim is None or not dim.isDimensionItem:
                                        view.modelXbrl.error(
                                            "xbrlte:invalidQNameAspectValue",
                                            _("Rule node %(xlinkLabel)s specifies dimension %(concept)s does not refer to an existing dimension concept."
                                              ),
                                            modelObject=definitionNode,
                                            xlinkLabel=definitionNode.
                                            xlinkLabel,
                                            concept=aspect)
                                    if isinstance(memQname, QName) and (
                                            mem is None
                                            or not mem.isDomainMember):
                                        view.modelXbrl.error(
                                            "xbrlte:invalidQNameAspectValue",
                                            _("Rule node %(xlinkLabel)s specifies domain member %(concept)s does not refer to an existing domain member concept."
                                              ),
                                            modelObject=definitionNode,
                                            xlinkLabel=definitionNode.
                                            xlinkLabel,
                                            concept=memQname)

                if axisDisposition == "z":
                    if structuralNode.choiceStructuralNodes:
                        choiceNodeIndex = view.zOrdinateChoices.get(
                            definitionNode, 0)
                        if isinstance(choiceNodeIndex,
                                      dict):  # aspect entry for open node
                            structuralNode.aspects = choiceNodeIndex
                            structuralNode.choiceNodeIndex = -1
                        elif choiceNodeIndex < len(
                                structuralNode.choiceStructuralNodes):
                            structuralNode.choiceNodeIndex = choiceNodeIndex
                        else:
                            structuralNode.choiceNodeIndex = 0
                    view.zmostOrdCntx = structuralNode

                if not isCartesianProductExpanded or (
                        axisDisposition == "z"
                        and structuralNode.choiceStructuralNodes is not None):
                    cartesianProductExpander(structuralNode,
                                             *cartesianProductNestedArgs)

                if not structuralNode.childStructuralNodes:  # childless root ordinate, make a child to iterate in producing table
                    subOrdContext = StructuralNode(structuralNode,
                                                   breakdownNode,
                                                   definitionNode)
        except ResolutionException as ex:
            if sys.version[0] >= '3':
                #import traceback
                #traceback.print_tb(ex.__traceback__)
                raise ex.with_traceback(
                    ex.__traceback__)  # provide original traceback information
            else:
                raise ex
        except Exception as ex:
            e = ResolutionException(
                "arelle:resolutionException",
                _("Exception in resolution of definition node %(node)s: %(error)s"
                  ),
                modelObject=definitionNode,
                node=definitionNode.qname,
                error=str(ex))
            if sys.version[0] >= '3':
                raise e.with_traceback(
                    ex.__traceback__)  # provide original traceback information
            else:
                raise e
Example #10
0
    def bodyCells(self, row, yParentStructuralNode, xStructuralNodes,
                  zAspectStructuralNodes, yChildrenFirst, tblELR):
        if yParentStructuralNode is not None:
            dimDefaults = self.modelXbrl.qnameDimensionDefaults
            for yStructuralNode in yParentStructuralNode.childStructuralNodes:
                if yChildrenFirst:
                    row = self.bodyCells(row, yStructuralNode,
                                         xStructuralNodes,
                                         zAspectStructuralNodes,
                                         yChildrenFirst, tblELR)
                if not (yStructuralNode.isAbstract or
                        (yStructuralNode.childStructuralNodes
                         and not isinstance(
                             yStructuralNode.definitionNode,
                             (ModelClosedDefinitionNode, ModelEuAxisCoord)))
                        ) and yStructuralNode.isLabeled:
                    yAspectStructuralNodes = defaultdict(set)
                    for aspect in aspectModels[self.aspectModel]:
                        if yStructuralNode.hasAspect(aspect):
                            if aspect == Aspect.DIMENSIONS:
                                for dim in (yStructuralNode.aspectValue(
                                        Aspect.DIMENSIONS) or emptyList):
                                    yAspectStructuralNodes[dim].add(
                                        yStructuralNode)
                            else:
                                yAspectStructuralNodes[aspect].add(
                                    yStructuralNode)
                    yTagSelectors = yStructuralNode.tagSelectors
                    # data for columns of rows
                    for _, xStructuralNode in enumerate(xStructuralNodes):
                        xAspectStructuralNodes = defaultdict(set)
                        for aspect in aspectModels[self.aspectModel]:
                            if xStructuralNode.hasAspect(aspect):
                                if aspect == Aspect.DIMENSIONS:
                                    for dim in (xStructuralNode.aspectValue(
                                            Aspect.DIMENSIONS) or emptyList):
                                        xAspectStructuralNodes[dim].add(
                                            xStructuralNode)
                                else:
                                    xAspectStructuralNodes[aspect].add(
                                        xStructuralNode)
                        cellTagSelectors = yTagSelectors | xStructuralNode.tagSelectors
                        cellAspectValues = {}
                        matchableAspects = set()
                        for aspect in _DICT_SET(
                                xAspectStructuralNodes.keys()) | _DICT_SET(
                                    yAspectStructuralNodes.keys()) | _DICT_SET(
                                        zAspectStructuralNodes.keys(
                                        )):  # @UndefinedVariable
                            aspectValue = xStructuralNode.inheritedAspectValue(
                                yStructuralNode, self, aspect,
                                cellTagSelectors, xAspectStructuralNodes,
                                yAspectStructuralNodes, zAspectStructuralNodes)
                            # value is None for a dimension whose value is to be not reported in this slice
                            if (isinstance(aspect, _INT)
                                    or  # not a dimension @UndefinedVariable
                                    dimDefaults.get(aspect) != aspectValue
                                    or  # explicit dim defaulted will equal the value
                                    aspectValue is not None
                                ):  # typed dim absent will be none
                                cellAspectValues[aspect] = aspectValue
                            matchableAspects.add(
                                aspectModelAspect.get(aspect, aspect)
                            )  #filterable aspect from rule aspect
                        cellDefaultedDims = _DICT_SET(dimDefaults) - _DICT_SET(
                            cellAspectValues.keys())  # @UndefinedVariable
                        priItemQname = cellAspectValues.get(Aspect.CONCEPT)

                        concept = self.modelXbrl.qnameConcepts.get(
                            priItemQname)
                        conceptNotAbstract = concept is None or not concept.isAbstract
                        fact = None
                        value = None
                        fp = FactPrototype(self, cellAspectValues)
                        if conceptNotAbstract:
                            # reduce set of matchable facts to those with pri item qname and have dimension aspects
                            facts = self.modelXbrl.factsByQname(
                                priItemQname, set()
                            ) if priItemQname else self.modelXbrl.factsInInstance
                            if self.hasTableFilters:
                                facts = self.modelTable.filterFacts(
                                    self.rendrCntx, facts)
                            for aspect in matchableAspects:  # trim down facts with explicit dimensions match or just present
                                if isinstance(aspect, QName):
                                    aspectValue = cellAspectValues.get(
                                        aspect, None)
                                    if isinstance(aspectValue,
                                                  ModelDimensionValue):
                                        if aspectValue.isExplicit:
                                            dimMemQname = aspectValue.memberQname  # match facts with this explicit value
                                        else:
                                            dimMemQname = None  # match facts that report this dimension
                                    elif isinstance(aspectValue, QName):
                                        dimMemQname = aspectValue  # match facts that have this explicit value
                                    elif aspectValue is None:  # match typed dims that don't report this value
                                        dimMemQname = DEFAULT
                                    else:
                                        dimMemQname = None  # match facts that report this dimension
                                    facts = facts & self.modelXbrl.factsByDimMemQname(
                                        aspect, dimMemQname)
                                    if len(facts) == 0:
                                        break
                            for fact in facts:
                                if (all(
                                        aspectMatches(self.rendrCntx, fact, fp,
                                                      aspect)
                                        for aspect in matchableAspects)
                                        and all(
                                            fact.context.dimMemberQname(
                                                dim, includeDefaults=True) in (
                                                    dimDefaults[dim], None)
                                            for dim in cellDefaultedDims)
                                        and len(fp.context.qnameDims) == len(
                                            fact.context.qnameDims)):
                                    if yStructuralNode.hasValueExpression(
                                            xStructuralNode):
                                        value = yStructuralNode.evalValueExpression(
                                            fact, xStructuralNode)
                                    else:
                                        value = fact.effectiveValue
                                    self.factWalkingAction.onFactEvent(
                                        fact, value, tblELR)
                                    break

                        fp.clear()  # dereference
                    row += 1
                if not yChildrenFirst:
                    row = self.bodyCells(row, yStructuralNode,
                                         xStructuralNodes,
                                         zAspectStructuralNodes,
                                         yChildrenFirst, tblELR)
        return row