Converts a node to an XPath query

@param VariableSet $variableSet
@param FactVariableBinding $factVariableBinding
@return string
770975
public function toQuery( $variableSet, $factVariableBinding )
	{
		$clause = "";
		if ( $this->qname )
		{
			$clause = "fn:QName('{$this->qname['namespace']}','{$this->qname['originalPrefix']}:{$this->qname['name']}')";
		}
		else if ( $this->qnameExpression )
		{
			$clause = $this->qnameExpression;
		}
		else
		{
			return null;
		}

		return "(xfi:is-numeric(fn:node-name(.)) and count(xfi:unit-numerator(xfi:unit(.))) eq 1 and count(xfi:unit-denominator(xfi:unit(.))) eq 0 and xfi:measure-name(xfi:unit-numerator(xfi:unit(.))[1]) eq $clause)";
	}
276727
public function evaluateResult()
	{
		// Check the variable set is not all fallback values
		$factsFallback = $this->factVariableBindings && ! count( array_filter( $this->factVariableBindings,
			function( /** @var VariableBinding $variableBinding */ $variableBinding )
			{
				return ! $variableBinding->isFallback;
			} )
		);

		// $generalsFallback =  $this->generalVariableBindings && ! count( array_filter( $this->generalVariableBindings,
		// 	function( /** @var VariableBinding $variableBinding */ $variableBinding )
		// 	{
		// 		return ! $variableBinding->isFallback;
		// 	} )
		// );

		if ( $factsFallback /* && $generalsFallback */ )
		{
			return false;

			$msg = "All facts have fallback values";
			\XBRL_Log::getInstance()->formula_validation( "Variable set evaluation", $msg, array(
				'variable set' => get_called_class()
			) );

			throw new \Exception( $msg );
		}

		// Check preconditions
		if ( ! $this->preconditions )
		{
			return true;
		}

		foreach ( $this->preconditions as $precondition )
		{
			try
			{
				$vars = $this->getBindingsAsVars();
				$result = $this->evaluateXPathExpression( $this, $precondition->testXPathExpression, $vars );
				// The pre-condition result should be true or false and only true will allow the evaluation to be counted
				if ( ! $result instanceof CoreFuncs::$True )
				{
					if ( ! $result instanceof CoreFuncs::$False )
					{
						throw XPath2Exception::withErrorCodeAndParam( "FORG0006", "The precondition with label '{0}' did not return a boolean result", $precondition->label );
					}

					return false;
				}
			}
			catch( XPath2Exception $ex )
			{
				throw $ex;
			}
			catch( \Exception $ex )
			{
				throw $ex;
			}
		}

		return true;
	}
864267
public function Filter( $facts, $variableSet )
	{
		// Look for the variable
		$vars = $variableSet->getBindingsAsVars();
		$clark = str_replace( "{}", "", "{{$this->variable['namespace']}}{$this->variable['name']}" );
		if ( ! isset( $vars[ $clark ] ) )
		{
			// Should probably throw some kind of error here
			throw XPath2Exception::withErrorCodeAndParam( "XPST0008", Resources::XPST0008, $clark );
		}

		/**
		 * @var \DOMNode[] $candidates
		 */
		$candidates = array();
		$var = $vars[ $clark ];
		if ( $var instanceof XPath2NodeIterator )
		{
			$candidates = array_map( function( $node ) { return $node->getUnderlyingObject(); }, $var->ToList() );
		}
		else
		{
			$candidates[] = $var->getUnderlyingObject();
		}

		$dom = dom_import_simplexml( $variableSet->xbrlInstance->getInstanceXml() );
		$doc = $dom->ownerDocument;
		$xpath = new \DOMXPath( $doc );

		$matched = array();
		$notMatched = array();

		foreach ( $facts as $fact )
		{
			$node = $fact->getUnderlyingObject();

			/**
			 * @var \DOMNode[] $candidates
			 */
			$locations = $xpath->query( $this->location, $node );

			// See if any $candidates and any $locations overlap
			foreach ( $candidates as /** @var \DOMElement $candidate */ $candidate )
			{
				foreach ( $locations as /** @var \DOMElement $location */ $location )
				{
					if ( $candidate->isSameNode( $location ) )
					{
						$matched[] = $fact->CloneInstance();
						continue 3;
					}
				}
			}

			$notMatched[] = $fact->CloneInstance();
		}

		return DocumentOrderNodeIterator::fromItemset( $this->complement ? $notMatched : $matched );

		return $facts;
	}
712884
public function getValue( $variableSet, $evaluationResult, $log )
	{
		$sourceFact = $this->getSourceFact( $variableSet, $evaluationResult, $log );
		if ( ! $sourceFact )
		{
			$log->formula_validation( "Concept aspect rule", "No valid concept can be located",
				array(
					'source' => $this->qname
									? (string)(new QName( $this->qname['originalPrefix'], $this->qname['namespace'], $this->qname['name']) )
									: $this->qnameExpression,
					'error' => 'xbrlfe:missingConceptRule'
				)
			);
			return null;
		}

		return $sourceFact;
	}
1285917
public function getValue( $variableSet, $evaluationResult, $log )
	{
		// This is an error
		if ( ! isset( $variableSet->context ) ) return array();

		// Get context for this rule's source
		$sourceContext = $variableSet->getComponentForPath( $this->source, $variableSet->explicitDimensionsComponentPath, 'explicitMember', $evaluationResult, $this->aspectDimension, $log, $contextRef );
		$sourceContext = Dimension::contextToIndex( $sourceContext, true, $variableSet, $this->aspectDimension );

		// Get original context
		$context = $variableSet->context;

		if ( ! $variableSet->xbrlInstance->getNamespaceForPrefix( $this->dimension['originalPrefix'] ) )
		{
			$this->dimension['originalPrefix'] = $variableSet->xbrlInstance->getPrefixForNamespace( $this->dimension['namespace'] );
		}
		$dimensionQName = "{$this->dimension['originalPrefix']}:{$this->dimension['name']}";

		if ( $this->omit )
		{
			// Omit always applies to the default context
			unset( $context[ $dimensionQName ] );
		}
		else if ( $this->member )
		{
			// If a member is defined then the dimension/member is being added or updated
			if ( isset( $this->member['qname'] ) )
			{
				// Make sure the prefix is compatible with the instance document
				$qname = qname( $this->member['qname'], $variableSet->nsMgr->getNamespaces() );
				if ( ! $variableSet->xbrlInstance->getNamespaceForPrefix( $qname->prefix ) )
				{
					$qname->prefix = $variableSet->xbrlInstance->getPrefixForNamespace( $qname->namespaceURI );
				}
				$name = "{$qname->prefix}:{$qname->localName}";
				$context[ $dimensionQName ] = array( $name => $name );
			}
			else if ( $this->member['qnameExpression'] )
			{
				$vars = $evaluationResult['vars'];
				$result = $this->evaluateXPath( $variableSet, "{$this->member['qnameExpression']} cast as xs:string", $vars );

				$qname = qname( $result->getValue(), $variableSet->nsMgr->getNamespaces() );
				if ( ! $variableSet->xbrlInstance->getNamespaceForPrefix( $qname->prefix ) )
				{
					$qname->prefix = $variableSet->xbrlInstance->getPrefixForNamespace( $qname->namespaceURI );
				}
				$name = "{$qname->prefix}:{$qname->localName}";

				$context[ $dimensionQName ] = array( $name => $name );
			}
		}
		else if ( isset( $sourceContext[ $dimensionQName ] ) )
		{
			// Add any members from the source
			$context[ $dimensionQName ] = $sourceContext[ $dimensionQName ];
		}
		else
		{
			$log->formula_validation( "Explicit dimension aspect rule", "A dimension is being added but there are no members",
				array(
					'dimension' => $dimensionQName,
					'error' => 'xbrlfe:missingSAVForExplicitDimensionRule'
				)
			);
		}

		return $context;
	}
474120
public static function getDimensionsInContextRef( $variableSet, $contextRef )
	{
		if ( ! $contextRef ) return array();
		$context = $variableSet->xbrlInstance->getContext( $contextRef );
		if ( ! $context ) return array();
		return FactValues::getDimensionsInContext( $variableSet, $context );
	}
711012
public function Filter( $facts, $variableSet )
	{
		// If the filter is being used in a boolean filter or there is a qname expresssion then return the input facts
		if ( $this->inBoolean || $this->qnameExpressions ) return $facts;

		if ( ! $this->qnames ) return $facts;

		$matched = array();
		$notMatched = array();
		foreach ( $facts as /** @var XPathNavigator $fact */ $fact )
		{
			$clark = "{{$fact->getNamespaceURI()}}{$fact->getLocalName()}";

			if ( in_array( $clark, $this->qnames ) )
			{
				$matched[] = $fact->CloneInstance();
			}
			else
			{
				$notMatched[] = $fact->CloneInstance();
			}
		}

		return DocumentOrderNodeIterator::fromItemset( $this->complement ? $notMatched : $matched );
	}
101398
public function toQuery( $variableSet, $factVariableBinding )
	{
		// return "(true())";

		$clauses = array();

		$dimensionClause = "";
		if ( $this->dimension )
		{
			// $qname = qname( $this->dimension );
			$dimensionClause = "fn:QName('{$this->dimension['namespace']}','{$this->dimension['name']}')";
		}
		else if ( $this->dimensionExpression )
		{
			$dimensionClause = $this->dimensionExpression;
		}
		else
		{
			return "false()";
		}

		if ( $this->test )
		{
			return "( xfi:fact-has-typed-dimension(.,$dimensionClause) and xfi:fact-typed-dimension-value(.,$dimensionClause)[{$this->test}] )";
		}
		else
		{
			return "xfi:fact-has-typed-dimension(.,$dimensionClause)";
		}
	}
376804
public static function RAW_setGetVar($varname, $varvalue, $currentURL = null)
    {
        $url = self::setGetVar($varname, $varvalue, $currentURL);
        return Convert::xml2raw($url);
    }
400439
public function Filter( $facts, $variableSet )
	{
		// Look for the variable
		$vars = $variableSet->getBindingsAsVars();
		$clark = str_replace( "{}", "", "{{$this->variable['namespace']}}{$this->variable['name']}" );
		if ( ! isset( $vars[ $clark ] ) )
		{
			// Should probably throw some kind of error here
			throw XPath2Exception::withErrorCodeAndParam( "XPST0008", Resources::XPST0008, $clark );
		}

		/**
		 * @var \DOMNode[] $candidates
		 */
		$candidate = null;
		$var = $vars[ $clark ];
		if ( $var instanceof XPath2NodeIterator )
		{
			$node = reset( $var->ToList() );
			if ( is_null( $node ) )
			{
				throw XPath2Exception::withErrorCodeAndParam( "XPST0008", Resources::XPST0008, $clark );
			}

			$candidate = $node->getUnderlyingObject();
		}
		else
		{
			$candidate = $var->getUnderlyingObject();
		}

		$matched = array();
		$notMatched = array();

		$candidateParent = $candidate->parentNode;

		// The fact can be an
		foreach ( $facts as $fact )
		{
			$node = $fact->getUnderlyingObject();
			$factParent = $node->parentNode;

			if ( $candidateParent->isSameNode( $factParent ) )
			{
				$matched[] = $fact->CloneInstance();
			}
			else
			{
				$notMatched[] = $fact->CloneInstance();
			}
		}

		return DocumentOrderNodeIterator::fromItemset( $this->complement ? $notMatched : $matched );

		return $facts;
	}
1243701
public static function Evaluate( $variableSet, $orderedVariableQNames, $notBindings, $uncoveredAspectFacts = null )
	{
		return ( new Evaluation( $variableSet, $orderedVariableQNames, $notBindings ) )->processVariables( $uncoveredAspectFacts );
	}
1204220
private function evaluate( $variableSet )
	{
		if ( ! $this->canEvaluate ) return;
		if ( isset( $variableSet->evaluated ) ) return true;

		// Process the variables in hierarchy order
		// $variableSet->parameters =& $this->parameterQnames;
		$variableSet->nsMgr = $this->nsMgr;
		$variableSet->xbrlInstance = $this->instances[ $this->instanceQName->clarkNotation() ];
		if ( $variableSet->evaluate() )
		{
			// If the variable set is a formula then add a facts container
			if ( $variableSet instanceof Formula )
			{
				if ( is_null( $this->formulaFactsContainer ) ) $this->formulaFactsContainer = new GeneratedFacts();
				$variableSet->factsContainer = $this->formulaFactsContainer;
			}

			$variableSet->ProcessEvaluationResult( $this->log );

			// If the variable set is a formula recover the facts container
			if ( $variableSet instanceof Formula )
			{
				// This is probably redundant because the container instance will be passed to the variable set by reference
				$this->formulaFactsContainer = $variableSet->factsContainer;
			}
		}

		$variableSet->evaluated = true;

		return true;
	}
1134516
public function validate( $variableSet, $nsMgr )
	{
		$testExpression = function( $expressionName, $expression )
		{
			$xpath2Expression = null;

			try
			{
				$xpath2Expression = XPath2Expression::Compile( $expression, $nsMgr );
				if ( parent::checkForCoverXFIFunctionUse( $this->qnameExpression, $xpath2Expression ) )
				{
					return false;
				}
			}
			catch ( Exception $ex )
			{
				\XBRL_Log::getInstance()->formula_validation( "Concept relation filter", "Failed to compile qname expression",
					array(
						'expression name' => $expressionName,
						'qname expression' => $expression,
						'error' => $ex instanceof XPath2Exception ? $ex->ErrorCode : get_class( $ex ),
						'reason' => $ex->getMessage()
					)
				);

				return false;
			}

			return $xpath2Expression;
		};

		foreach ( $this->expressionsList as $expressionName => $details )
		{
			if ( ! $details['expression'] ) continue;
			$xpath2Expression = $testExpression( $expressionName, $details['expression'] );
			if ( ! $xpath2Expression ) continue;
			$this->${$details['expression']} = $xpath2Expression;
		}

		return true;
	}
346962
def xpathVariableLookupNS(self, name, ns_uri):
        
        ret = libxml2mod.xmlXPathVariableLookupNS(self._o, name, ns_uri)
        if ret is None:raise xpathError('xmlXPathVariableLookupNS() failed')
        return xpathObjectRet(ret)
13763
@Nullable
    public final Object extraBinding(int variableId) {
        if (extraBindings == null) {
            return null;
        }
        return extraBindings.get(variableId);
    }
272217
public function validate( $variableSet, $nsMgr )
	{
		if ( isset( $this->test ) && ! empty( $this->test ) )
		{
			try
			{
				$expression = XPath2Expression::Compile( $this->test, $nsMgr );
				$this->testXPath2Expression = $expression;
			}
			catch ( Exception $ex )
			{
				\XBRL_Log::getInstance()->valueassertion_validation( "Value assertion", "Failed to compile test expression",
					array(
						'test expression' => $this->test,
						'error' => $ex instanceof XPath2Exception ? $ex->ErrorCode : get_class( $ex ),
						'reason' => $ex->getMessage()
					)
				);

				return false;
			}

		}

		return true;
	}
1298705
private function validatePreconditions( $taxonomy, $variableSet )
	{
		$preconditionArcs = $taxonomy->getGenericArc( XBRL_Constants::$arcRoleVariableSetPrecondition, $variableSet->extendedLinkRoleUri, $variableSet->label, $variableSet->path, null, $variableSet->linkbase );
		if ( $preconditionArcs )
		{
			$element = "precondition";
			$preconditionClassName = '\\XBRL\\Formulas\\Resources\\' .
				Formulas::$formulaElements[ $element ]['part'] .
				( isset( Formulas::$formulaElements[ $element ]['className'] )
					? Formulas::$formulaElements[ $element ]['className']
					: ucfirst( $element )
				);

			$preconditionResources = array();
			// BMS 2018-06-29 Modified this loop to put the arcs on the outside so it can take advantage of the indexes on the resources collection
			// $taxonomy->getGenericResource( 'variable', $element, function( $roleUri, $linkbase, $variableSetName, $index, $resource ) use( $preconditionArcs, &$preconditionResources )
			// {
			// 	foreach ( $preconditionArcs as $preconditionArc )
			// 	{
			// 		if ( $roleUri == $preconditionArc['toRoleUri'] )
			// 		if ( $variableSetName == $preconditionArc['label'] )
			// 		{
			// 			$resource['linkbase'] = $linkbase;
			// 			$resource['linkRoleUri'] = $roleUri;
			// 			$preconditionResources[] = $resource;
			// 		}
			// 	}
			// 	return true;
			// } );

			foreach ( $preconditionArcs as $preconditionArc )
			{
				if ( $variableSet->path != $preconditionArc['frompath'] ) continue;
				$taxonomy->getGenericResource( 'variable', $element, function( $roleUri, $linkbase, $variableSetName, $index, $resource ) use( $preconditionArc, &$preconditionResources )
				{
					// This test is probably redundant because I believe $variableSetName is the same as $variableSetArc['label']
					// if ( $variableSetName == $preconditionArc['label'] )
					if ( $resource['path'] == $preconditionArc['topath'] /* || $linkbase == $preconditionArc['linkbase'] */ )
					{
						$resource['linkbase'] = $linkbase;
						$resource['linkRoleUri'] = $roleUri;
						$preconditionResources[] = $resource;
					}

					return true;
				}, $preconditionArc['toRoleUri'], $preconditionArc['to'], $preconditionArc['tolinkbase'] );
			}

			if ( ! $preconditionResources )
			{
				$this->log->formula_validation( "Precondition", "The source precondition for formula resource cannot be located",
					array(
						'formula' => $variableSet->label,
					)
				);

				return false;
			}

			foreach ( $preconditionResources as $preconditionResource )
			{
				/** @var Precondition $precondition */
				$precondition = $preconditionClassName::fromArray( $preconditionResource );
				$precondition->extendedLinkRoleUri = $preconditionResource['linkRoleUri'];
				if ( ! $precondition->validate( $variableSet, $this->nsMgr ) )
				{
					return false;
				}

				$variableSet->preconditions[ "{$precondition->extendedLinkRoleUri}#{$precondition->label}" ] = $precondition;
			}
		}

		return true;
	}