protected function prepareDatasetSequence(ReferenceCallContext $callcontext, MetaModel $metamodel, ReferenceLink $link, $referencePath) {
        $referenceParts = ReferencePathHelper::splitReference($referencePath);

        $parentColumnName = array_pop($referenceParts);
        $parentDatasetName = array_pop($referenceParts);
        $referencedColumnName = $referencedDatasetName = NULL;

        $leftReferencePartCount = count($referenceParts);

        $nestedReferencePath = $referencePath;
        if ($link->dataset->name == $parentDatasetName) {
            // dataset is there and it is link's dataset
            if ($leftReferencePartCount == 0) {
                return;
            }

            // assembling new reference path
            $nestedReferencePath = ReferencePathHelper::assembleReferenceParts($referenceParts);

            $referencedColumnName = array_pop($referenceParts);
            $referencedDatasetName = array_pop($referenceParts);

            if (!isset($referencedDatasetName)) {
                throw new UnsupportedOperationException(t(
                    'Dataset name is not set in the reference path: %referencePath',
                    array('%referencePath' => $referencePath)));
            }
        }
        elseif (isset($parentDatasetName)) {
            $referencedColumnName = $parentColumnName;
            $referencedDatasetName = $parentDatasetName;
            $parentColumnName = $parentDatasetName = NULL;
        }
        else {
            if ($leftReferencePartCount > 0) {
                throw new UnsupportedOperationException(t(
                    'Dataset name is not set in the reference path: %referencePath',
                    array('%referencePath' => $referencePath)));
            }

            // it means that we just point to column in link's dataset
            return;
        }

        // checking if there any references which could be used to find required dataset
        $references = $metamodel->findReferencesByDatasetName($link->dataset->name);
        if (!isset($references)) {
            return;
        }

        // maximum number of columns in direct references
        $directReferencePointColumnCount = NULL;

        // checking if there is any reference which directly link to referenced dataset
        $parentReferencePointIndex4References = $directReferencePointIndex4References = $transitionalReferencePointIndexes4References = NULL;
        foreach ($references as $reference) {
            $referencePointColumnCount = $reference->getPointColumnCount();

            // checking if the reference can be used to link with other datasets
            $parentReferencePointIndex4Reference = $directReferencePointIndex4Reference = $transitionalReferencePointIndexes4Reference = NULL;
            for ($referencePointColumnIndex = 0; $referencePointColumnIndex < $referencePointColumnCount; $referencePointColumnIndex++) {
                $parentReferencePointIndex = $directReferencePointIndex = $transitionalReferencePointIndexes = NULL;
                foreach ($reference->points as $referencePointIndex => $referencePoint) {
                    $datasetName = $referencePoint->columns[$referencePointColumnIndex]->datasetName;

                    if (($link->dataset->name == $datasetName)
                            && (!isset($parentColumnName) || ($parentColumnName == $referencePoint->columns[$referencePointColumnIndex]->columnName))) {
                        if (isset($parentReferencePointIndex)) {
                            // Found several possible ways to start a join from the referring dataset.
                            // That happens because we do not have parent column name and possible join is ambiguous
                            // We cannot use this way to proceed
                            continue 3;
                        }
                        else {
                            $parentReferencePointIndex = $referencePointIndex;
                        }
                    }
                    elseif ($datasetName == $referencedDatasetName) {
                        if (isset($directReferencePointIndex)) {
                            // found several possible ways to join with the referenced dataset
                            continue 3;
                        }
                        else {
                            $directReferencePointIndex[$referencePointIndex] = TRUE;
                        }
                    }
                    else {
                        $transitionalReferencePointIndexes[$referencePointIndex] = FALSE;
                    }
                }

                // this reference cannot be used because none of the reference points linked with parent dataset
                if (!isset($parentReferencePointIndex)) {
                    continue 2;
                }

                if (isset($directReferencePointIndex)) {
                    // if we have direct reference we do not care about indirect ones
                    $transitionalReferencePointIndexes = NULL;
                }
                else {
                    // there is no direct or indirect ways. This reference is useless :)
                    if (!isset($transitionalReferencePointIndexes)) {
                        continue 2;
                    }
                }

                $parentReferencePointIndex4Reference[$referencePointColumnIndex] = $parentReferencePointIndex;
                if (isset($directReferencePointIndex)) {
                    $directReferencePointIndex4Reference[$referencePointColumnIndex] = $directReferencePointIndex;
                }
                if (isset($transitionalReferencePointIndexes)) {
                    $transitionalReferencePointIndexes4Reference[$referencePointColumnIndex] = $transitionalReferencePointIndexes;
                }
            }

            // we support only direct references between datasets
            // in this case we have direct reference based on some columns only. Rest columns are connected indirectly
            if (isset($directReferencePointIndex4Reference) && isset($transitionalReferencePointIndexes4Reference)) {
                continue;
            }

            $parentReferencePointIndex4References[$reference->name] = $parentReferencePointIndex4Reference;
            if (isset($directReferencePointIndex4Reference)) {
                $directReferencePointIndex4References[$reference->name] = $directReferencePointIndex4Reference;
                $directReferencePointColumnCount = MathHelper::max($directReferencePointColumnCount, $referencePointColumnCount);
            }
            if (isset($transitionalReferencePointIndexes4Reference)) {
                $transitionalReferencePointIndexes4References[$reference->name] = $transitionalReferencePointIndexes4Reference;
            }
        }
        // we could use none of the selected references
        if (!isset($parentReferencePointIndex4References)) {
            return;
        }

        // removing all useless direct and indirect references if there is a direct way
        if (isset($directReferencePointColumnCount)) {
            foreach ($parentReferencePointIndex4References as $referenceName => $parentReferencePointIndex4Reference) {
                $referencePointColumnCount = count($parentReferencePointIndex4Reference);

                if (isset($directReferencePointIndex4References[$referenceName])) {
                    // we preserve only direct ways with maximum number of columns
                    if ($referencePointColumnCount == $directReferencePointColumnCount) {
                        continue;
                    }
                }
                else {
                    // we preserve only indirect ways with more columns than in direct way
                    if ($referencePointColumnCount > $directReferencePointColumnCount) {
                        continue;
                    }
                }

                unset($parentReferencePointIndex4References[$referenceName]);
                unset($directReferencePointIndex4References[$referenceName]);
                unset($transitionalReferencePointIndexes4References[$referenceName]);
            }
        }

        foreach ($parentReferencePointIndex4References as $referenceName => $parentReferencePointIndex4Reference) {
            $reference = $references[ArrayHelper::search($references, 'name', $referenceName)];

            $referencePointColumnCount = $reference->getPointColumnCount();

            $referencePointIndexes4Reference = isset($directReferencePointIndex4References[$referenceName])
                ? $directReferencePointIndex4References[$referenceName]
                : NULL;
            $isDirectReference = isset($referencePointIndexes4Reference);

            if (!$isDirectReference) {
                // 01/09/2014 reference can be reused only for direct references
                if (isset($callcontext->referenceNameStack[$referenceName])) {
                    continue;
                }

                $referencePointIndexes4Reference = isset($transitionalReferencePointIndexes4References[$referenceName])
                    ? $transitionalReferencePointIndexes4References[$referenceName]
                    : NULL;
            }

            // registering the reference in a stack to avoid excessive calls
            // registration was moved here because we could have date[->month->quarter->year] and year columns in one dataset
            // if references related to date and year are registered before we start to process individual references
            // we will end up with nested links for date->month->quarter->year which do not contain a reference to year
            // which leads to GOVDB-1313 issue
            $callcontext->referenceNameStack[$reference->name] = TRUE;

            // preparing dataset names for each reference point
            $referencePointDatasetNames = NULL;
            for ($referencePointColumnIndex = 0; $referencePointColumnIndex < $referencePointColumnCount; $referencePointColumnIndex++) {
                foreach ($referencePointIndexes4Reference[$referencePointColumnIndex] as $referencePointIndex => $directReferencePointFlag) {
                    $referencePointColumn = $reference->points[$referencePointIndex]->columns[$referencePointColumnIndex];
                    $datasetName = $referencePointColumn->datasetName;

                    // it is expected that dataset name is the same for all columns in a reference point
                    if (isset($referencePointDatasetNames[$referencePointIndex])) {
                        if ($referencePointDatasetNames[$referencePointIndex] != $datasetName) {
                            // Dataset name is not the same for all columns for the reference point
                            $referencePointDatasetNames[$referencePointIndex] = FALSE;
                        }
                    }
                    else {
                        $referencePointDatasetNames[$referencePointIndex] = $datasetName;
                    }
                }
            }
            // removing all reference points which we cannot support now
            foreach ($referencePointDatasetNames as $referencePointIndex => $datasetName) {
                if ($datasetName === FALSE) {
                    unset($referencePointDatasetNames[$referencePointIndex]);
                }
            }
            // if nothing left there is not need to proceed
            if (count($referencePointDatasetNames) == 0) {
                continue;
            }

            // preparing list of parent column names
            $parentColumnNames = NULL;
            for ($referencePointColumnIndex = 0; $referencePointColumnIndex < $referencePointColumnCount; $referencePointColumnIndex++) {
                $parentReferencePointIndex = $parentReferencePointIndex4Reference[$referencePointColumnIndex];
                $parentReferencePointColumnName = $reference->points[$parentReferencePointIndex]->columns[$referencePointColumnIndex]->columnName;

                $parentColumnNames[$referencePointColumnIndex] = $parentReferencePointColumnName;
            }

            $referenceCallContext = $isDirectReference ? $callcontext : (clone $callcontext);

            // adding all indirect datasets in stack to prevent recursive calls
            if (!$isDirectReference) {
                foreach ($referencePointDatasetNames as $referencePointIndex => $datasetName) {
                    if (isset($referenceCallContext->datasetNameStack[$datasetName])) {
                        unset($referencePointDatasetNames[$referencePointIndex]);
                    }
                    else {
                        $referenceCallContext->datasetNameStack[$datasetName] = TRUE;
                    }
                }
            }

            foreach ($referencePointDatasetNames as $referencePointIndex => $datasetName) {
                // looking for existing link
                $referencedLink = $link->findNestedLinkByDatasetNameAndParentColumnNames($datasetName, $parentColumnNames);
                if (!isset($referencedLink)) {
                    $dataset = $metamodel->getDataset($datasetName);

                    $referencedLink = new ReferenceLink($dataset);
                    foreach ($parentColumnNames as $referencePointColumnIndex => $parentReferencePointColumnName) {
                        $referencePointColumn = $reference->points[$referencePointIndex]->columns[$referencePointColumnIndex];
                        $referencedLink->linkColumnWithParent($referencePointColumnIndex, $parentReferencePointColumnName, $referencePointColumn->columnName);
                    }

                    $link->registerNestedLink($referencedLink);
                }
                ArrayHelper::addUniqueValue($referencedLink->referenceNames, $referenceName);

                // marking the link as required for the branch so it will not be deleted by the optimizer later
                if ($isDirectReference) {
                    $referencedLink->required = TRUE;
                }

                // because this reference path is not processed completely we need to continue scanning this branch
                if (isset($nestedReferencePath)) {
                    LogHelper::log_debug(t(
                        'Checking sub-path[linkId: @linkId; stackSize: @stackSize]: @referencePath',
                        array('@linkId' => $referencedLink->linkId, '@stackSize' => count($callcontext->referenceNameStack), '@referencePath' => $referencePath)));
                    $referencePointCallContext = clone $referenceCallContext;
                    $this->prepareDatasetSequence($referencePointCallContext, $metamodel, $referencedLink, $nestedReferencePath);
                }
            }
        }
    }