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
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
def bodyCells(self, row, indent, yAxisParentObj, xFilters, zFilters, yChildrenFirst): for axisMbrRel in self.axisMbrRelSet.fromModelObject(yAxisParentObj): yAxisHdrObj = axisMbrRel.toModelObject if yChildrenFirst: row = self.bodyCells(row, indent + 20, yAxisHdrObj, xFilters, zFilters, yChildrenFirst) if yAxisHdrObj.abstract == "false": yAxisPriItemQname = self.inheritedPrimaryItemQname(yAxisHdrObj) yAxisExplicitDims = self.inheritedExplicitDims(yAxisHdrObj) # data for columns of row ignoreDimValidity = self.ignoreDimValidity.get() zFilter = zFilters[self.zFilterIndex] for i, colFilter in enumerate(xFilters): colPriItemQname = colFilter[0] # y axis pri item if not colPriItemQname: colPriItemQname = yAxisPriItemQname # y axis if not colPriItemQname: colPriItemQname = zFilter[0] # z axis fp = FactPrototype(self, colPriItemQname, yAxisExplicitDims | colFilter[1] | zFilter[1]) from arelle.ValidateXbrlDimensions import isFactDimensionallyValid value = None objectId = None justify = None for fact in self.modelXbrl.facts: if fact.qname == fp.qname and all( fact.context.dimMemberQname(dim, includeDefaults=True) == mem for dim, mem in fp.dims ): 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): gridCell( self.gridBody, self.dataFirstCol + i, row, value, justify=justify, width=12, 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, indent + 20, yAxisHdrObj, xFilters, zFilters, yChildrenFirst) return row
def bodyCells(self, row, indent, yAxisParentObj, xFilters, zFilters, yChildrenFirst): for axisMbrRel in self.axisMbrRelSet.fromModelObject(yAxisParentObj): yAxisHdrObj = axisMbrRel.toModelObject if yChildrenFirst: row = self.bodyCells(row, indent + 20, yAxisHdrObj, xFilters, zFilters, yChildrenFirst) if yAxisHdrObj.abstract == "false": yAxisPriItemQname = self.inheritedPrimaryItemQname(yAxisHdrObj) yAxisExplicitDims = self.inheritedExplicitDims(yAxisHdrObj) # data for columns of row ignoreDimValidity = self.ignoreDimValidity.get() zFilter = zFilters[self.zFilterIndex] for i, colFilter in enumerate(xFilters): colPriItemQname = colFilter[0] # y axis pri item if not colPriItemQname: colPriItemQname = yAxisPriItemQname # y axis if not colPriItemQname: colPriItemQname = zFilter[0] # z axis fp = FactPrototype(self, colPriItemQname, yAxisExplicitDims | colFilter[1] | zFilter[1]) from arelle.ValidateXbrlDimensions import isFactDimensionallyValid value = None objectId = None justify = None for fact in self.modelXbrl.facts: if (fact.qname == fp.qname and all(fact.context.dimMemberQname(dim,includeDefaults=True) == mem for dim, mem in fp.dims)): 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): gridCell(self.gridBody, self.dataFirstCol + i, row, value, justify=justify, width=12, 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, indent + 20, yAxisHdrObj, xFilters, zFilters, 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
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
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 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
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
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
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
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