JoinAssociationPathExpression ::= IdentificationVariable "." (CollectionValuedAssociationField | SingleValuedAssociationField)

@return AST\JoinAssociationPathExpression
320230
public function JoinAssociationPathExpression()
    {
        $identVariable = $this->IdentificationVariable();

        if (! isset($this->queryComponents[$identVariable])) {
            $this->semanticalError(
                'Identification Variable ' . $identVariable . ' used in join path expression but was not defined before.'
            );
        }

        $this->match(Lexer::T_DOT);
        $this->match(Lexer::T_IDENTIFIER);

        $field = $this->lexer->token['value'];

        // Validate association field
        $qComp    = $this->queryComponents[$identVariable];
        $class    = $qComp['metadata'];
        $property = $class->getProperty($field);

        if (! ($property !== null && $property instanceof AssociationMetadata)) {
            $this->semanticalError('Class ' . $class->getClassName() . ' has no association named ' . $field);
        }

        return new AST\JoinAssociationPathExpression($identVariable, $field);
    }
906448
public function IdentificationVariableDeclaration()
    {
        $joins                    = [];
        $rangeVariableDeclaration = $this->RangeVariableDeclaration();
        $indexBy                  = $this->lexer->isNextToken(Lexer::T_INDEX)
            ? $this->IndexBy()
            : null;

        $rangeVariableDeclaration->isRoot = true;

        while ($this->lexer->isNextToken(Lexer::T_LEFT) ||
            $this->lexer->isNextToken(Lexer::T_INNER) ||
            $this->lexer->isNextToken(Lexer::T_JOIN)
        ) {
            $joins[] = $this->Join();
        }

        return new AST\IdentificationVariableDeclaration(
            $rangeVariableDeclaration,
            $indexBy,
            $joins
        );
    }
1038763
public function getJoinString()
    {
        $statement = "";
        
        foreach ($this->join as $i => $join) {
            $statement .= " " . $join['type'] . " " . $join['table'];
            
            if ($join['alias']) {
                $statement .= " AS " . $join['alias'];
            }
            
            // Add ON criteria if specified.
            if ($join['criteria']) {
                $statement .= " ON ";
                
                foreach ($join['criteria'] as $x => $criterion) {
                    // Logically join each criterion with AND.
                    if ($x != 0) {
                        $statement .= " " . self::LOGICAL_AND . " ";
                    }
                    
                    // If the criterion does not include an equals sign, assume a
                    // column name and join against the same column from the previous
                    // table.
                    if (strpos($criterion, '=') === false) {
                        $statement .= $this->getJoinCriteriaUsingPreviousTable($i, $join['table'], $criterion);
                    } else {
                        $statement .= $criterion;
                    }
                }
            }
        }
        
        $statement = trim($statement);
        
        return $statement;
    }
509870
protected function getFieldForToOneAssociation($sourceAssociation)
    {
        $targetClassMetadata = $this->getClassMetadata($sourceAssociation['targetEntity']);
        $joinedColumn = reset($sourceAssociation['joinColumns']);

        if (!$joinedColumn) {
            // One-to-One referenced only in foreign table => do not create field
            return null;
        }

        $type = $this->getTypeForAssociation($sourceAssociation);

        $fieldName = $sourceAssociation['fieldName'];

        $inverseOf = $sourceAssociation['inversedBy'];

        $foreignTableName = $targetClassMetadata->getTableName();
        $foreignIdentifier = $targetClassMetadata->getIdentifier();
        //if(count($foreignIdentifier) > 1) die(__METHOD__.'::'.__LINE__.': '.$foreignTableName.' has more than one identifier : '.json_encode($foreignIdentifier));
        $foreignIdentifier = reset($foreignIdentifier);
        $reference = $foreignTableName . '.' . $foreignIdentifier;

        // $pivot is just the foreign key in current table
        $pivot = new Pivot($joinedColumn['name']);

        return new ForestField($fieldName, $type, $reference, $inverseOf, $pivot);
    }
560497
public function versionAssociation($field = null, $options = [])
    {
        $name = $this->_associationName($field);

        if (!$this->_table->associations()->has($name)) {
            $model = $this->_config['referenceName'];

            $options += [
                'className' => $this->_config['versionTable'],
                'foreignKey' => $this->_config['foreignKey'],
                'strategy' => 'subquery',
                'dependent' => true
            ];

            if ($field) {
                $options += [
                    'conditions' => [
                        $name . '.model' => $model,
                        $name . '.field' => $field,
                    ],
                    'propertyName' => $field . '_version'
                ];
            } else {
                $options += [
                    'conditions' => [
                        $name . '.model' => $model
                    ],
                    'propertyName' => '__version'
                ];
            }

            $this->_table->hasMany($name, $options);
        }

        return $this->_table->getAssociation($name);
    }
1044074
public function fieldIdentifier()
    {
        $tableName = $this->table();
        $fieldName = $this->fieldName();

        return Expression::quoteIdentifier($fieldName, $tableName);
    }
894869
public function PartialObjectExpression()
    {
        $this->match(Lexer::T_PARTIAL);

        $partialFieldSet = array();

        $identificationVariable = $this->IdentificationVariable();

        $this->match(Lexer::T_DOT);
        $this->match(Lexer::T_OPEN_CURLY_BRACE);
        $this->match(Lexer::T_IDENTIFIER);

        $partialFieldSet[] = $this->lexer->token['value'];

        while ($this->lexer->isNextToken(Lexer::T_COMMA)) {
            $this->match(Lexer::T_COMMA);
            $this->match(Lexer::T_IDENTIFIER);
    
            $field = $this->lexer->token['value'];
    
            while ($this->lexer->isNextToken(Lexer::T_DOT)) {
                $this->match(Lexer::T_DOT);
                $this->match(Lexer::T_IDENTIFIER);
                $field .= '.'.$this->lexer->token['value'];
            }
    
            $partialFieldSet[] = $field;
        }

        $this->match(Lexer::T_CLOSE_CURLY_BRACE);

        $partialObjectExpression = new AST\PartialObjectExpression($identificationVariable, $partialFieldSet);

        // Defer PartialObjectExpression validation
        $this->deferredPartialObjectExpressions[] = array(
            'expression'   => $partialObjectExpression,
            'nestingLevel' => $this->nestingLevel,
            'token'        => $this->lexer->token,
        );

        return $partialObjectExpression;
    }
1144781
public function listAssociationsAction(string $filter = null)
    {
        $this->checkStaticTemplateIsIncluded();
        $this->checkSettings();

        $this->slotExtendedAssignMultiple([
            self::VIEW_VARIABLE_ASSOCIATION_ID => $this->settings[self::SETTINGS_ASSOCIATION_ID],
            self::VIEW_VARIABLE_FILTER => $this->getAssociationsFilter($filter),
            self::VIEW_VARIABLE_USER_FILTER => $this->getUserAssociationsFilter($filter)
        ], __CLASS__, __FUNCTION__);

        return $this->view->render();
    }
546492
public function getAssociationCategories()
    {
        $url = $this->getBaseApiUrl() . '/meta/association/categories';

        $xml = $this->queryXml($url);
        return $xml->metalist;
    }
1071828
function getPathFromMemberExpression(expr, acc = []) {
  if (expr.type === "Identifier") {
    return acc.concat(expr.name);
  } else if (expr.type === "MemberExpression") {
    return acc.concat(getPathFromMemberExpression(expr.object, acc)).concat(expr.property.name);
  } else {
    throw new Error(`Expected MemberExpression or Identifier but get ${expr.type}.`);
  }
}
129728
public function walkIdentificationVariable($identificationVariable, $fieldName = null)
    {
        $class = $this->queryComponents[$identificationVariable]['metadata'];

        if (! $fieldName) {
            return $this->getSQLTableAlias($class->getTableName(), $identificationVariable);
        }

        $property = $class->getProperty($fieldName);

        if ($class->inheritanceType === InheritanceType::JOINED && $class->isInheritedProperty($fieldName)) {
            $class = $property->getDeclaringClass();
        }

        return $this->getSQLTableAlias($class->getTableName(), $identificationVariable);
    }
27725
private function getAssociationValue(ResultSetMapping $rsm, $assocAlias, $entity)
    {
        $path  = [];
        $alias = $assocAlias;

        while (isset($rsm->parentAliasMap[$alias])) {
            $parent = $rsm->parentAliasMap[$alias];
            $field  = $rsm->relationMap[$alias];
            $class  = $rsm->aliasMap[$parent];

            array_unshift($path, [
                'field'  => $field,
                'class'  => $class,
            ]);

            $alias = $parent;
        }

        return $this->getAssociationPathValue($entity, $path);
    }
916114
public function getAssociations() : array
    {
        $values = get_object_vars($this);
        foreach ($values as $property => $value) {
            // Skip scalar values
            if ( ! is_object($value)) {
                unset($values[$property]);
            }
        }

        return $values;
    }
1115925
public function getAssociation($name, $autoLoad = true)
    {
        if (isset($this->loadedAssociations[$name])) {
            return $this->loadedAssociations[$name];
        } elseif ($autoLoad && $this->getAssociations()->exists($name)) {
            $this->loadedAssociations[$name] =
                $this->getAssociations()->load($this, $name);
            return $this->loadedAssociations[$name];
        }
        return null;
    }
946630
public function JoinAssociationDeclaration()
    {
        $joinAssociationPathExpression = $this->JoinAssociationPathExpression();

        if ($this->lexer->isNextToken(Lexer::T_AS)) {
            $this->match(Lexer::T_AS);
        }

        $aliasIdentificationVariable = $this->AliasIdentificationVariable();
        $indexBy                     = $this->lexer->isNextToken(Lexer::T_INDEX) ? $this->IndexBy() : null;

        $identificationVariable = $joinAssociationPathExpression->identificationVariable;
        $field                  = $joinAssociationPathExpression->associationField;

        $class       = $this->queryComponents[$identificationVariable]['metadata'];
        $targetClass = $this->em->getClassMetadata($class->associationMappings[$field]['targetEntity']);

        // Building queryComponent
        $joinQueryComponent = array(
            'metadata'     => $targetClass,
            'parent'       => $joinAssociationPathExpression->identificationVariable,
            'relation'     => $class->getAssociationMapping($field),
            'map'          => null,
            'nestingLevel' => $this->nestingLevel,
            'token'        => $this->lexer->lookahead
        );

        $this->queryComponents[$aliasIdentificationVariable] = $joinQueryComponent;

        return new AST\JoinAssociationDeclaration($joinAssociationPathExpression, $aliasIdentificationVariable, $indexBy);
    }
871605
public function walkIdentificationVariableDeclaration($identificationVariableDecl)
    {
        $sql = $this->walkRangeVariableDeclaration($identificationVariableDecl->rangeVariableDeclaration);

        if ($identificationVariableDecl->indexBy) {
            $this->walkIndexBy($identificationVariableDecl->indexBy);
        }

        foreach ($identificationVariableDecl->joins as $join) {
            $sql .= $this->walkJoin($join);
        }

        return $sql;
    }
1348777
private Attribute<?> toAssociationDto(Object value, AssociationAttributeInfo associationAttributeInfo)
			throws GeomajasException {
		if (associationAttributeInfo.getType() == AssociationType.MANY_TO_ONE) {
			return new ManyToOneAttribute(createAssociationValue(value, associationAttributeInfo));
		} else if (associationAttributeInfo.getType() == AssociationType.ONE_TO_MANY) {
			// Value should be an array of objects...
			List<AssociationValue> associationValues = new ArrayList<AssociationValue>();
			if (value != null && value instanceof Object[]) {
				Object[] array = (Object[]) value;
				for (Object bean : array) {
					associationValues.add(createAssociationValue(bean, associationAttributeInfo));
				}
			}
			return new OneToManyAttribute(associationValues);
		}
		return null;
	}