Get the xequal comparison type an element
@param XBRL_Types $types
@param string $localName
@param string|null $prefix
@return number
776104
private static function xequalElementType( $types, $localName, $prefix )
	{
		$element = $types->getElement( $localName, $prefix );
		if ( ! $element || ! isset( $element['types'] ) || ! count( $element['types'] ) ) return XBRL_Equality::$EQUALITY_TYPE_STRING;

		return XBRL_Equality::xEqualComparisonType( array( 'type' => $element['types'][0] ), $types);
	}
560871
public function isNumeric( $type )
	{
		// BMS 2018-05-02 Changed to use resolvesToBaseType instead of relying on some property
		if ( $type instanceof QName )
		{
			// $type = $this->getType( $type->localName, $type->prefix );
			$type = "{$type->prefix}:{$type->localName}";
		}
		else if ( is_string( $type ) && isset( $this->types[ $type ] ) )
		{
			$type = $this->types[ $type ];
		}

		$result = $this->resolvesToBaseType( $type, array( 'xs:decimal', 'xs:double', 'xs:float' ) );
		return $result;

		// if ( is_array( $type ) )
		// {
		// 	return isset( $type['numeric'] ) && filter_var( $type['numeric'], FILTER_VALIDATE_BOOLEAN );
		// }
		// else
		// {
		// 	return false;
		// }
	}
522707
public static function isEqualType(TypeInterface $typeA, TypeInterface $typeB): bool
    {
        // Equivalent types are equal.
        if ($typeA === $typeB) {
            return true;
        }

        // If either type is non-null, the other must also be non-null.
        if ($typeA instanceof NonNullType && $typeB instanceof NonNullType) {
            return self::isEqualType($typeA->getOfType(), $typeB->getOfType());
        }

        // If either type is a list, the other must also be a list.
        if ($typeA instanceof ListType && $typeB instanceof ListType) {
            return self::isEqualType($typeA->getOfType(), $typeB->getOfType());
        }

        // Otherwise the types are not equal.
        return false;
    }
1255447
public static boolean matchesTypeName(Class<?> clazz, String typeName) {
		return (typeName != null &&
				(typeName.equals(clazz.getName()) || typeName.equals(clazz.getSimpleName()) ||
				(clazz.isArray() && typeName.equals(getQualifiedNameForArray(clazz)))));
	}
530129
@Override
  protected boolean equalElements(KTypeVTypeHashMap<?, ?> other) {
    if (other.size() != size()) {
      return false;
    }

    Iterator<? extends KTypeVTypeCursor<?, ?>> i = other.iterator();
    while (i.hasNext()) {
      KTypeVTypeCursor<?, ?> c = i.next();
      KType key = Intrinsics.<KType> cast(c.key);
      if (!containsKey(key) ||
          !equals(get(key), c.value)) {   // Compare values using the same function as keys.
        return false;
      }
    }

    return true;
  }
817679
public static function getPhpType($type, $xsdTypesPath = null, $fallback = self::TYPE_STRING)
    {
        return XsdTypes::instance($xsdTypesPath)->isXsd(str_replace('[]', '', $type)) ? XsdTypes::instance($xsdTypesPath)->phpType($type) : $fallback;
    }
1270869
function getSite(prefix, locals) {
  const site = locals && locals.site;

  return site || siteService.getSiteFromPrefix(prefix);
}
3818
public function getAtomicType( $type )
	{
		if ( $type instanceof QName )
		{
			$type = "{$type->prefix}:{$type->localName}";
		}
		else if ( is_array( $type ) && isset( $type['prefix'] ) && isset( $type['prefix'] ) )
		{
			$type = "{$type['prefix']}:{$type['name']}";
		}
		else if ( ! is_string( $type ) ) return false;

		// If its not then look to see if there are ancestral types
		// BMS 2018-04-09 Test candidates changed.
		if ( $type == "xs:anyType" ) return "xs:anyType";

		// If its not then look to see if there are ancestral types
		// BMS 2018-04-09 Test candidates changed.
		if ( $type == "xs:anyComplexType" ) return false;

		// anyAtomicType is an alias for anySimpleType
		// BMS 2018-04-09 Test candidates changed.
		if ( $type == "xs:anyAtomicType" )
		{
			$type = "xs:anySimpleType";
		}
		// Is the $type already in $xsTypes
		if ( isset( SchemaTypes::$xsTypes[ $type ] ) )
		{
			return $type;
		}

		if ( ! isset( $this->types[ $type ] ) ) return false;

		$t = $this->types[ $type ];
		if ( isset( $t['parent'] ) )
		{
			// There are so repeat the test with the ancestor element
			return $this->getAtomicType( $t['parent'] );
		}
		// else if ( isset( $t['types'] ) )
		// {
		// 	// It may be necessary to consider types if $t is defined as a union such as xbrli:dateTimeItemType
		// 	foreach ( $t['types'] as $parentType )
		// 	{
		// 		$result = $this->getAtomicType( $parentType );
		// 		if ( $result )
		// 		{
		// 			return $t;
		// 		}
		// 	}
		// }
		else
		{
		}

		return false;
	}
208630
private function matchesIdAndEntityType()
    {
        $expr = $this->connection->getExpressionBuilder();

        return $expr->andX(
            $expr->eq('entity_id', ':entity_id'),
            $expr->eq('entity_type', ':entity_type')
        );
    }
46612
public function equals(Type $type) {
        if ($type === $this) {
            return true;
        }
        if ($type->type !== $this->type) {
            return false;
        }
        if ($type->type === Type::TYPE_OBJECT) {
            return strtolower($type->userType) === strtolower($this->userType);
        }
        // TODO: handle sub types
        if (isset(self::$hasSubtypes[$this->type]) && isset(self::$hasSubtypes[$type->type])) {
            if (count($this->subTypes) !== count($type->subTypes)) {
                return false;
            }
            // compare 
            $other = $type->subTypes;
            foreach ($this->subTypes as $st1) {
                foreach ($other as $key => $st2) {
                    if ($st1->equals($st2)) {
                        unset($other[$key]);
                        continue 2;
                    }
                    // We have a subtype that's not equal
                    return false;
                }
            }
            return empty($other);
        }
        return true;
    }
147050
public function getCountType( $kind = XPathNodeType::All )
	{
		$count = 0;

		/**
		 * @var XPath2NodeIterator $iter
		 */
		$iter = $this->CloneInstance();
		$iter->Reset();
		while ( $iter->MoveNext() )
		{
			$result = $iter->getCurrent();
			if ( $result instanceof ExprIterator )
			{
				$count += $result->getCount( $kind );
			}
			else
			{
				if ( $kind == XPathNodeType::All || $kind == $result->getNodeType() )
				{
					$count++;
				}
			}
		}

		return $count;
	}
1344318
public function Compare( $x, $y )
	{
		$nav1 = $x instanceof XPathNavigator
			? $x
			: null;
		$nav2 = $y instanceof XPathNavigator
			? $y
			: null;
		/**
		 * @var XPathNavigator $nav1
		 * @var XPathNavigator $nav2
		 */
		if ( ! is_null( $nav1 ) && ! is_null( $nav2 ) )
		{
			switch ( $nav1->ComparePosition( $nav2, $this->useLineNo ) )
			{
				case XmlNodeOrder::Before:
					return -1;

				case XmlNodeOrder::After:
					return 1;

				case XmlNodeOrder::Same:
					return 0;

				default:

					// It appears to be correct to return -1 every time because $nav1
					// will always appear before $nav2 because that's the order in which
					// they are presented in the XPath query.
					return -1;

					/**
					 * Below is an implementation of the C# version which appears to be wrong
					 * because the value of spl_object_hash (or getHashCode in C# is random
					 * so the result here is likely to be random.
					 * @var XPathNavigator $root1
					 * @var XPathNavigator $root2
					 */
					$root1 = $nav1->CloneInstance();
					$root1->MoveToRoot();
					$root2 = $nav2->CloneInstance();
					$root2->MoveToRoot();

					$hashCode1 = spl_object_hash( $root1 );
					$hashCode2 = spl_object_hash( $root2 );

					if ( $hashCode1 < $hashCode2 )
					{
						return -1;
					}
					else if ( $hashCode1 > $hashCode2 )
					{
						return 1;
					}
					else
					{
						throw new InvalidOperationException();
					}
			}
		}
		else
			throw XPath2Exception::withErrorCodeAndParams( "XPTY0004", Resources::XPTY0004,
				array(
					"xs:anyAtomicType",
					"node()* in function op:union,op:intersect and op:except"
				)
			);
	}
901769
private function findByBindingType($typeName)
    {
        $matches = array();

        $expr = Expr::isInstanceOf('Puli\Discovery\Binding\ResourceBinding');

        foreach ($this->discovery->findBindings($typeName, $expr) as $binding) {
            /** @var ResourceBinding $binding */
            foreach ($binding->getResources() as $resource) {
                $matches[$resource->getPath()] = StringUtil::getShortClassName(get_class($resource));
            }
        }

        ksort($matches);

        return $matches;
    }
705222
private function validateEssenceAliasArcs( XBRL_Types &$types )
	{

		$arcs = $this->getInstanceTaxonomy()->getEssenceAliasList();
		if ( ! $arcs ) return true;

		/* ---------------------------------------------------------
		 * Look for directed cycles
		 * ---------------------------------------------------------
		 */

		/**
		 * Examine the arcs recursively to look for directed cycles.
		 * If there are directed cyles then the $alias of an arc will appear in the list of $parents
		 *
		 * @var function $detectDirected
		 * @param string $essence
		 * @param array $parents
		 * @return bool
		 */
		$detectDirected = function( $essence, $parents = array() ) use( &$detectDirected, &$arcs )
		{
			foreach ( $arcs[ $essence ] as $alias => $details )
			{
				if ( $alias == $essence || in_array( $alias, $parents ) ) return true;

				if ( ! isset( $arcs[ $alias ] ) ) continue;

				if ( $detectDirected( $alias, array_merge( $parents, array( $essence ) ) ) )
				{
					XBRL_Log::getInstance()->instance_validation( "5.2.6.2.2", "The essence alias arcs contain directed cycles",
						array(
							'path' => implode( '->', $parents ),
						)
					);

					return true;
				}
			}

			return false;
		};

		foreach ( $arcs as $essence => $aliases )
		{
			if ( $detectDirected( $essence ) )
			{
				return false;
			}
		}

		/* ---------------------------------------------------------
		 * Check each arc
		 * ---------------------------------------------------------
		 */

		foreach ( $arcs as $essence => $aliases )
		{
			// echo "$essence\n";

			$parts = parse_url( $essence );
			if ( ! isset( $parts['path'] ) || ! isset( $parts['fragment'] ) ) continue;

			$essenceTaxonomy = $this->getInstanceTaxonomy()->getTaxonomyForXSD( $parts['path'] );
			if ( ! $essenceTaxonomy )
			{
				$this->log()->instance_validation( "5.2.6.2.2", "The taxonomy of the source does not exist in the DTS",
					array(
						'from' => $essence,
					)
				);
				continue;
			}

			$essenceElement = $essenceTaxonomy->getElementById( $parts['fragment'] );
			if ( ! $essenceElement )
			{
				$this->log()->instance_validation( "5.2.6.2.2", "The concept of the source does not exist in the DTS",
					array(
						'essence' => $essence,
					)
				);
				continue;
			}

			$type = $types->getType( $essenceElement['type'] );
			if ( ! $type )
			{
				$this->log()->instance_validation( "5.2.6.2.2" , "Cannot locate type information for the essence",
					array(
						'type' => $essenceElement['type'],
						'element' => $essence,
					)
				);
				continue;
			}

			// Look for the essence fact(s) in the instance document
			$essenceFact = $this->getElement( $essenceElement['id'] );

			// If the $from does not exist then infer the value
			$essenceAliasValues = array(); // Holds a list of inferred values grouped by parent nodes
			$combinations = new TupleDictionary();

			foreach ( $aliases as $alias => $details )
			{
				// echo "\t-> $alias\n";

				$parts = parse_url( $alias );
				if ( ! isset( $parts['path'] ) || ! isset( $parts['fragment'] ) ) continue;

				$aliasTaxonomy = $this->getInstanceTaxonomy()->getTaxonomyForXSD( $parts['path'] );
				if ( ! $aliasTaxonomy )
				{
					$this->log()->instance_validation( "5.2.6.2.2", "The taxonomy of the alias does not exist in the DTS",
						array(
							'alias' => $alias,
						)
					);
					continue;
				}

				$aliasElement = $aliasTaxonomy->getElementById( $parts['fragment'] );
				if ( ! $aliasElement )
				{
					$this->log()->instance_validation( "5.2.6.2.2", "The concept of the alias does not exist in the DTS",
						array(
							'alias' => $alias,
						)
					);
					continue;
				}

				// The element definitions should always have an type but its worth checking
				if ( XBRL_Instance::isEmpty( $aliasElement, 'type' ) || XBRL_Instance::isEmpty( $essenceElement, 'type' ) )
				{
					$this->log()->taxonomy_validation( "5.1.1.1", "Missing type attribute on essence or alias",
						array(
							'essence' => $essence,
							'alias' => $alias,
							'point' => '3',
							'essence_type' => $essenceElement['type'],
							'alias_type' => $aliasElement['type'],
						)
					);
					continue;
				}

				// The type of the essence and the alias must be the same
				if ( $aliasElement['type'] != $essenceElement['type'] )
				{
					continue;
				}

				// The element definitions should always have a periodType but its worth checking
				if ( XBRL_Instance::isEmpty( $aliasElement, 'periodType' ) || XBRL_Instance::isEmpty( $essenceElement, 'periodType' ) )
				{
					$this->log()->taxonomy_validation( "5.1.1.1", "Missing periodType attribute on essence or alias",
						array(
							'essence' => $essence,
							'alias' => $alias,
							'point' => '3',
							'essence_period_type' => $essenceElement['periodType'],
							'alias_period_type' => $aliasElement['periodType'],
						)
					);
					continue;
				}

				// The period type of both concepts MUST be the same
				if ( $aliasElement['periodType'] != $essenceElement['periodType'] )
				{
					$this->log()->instance_validation( "5.2.6.2.2", "The period types of the essence and alias are not compatible",
						array(
							'essence' => $essence,
							'alias' => $alias,
							'point' => '3',
							'essence_period_type' => $essenceElement['periodType'],
							'alias_period_type' => $aliasElement['periodType'],
						)
					);
					continue;
				}

				// If the alias and essence concepts include balance attribute then the value MUST be the same
				if ( ! XBRL_Instance::isEmpty( $aliasElement, 'balance' ) && ! XBRL_Instance::isEmpty( $essenceElement, 'balance' ) )
				{
					if (  $aliasElement['balance'] != $essenceElement['balance'] )
					{
						continue;
					}
				}

				// Look for the fact in the instance document
				$aliasFact = $this->getElement( $aliasElement['id'] );

				// If the $from does not exist there is noting else to do
				if ( ! $aliasFact ) continue;

				// Getting here means there is an essence concept and an alias concept that are equal
				// Now take a look at the facts

				if ( ! $essenceFact )
				{
					// If there is no essence fact infer any values
					foreach ( $aliasFact as $aliasEntryKey => $aliasEntry )
					{
						$value = $type['numeric']
							? $this->getNumericPresentation( $aliasEntry )
							: $aliasEntry['value'];

						// Create a key
						$key = array(
							'name' => $aliasElement['id'],
							'parent' => $aliasEntry['parent'],
							'context' => $this->getContext( $aliasEntry['contextRef'] ),
							'unit' => $type['numeric'] ? $this->getUnit( $aliasEntry['unitRef'] ) : null,
							'value' => $value,
						);

						$existing =& $combinations->getValue( $key, null );
						if ( ! is_null( $existing ) )
						{
							$source = array(
								'section' => '4.10',
								'name' => $aliasElement['id'],
								'contextRef' => "{$aliasEntry['contextRef']} vs {$existing['context']}",
								'unitRef' => "{$aliasEntry['contextRef']} vs {$existing['unit']}",
								'value' => "{$value} vs {$existing['value']}",
							);

							$this->log()->warning( sprintf( "Duplicate item: %s", $this->log()->arrayToDescription( $source ) ) );
						}

						$combinations->addValue( $key, array(
							'name' => $aliasElement['id'],
							'context' => $aliasEntry['contextRef'],
							'unit' => $type['numeric'] ? $aliasEntry['unitRef'] : null,
							'value' => $value,
						) );

						$essenceAliasValues[ $aliasEntry['parent'] ]['alias'][ $alias ] = $value;
						$essenceAliasValues[ $aliasEntry['parent'] ]['contexts'][ $aliasEntry['contextRef'] ] = $aliasEntry['contextRef'];
						$essenceAliasValues[ $aliasEntry['parent'] ]['units'][ $aliasEntry['unitRef'] ] = $aliasEntry['unitRef'];
					}
				}
				else
				{
					// There is an essence fact so make sure the essence and alias facts are c-equal, u-equal, p-equal and v-equal
					foreach ( $essenceFact as $essenceEntryKey => $essenceEntry )
					{
						// Using PHP_ROUND_HALF_EVEN see XBRL 2.1 section 4.6.7.2
						$essenceValue = $type['numeric']
						 	? $this->getNumericPresentation( $essenceEntry )
							: $essenceEntry['value'];

						foreach ( $aliasFact as $aliasEntryKey => $aliasEntry )
						{
							if ( ! XBRL_Instance::isEmpty( $aliasEntry, 'nil' ) && filter_var( $aliasEntry['nil'], FILTER_VALIDATE_BOOLEAN ) ) continue;

							// The essence and alias should be p-equal
							if ( $essenceEntry['parent'] != $aliasEntry['parent'] )
							{
								/*
								$this->log()->instance_validation( "5.2.6.2.2", "The scope for the arc is not valid because the essence parent and the alias parent are not the same",
									array(
										'essence' => $essence,
										'alias' => $alias,
										'point' => '3',
									)
								);
								*/
								continue;
							}

							// check the essence and alias are C-Equal (by definition also S-Equal), P-Equal, U-Equal, V-Equal
							if ( $essenceEntry['contextRef'] != $aliasEntry['contextRef'] &&
								 ! XBRL_Equality::context_equal( $this->getContext( $essenceEntry['contextRef'] ), $this->getContext( $aliasEntry['contextRef'] ) )
							   )
							{
								/*
								$this->log()->instance_validation( "5.2.6.2.2", "The contexts on the essence and alias are not compatible",
									array(
										'essence' => $essence,
										'alias' => $alias,
										'point' => '3',
										'essence_context' => $essenceEntry['contextRef'],
										'alias_context' => $aliasEntry['contextRef'],
									)
								);
								*/
								continue;
							}

							if ( $essenceEntry['unitRef'] != $aliasEntry['unitRef'] &&
								 ! XBRL_Equality::unit_equal( $this->getUnit( $essenceEntry['unitRef'] ), $this->getUnit( $aliasEntry['unitRef'] ), $types, $this->getInstanceNamespaces() )
							   )
							{
								$this->log()->instance_validation( "5.2.6.2.2", "The units on the essence and alias are not compatible",
									array(
										'essence' => $essence,
										'alias' => $alias,
										'point' => '3',
										'essence_unit' => $essenceEntry['unitRef'],
										'alias_unit' => $aliasEntry['unitRef'],
									)
								);
								continue;
							}

							$value = $type['numeric']
								? $this->getNumericPresentation( $aliasEntry )
								: $aliasEntry['value'];

							// Create a key
							$key = array(
								'name' => $aliasElement['id'],
								'parent' => $aliasEntry['parent'],
								'context' => $this->getContext( $aliasEntry['contextRef'] ),
								'unit' => $type['numeric'] ? $this->getUnit( $aliasEntry['unitRef'] ) : null,
								'value' => $value,
							);

							$existing =& $combinations->getValue( $key, null );
							if ( ! is_null( $existing ) )
							{
								$source = array(
									'section' => '4.10',
									'name' => $aliasElement['id'],
									'contextRef' => "{$aliasEntry['contextRef']} vs {$existing['context']}",
									'unitRef' => "{$aliasEntry['contextRef']} vs {$existing['unit']}",
									'value' => "{$value} vs {$existing['value']}",
								);

								$this->log()->warning( sprintf( "Duplicate item: %s", $this->log()->arrayToDescription( $source ) ) );
							}

							$combinations->addValue( $key, array(
								'name' => $aliasElement['id'],
								'context' => $aliasEntry['contextRef'],
								'unit' => $type['numeric'] ? $aliasEntry['unitRef'] : null,
								'value' => $value,
							) );

							$essenceAliasValues[ $essenceEntry['parent'] ]['essencevalue'] = $essenceValue;
							$essenceAliasValues[ $essenceEntry['parent'] ]['essence'] = $essence;

							$essenceAliasValues[ $aliasEntry['parent'] ]['alias'][ $alias ] = $value;
							$essenceAliasValues[ $aliasEntry['parent'] ]['contexts'][ $aliasEntry['contextRef'] ] = $aliasEntry['contextRef'];
							$essenceAliasValues[ $aliasEntry['parent'] ]['units'][ $aliasEntry['unitRef'] ] = $aliasEntry['unitRef'];
						}
					}
				}
			}

			// If an essence fact exists then check its values are consistent with the alias value(s)
			// If an essence fact does not exist then create one based on the values in the $inferredParents
			foreach ( $essenceAliasValues as $parentKey => $details )
			{
				if ( isset( $details['essencevalue'] ) )
				{
					foreach ( $details['alias'] as $alias => $value )
					{
						if ( $value === $details['essencevalue'] ) continue;
						$this->log()->instance_validation( "5.2.6.2.2", "Essence alias values do not match",
							array(
								'essence' => $details['essence'],
								'alias' => $alias,
								'essence_value' => $details['essencevalue'],
								'alias_value' => "'$value'",
							)
						);
					}
				}
				else
				{
					// echo "Need to create an inferred fact\n";
					// Create a namespace prefix as known in the instance document for consistency
					// This gets the namespace for the essence element looks up the corresponding prefix in the instance document
					$namespace = $this->getPrefixForNamespace( $essenceTaxonomy->getNamespaceForPrefix( $essenceTaxonomy->getPrefix() ) );
					$newEntry = array(
						'taxonomy_element' => $essenceElement,
						'namespace' => $namespace,
					);

					// All the values must be the same if a value for the essence is to be inferred
					$diff = array_diff( $details['alias'], $details['alias'] );
					if ( ! $diff ) continue;

					$this->log()->instance_validation( "5.2.6.2.2", "The values of all aliases should all be the same for an essence value to be inferre",
						array(
							'essence' => $essence,
							'alias' => $this->log()->arrayToDescription( $details['alias'] ),
						)
					);

					$newEntry['contextRef'] = reset( $details['contexts'] );
					$newEntry['unitRef'] = reset( $details['units'] );

					$this->addElement( $essence, $newEntry );
				}
			}
		}
	}
295097
private static function xEqualComparisonType( $details, $types )
	{
		$type = isset( $details['type'] ) ? $details['type'] : false;

		if ( $type && $types->resolvesToBaseType( $type, array( 'xs:double', 'xsd:double', 'xs:float', 'xsd:float', 'xs:decimal', 'xsd:decimal' ) ) )
		{
			return XBRL_Equality::$EQUALITY_TYPE_NUMBER;
		}
		else if ( $type && $types->resolvesToBaseType( $type, array( 'xs:boolean', 'xsd:boolean' ) ) )
		{
			return XBRL_Equality::$EQUALITY_TYPE_BOOLEAN;
		}

		return XBRL_Equality::$EQUALITY_TYPE_STRING;
	}
680505
public static function entity_equal( $e1, $e2 )
	{
		if ( is_null( $e1 ) && is_null( $e2 ) ) return true;
		if ( is_null( $e1 ) || is_null( $e2 ) ) return false;

		// Check the arrays have the same elements
		$result = XBRL_Equality::matchedKeyNames( $e1, $e2, array( 'identifier', 'segment' ) );

		// if ( $result === false || ! is_array( $result ) || ! count( $result ) ) return false;
		if ( $result === false || ! is_array( $result ) ) return false;
		if ( ! count( $result ) ) return true;

		foreach ( $result as $elementName )
		{
			switch ( $elementName )
			{
				case 'identifier':

					if ( ! XBRL_Equality::identifier_equal( $e1['identifier'], $e2['identifier'] ) )
					{
						return false;
					}

					break;

				case 'segment':

					if ( ! XBRL_Equality::segment_equal( $e1['segment'], $e2['segment'] ) )
					{
						return false;
					}

					break;
			}
		}

		return true;
	}
759184
public function getElement( $name, $prefix = null )
	{
		return $this->hasElement( $name, $prefix )
			? $this->elements[ is_null( $prefix ) ? $name : "$prefix:$name" ]
			: false;
	}