def __init__(self, parentOrdinateContext, axisObject, zInheritance=None, contextItemFact=None):
     self.parentOrdinateContext = parentOrdinateContext
     self._axisObject = axisObject
     self._rendrCntx = getattr(axisObject.modelXbrl, "rendrCntx", None) # None for EU 2010 table linkbases
     self.variables = {}
     self.aspects = {}
     self.subOrdinateContexts = []
     self.choiceOrdinateContexts = []
     self.zInheritance = zInheritance
     if contextItemFact is not None:
         self.contextItemBinding = VariableBinding(self._rendrCntx,
                                                   boundFact=contextItemFact)
     else:
         self.contextItemBinding = None
 def __init__(self, parentStructuralNode, definitionNode, zInheritance=None, contextItemFact=None):
     self.parentStructuralNode = parentStructuralNode
     self._definitionNode = definitionNode
     self._rendrCntx = getattr(definitionNode.modelXbrl, "rendrCntx", None) # None for EU 2010 table linkbases
     self.variables = {}
     self.aspects = {}
     self.childStructuralNodes = []
     self.rollUpStructuralNode = None
     self.choiceStructuralNodes = []
     self.zInheritance = zInheritance
     if contextItemFact is not None:
         self.contextItemBinding = VariableBinding(self._rendrCntx,
                                                   boundFact=contextItemFact)
     else:
         self.contextItemBinding = None
     self.subtreeRollUp = ROLLUP_NOT_ANALYZED
     self.depth = parentStructuralNode.depth + 1 if parentStructuralNode else 0
class StructuralNode:
    def __init__(self, parentStructuralNode, definitionNode, zInheritance=None, contextItemFact=None):
        self.parentStructuralNode = parentStructuralNode
        self._definitionNode = definitionNode
        self._rendrCntx = getattr(definitionNode.modelXbrl, "rendrCntx", None) # None for EU 2010 table linkbases
        self.variables = {}
        self.aspects = {}
        self.childStructuralNodes = []
        self.rollUpStructuralNode = None
        self.choiceStructuralNodes = []
        self.zInheritance = zInheritance
        if contextItemFact is not None:
            self.contextItemBinding = VariableBinding(self._rendrCntx,
                                                      boundFact=contextItemFact)
        else:
            self.contextItemBinding = None
        self.subtreeRollUp = ROLLUP_NOT_ANALYZED
        self.depth = parentStructuralNode.depth + 1 if parentStructuralNode else 0
        
    @property
    def modelXbrl(self):
        return self._definitionNode.modelXbrl
        
    @property
    def isAbstract(self):
        if self.subtreeRollUp:
            return self.subtreeRollUp == CHILDREN_BUT_NO_ROLLUP
        try:
            try:
                return self.abstract # ordinate may have an abstract attribute
            except AttributeError: # if none use axis object
                return self.definitionNode.isAbstract
        except AttributeError: # axis may never be abstract
            return False
        
    @property
    def isRollUp(self):
        return self.definitionNode.isRollUp
        
    @property
    def cardinalityAndDepth(self):
        return self.definitionNode.cardinalityAndDepth(self)
    
    @property
    def definitionNode(self):
        if self.choiceStructuralNodes:
            return self.choiceStructuralNodes[getattr(self,"choiceNodeIndex",0)]._definitionNode
        return self._definitionNode
    
    def aspectsCovered(self):
        return _DICT_SET(self.aspects.keys()) | self.definitionNode.aspectsCovered()
      
    def hasAspect(self, aspect, inherit=True):
        return (aspect in self.aspects or 
                self.definitionNode.hasAspect(self, aspect) or 
                (inherit and
                 self.parentStructuralNode is not None and 
                 self.parentStructuralNode.hasAspect(aspect, inherit)))
    
    def aspectValue(self, aspect, inherit=True, dims=None):
        xc = self._rendrCntx
        if self.choiceStructuralNodes:  # use aspects from choice structural node
            aspects = self.choiceStructuralNodes[self.choiceNodeIndex].aspects
        else:
            aspects = self.aspects
        if aspect == Aspect.DIMENSIONS:
            if dims is None: dims = set()
            if inherit and self.parentStructuralNode is not None:
                dims |= self.parentStructuralNode.aspectValue(aspect, dims=dims)
            if aspect in aspects:
                dims |= aspects[aspect]
            elif self.definitionNode.hasAspect(self, aspect):
                dims |= set(self.definitionNode.aspectValue(xc, aspect) or {})
            if self.definitionNode.hasAspect(self, Aspect.OMIT_DIMENSIONS):
                dims -= set(self.definitionNode.aspectValue(xc, Aspect.OMIT_DIMENSIONS))
            return dims
        if aspect in aspects:
            return aspects[aspect]
        elif self.definitionNode.hasAspect(self, aspect):
            if isinstance(self._definitionNode, ModelSelectionDefinitionNode):
                # result is in the indicated variable of ordCntx
                return self.variables.get(self._definitionNode.variableQname)
            elif isinstance(self._definitionNode, ModelFilterDefinitionNode):
                if self.contextItemBinding:
                    return self.contextItemBinding.aspectValue(aspect)
            elif isinstance(self._definitionNode, ModelTupleDefinitionNode):
                if aspect == Aspect.LOCATION and self.contextItemBinding:
                    return self.contextItemBinding.yieldedFact
                # non-location tuple aspects don't leak into cell bindings
            else:
                return self.definitionNode.aspectValue(xc, aspect)
        elif inherit and self.parentStructuralNode is not None:
            return self.parentStructuralNode.aspectValue(aspect)
        return None

    '''
    @property   
    def primaryItemQname(self):  # for compatibility with viewRelationsihps
        if Aspect.CONCEPT in self.aspects:
            return self.aspects[Aspect.CONCEPT]
        return self.definitionNode.primaryItemQname
        
    @property
    def explicitDims(self):
        return self.definitionNode.explicitDims
    '''
        
    def objectId(self, refId=""):
        return self._definitionNode.objectId(refId)
        
    def header(self, role=None, lang=None, evaluate=True, returnGenLabel=True, returnMsgFormatString=False):
        # if ord is a nested selectionAxis selection, use selection-message or text contents instead of axis headers
        isZSelection = isinstance(self._definitionNode, ModelSelectionDefinitionNode) and hasattr(self, "zSelection")
        if role is None:
            # check for message before checking for genLabel
            msgsRelationshipSet = self._definitionNode.modelXbrl.relationshipSet(
                    (XbrlConst.tableDefinitionNodeSelectionMessage, XbrlConst.tableAxisSelectionMessage2011) 
                    if isZSelection else 
                    (XbrlConst.tableDefinitionNodeMessage, XbrlConst.tableAxisMessage2011))
            if msgsRelationshipSet:
                msg = msgsRelationshipSet.label(self._definitionNode, XbrlConst.standardMessage, lang, returnText=False)
                if msg is not None:
                    if evaluate:
                        if returnMsgFormatString:
                            return msg.formatString # not possible to evaluate (during resolution)
                        else:
                            return self.evaluate(msg, msg.evaluate)
                    else:
                        return XmlUtil.text(msg)
        if isZSelection: # no message, return text of selection
            return self.variables.get(self._definitionNode.variableQname, "selection")
        if returnGenLabel:
            label = self._definitionNode.genLabel(role=role, lang=lang)
            if label:
                return label
        # if there's a child roll up, check for it
        if self.rollUpStructuralNode is not None:  # check the rolling-up child too
            return self.rollUpStructuralNode.header(role, lang, evaluate, returnGenLabel, returnMsgFormatString)
        # if aspect is a concept of dimension, return its standard label
        concept = None
        for aspect in self.aspectsCovered():
            if isinstance(aspect, QName) or aspect == Aspect.CONCEPT: # dimension or concept
                aspectValue = self.aspectValue(aspect)
                if isinstance(aspectValue, QName):
                    concept = self.modelXbrl.qnameConcepts[aspectValue]
                    break
                elif isinstance(aspectValue, ModelDimensionValue):
                    if aspectValue.isExplicit:
                        concept = aspectValue.member
                    elif aspectValue.isTyped:
                        return XmlUtil.innerTextList(aspectValue.typedMember)
        if concept is not None:
            label = concept.label(lang=lang)
            if label:
                return label
        # if there is a role, check if it's available on a parent node
        if role and self.parentStructuralNode is not None:
            return self.parentStructuralNode.header(role, lang, evaluate, returnGenLabel, returnMsgFormatString)
        return None
    
    def evaluate(self, evalObject, evalMethod, otherOrdinate=None, evalArgs=()):
        xc = self._rendrCntx
        if self.contextItemBinding and not isinstance(xc.contextItem, ModelFact):
            previousContextItem = xc.contextItem # xbrli.xbrl
            xc.contextItem = self.contextItemBinding.yieldedFact
        else:
            previousContextItem = None
        if self.choiceStructuralNodes and hasattr(self,"choiceNodeIndex"):
            variables = self.choiceStructuralNodes[self.choiceNodeIndex].variables
        else:
            variables = self.variables
        removeVarQnames = []
        for qn, value in variables.items():
            if qn not in xc.inScopeVars:
                removeVarQnames.append(qn)
                xc.inScopeVars[qn] = value
        if self.parentStructuralNode is not None:
            result = self.parentStructuralNode.evaluate(evalObject, evalMethod, otherOrdinate, evalArgs)
        elif otherOrdinate is not None:
            # recurse to other ordinate (which will recurse to z axis)
            result = otherOrdinate.evaluate(evalObject, evalMethod, None, evalArgs)
        elif self.zInheritance is not None:
            result = self.zInheritance.evaluate(evalObject, evalMethod, None, evalArgs)
        else:
            try:
                result = evalMethod(xc, *evalArgs)
            except XPathContext.XPathException as err:
                xc.modelXbrl.error(err.code,
                         _("%(element)s set %(xlinkLabel)s \nException: %(error)s"), 
                         modelObject=evalObject, element=evalObject.localName, 
                         xlinkLabel=evalObject.xlinkLabel, error=err.message)
                result = ''
        for qn in removeVarQnames:
            xc.inScopeVars.pop(qn)
        if previousContextItem is not None:
            xc.contextItem = previousContextItem # xbrli.xbrl
        return result
    
    def hasValueExpression(self, otherOrdinate=None):
        return (self.definitionNode.hasValueExpression or 
                (otherOrdinate is not None and otherOrdinate.definitionNode.hasValueExpression))
    
    def evalValueExpression(self, fact, otherOrdinate=None):
        for ordinate in (self, otherOrdinate):
            if ordinate is not None and ordinate.definitionNode.hasValueExpression:
                return self.evaluate(self.definitionNode, ordinate.definitionNode.evalValueExpression, otherOrdinate=otherOrdinate, evalArgs=(fact,))
        return None
            
    def __repr__(self):
        return ("structuralNode[{0}]{1})".format(self.objectId(),self.definitionNode))
class OrdinateContext:
    def __init__(self, parentOrdinateContext, axisObject, zInheritance=None, contextItemFact=None):
        self.parentOrdinateContext = parentOrdinateContext
        self._axisObject = axisObject
        self._rendrCntx = getattr(axisObject.modelXbrl, "rendrCntx", None) # None for EU 2010 table linkbases
        self.variables = {}
        self.aspects = {}
        self.subOrdinateContexts = []
        self.choiceOrdinateContexts = []
        self.zInheritance = zInheritance
        if contextItemFact is not None:
            self.contextItemBinding = VariableBinding(self._rendrCntx,
                                                      boundFact=contextItemFact)
        else:
            self.contextItemBinding = None
        
    @property
    def isAbstract(self):
        try:
            try:
                return self.abstract # ordinate may have an abstract attribute
            except AttributeError: # if none use axis object
                return self.axisObject.abstract == "true"
        except AttributeError: # axis may never be abstract
            return False
        
    @property
    def cardinalityAndDepth(self):
        return self.axisObject.cardinalityAndDepth(self)
    
    @property
    def axisObject(self):
        if self.choiceOrdinateContexts:
            return self.choiceOrdinateContexts[getattr(self,"choiceOrdinateIndex",0)]._axisObject
        return self._axisObject
    
    def aspectsCovered(self):
        return _DICT_SET(self.aspects.keys()) | self.axisObject.aspectsCovered()
      
    def hasAspect(self, aspect, inherit=True):
        return (aspect in self.aspects or 
                self.axisObject.hasAspect(aspect) or 
                (inherit and
                 self.parentOrdinateContext is not None and 
                 self.parentOrdinateContext.hasAspect(aspect)))
    
    def aspectValue(self, aspect, inherit=True, dims=None):
        if aspect == Aspect.DIMENSIONS:
            if dims is None: dims = set()
            if inherit and self.parentOrdinateContext is not None:
                dims |= self.parentOrdinateContext.aspectValue(aspect, dims=dims)
            if aspect in self.aspects:
                dims |= self.aspects[aspect]
            elif self.axisObject.hasAspect(aspect):
                dims |= set(self.axisObject.aspectValue(self._rendrCntx, aspect) or {})
            if self.axisObject.hasAspect(Aspect.OMIT_DIMENSIONS):
                dims -= set(self.axisObject.aspectValue(self._rendrCntx, Aspect.OMIT_DIMENSIONS))
            return dims
        if aspect in self.aspects:
            return self.aspects[aspect]
        elif self.axisObject.hasAspect(aspect):
            if isinstance(self._axisObject, ModelSelectionAxis):
                # result is in the indicated variable of ordCntx
                return self.variables.get(self._axisObject.variableQname)
            elif isinstance(self._axisObject, ModelFilterAxis):
                if self.contextItemBinding:
                    return self.contextItemBinding.aspectValue(aspect)
            elif isinstance(self._axisObject, ModelTupleAxis):
                if aspect == Aspect.LOCATION and self.contextItemBinding:
                    return self.contextItemBinding.yieldedFact
                # non-location tuple aspects don't leak into cell bindings
            else:
                return self.axisObject.aspectValue(self._rendrCntx, aspect)
        elif inherit and self.parentOrdinateContext is not None:
            return self.parentOrdinateContext.aspectValue(aspect)
        return None

    '''
    @property   
    def primaryItemQname(self):  # for compatibility with viewRelationsihps
        if Aspect.CONCEPT in self.aspects:
            return self.aspects[Aspect.CONCEPT]
        return self.axisObject.primaryItemQname
        
    @property
    def explicitDims(self):
        return self.axisObject.explicitDims
    '''
        
    def objectId(self, refId=""):
        return self._axisObject.objectId(refId)
        
    def header(self, role=None, lang=None, evaluate=True, returnGenLabel=True):
        # if ord is a nested selectionAxis selection, use selection-message or text contents instead of axis headers
        isZSelection = isinstance(self._axisObject, ModelSelectionAxis) and hasattr(self, "zSelection")
        if role is None:
            # check for message before checking for genLabel
            msgsRelationshipSet = self._axisObject.modelXbrl.relationshipSet(
                    XbrlConst.tableAxisSelectionMessage if isZSelection else XbrlConst.tableAxisMessage)
            if msgsRelationshipSet:
                msg = msgsRelationshipSet.label(self._axisObject, XbrlConst.standardMessage, lang, returnText=False)
                if msg is not None:
                    if evaluate:
                        return self.evaluate(msg, msg.evaluate)
                    else:
                        return XmlUtil.text(msg)
        if isZSelection: # no message, return text of selection
            return self.variables.get(self._axisObject.variableQname, "selection")
        if returnGenLabel:
            return self._axisObject.genLabel(role=role, lang=lang)
        return None
    
    def evaluate(self, evalObject, evalMethod, otherOrdinate=None, evalArgs=()):
        xc = self._rendrCntx
        if self.contextItemBinding and not isinstance(xc.contextItem, ModelFact):
            previousContextItem = xc.contextItem # xbrli.xbrl
            xc.contextItem = self.contextItemBinding.yieldedFact
        else:
            previousContextItem = None
        if self.choiceOrdinateContexts and hasattr(self,"choiceOrdinateIndex"):
            variables = self.choiceOrdinateContexts[self.choiceOrdinateIndex].variables
        else:
            variables = self.variables
        removeVarQnames = []
        for qn, value in variables.items():
            if qn not in xc.inScopeVars:
                removeVarQnames.append(qn)
                xc.inScopeVars[qn] = value
        if self.parentOrdinateContext is not None:
            result = self.parentOrdinateContext.evaluate(evalObject, evalMethod, otherOrdinate, evalArgs)
        elif otherOrdinate is not None:
            # recurse to other ordinate (which will recurse to z axis)
            result = otherOrdinate.evaluate(evalObject, evalMethod, None, evalArgs)
        elif self.zInheritance is not None:
            result = self.zInheritance.evaluate(evalObject, evalMethod, None, evalArgs)
        else:
            try:
                result = evalMethod(xc, *evalArgs)
            except XPathContext.XPathException as err:
                xc.modelXbrl.error(err.code,
                         _("%(element)s set %(xlinkLabel)s \nException: %(error)s"), 
                         modelObject=evalObject, element=evalObject.localName, 
                         xlinkLabel=evalObject.xlinkLabel, error=err.message)
                result = ''
        for qn in removeVarQnames:
            xc.inScopeVars.pop(qn)
        if previousContextItem is not None:
            xc.contextItem = previousContextItem # xbrli.xbrl
        return result
    
    def hasValueExpression(self, otherOrdinate=None):
        return (self.axisObject.hasValueExpression or 
                (otherOrdinate is not None and otherOrdinate.axisObject.hasValueExpression))
    
    def evalValueExpression(self, fact, otherOrdinate=None):
        for ordinate in (self, otherOrdinate):
            if ordinate is not None and ordinate.axisObject.hasValueExpression:
                return self.evaluate(self.axisObject, ordinate.axisObject.evalValueExpression, otherOrdinate=otherOrdinate, evalArgs=(fact,))
        return None
            
    def __repr__(self):
        return ("ordinateContext[{0}]{1})".format(self.objectId(),self.axisObject))