public function generate(array $possiblyLinkableDatasetNames = NULL) {
        $adjustedPossiblyLinkableDatasetNames = NULL;
        if (isset($possiblyLinkableDatasetNames)) {
            foreach ($possiblyLinkableDatasetNames as $possiblyLinkableDatasetName) {
                $adjustedPossiblyLinkableDatasetName = $this->adjustDatasetName($possiblyLinkableDatasetName);
                // we should not try to link with itself
                if ($adjustedPossiblyLinkableDatasetName == $this->primaryDatasetName) {
                    continue;
                }

                ArrayHelper::addUniqueValue($adjustedPossiblyLinkableDatasetNames, $adjustedPossiblyLinkableDatasetName);
            }
        }

        // preparing reference paths for all datasets which we need to test for possible linkage
        $referencePaths = NULL;
        if (isset($adjustedPossiblyLinkableDatasetNames)) {
            foreach ($adjustedPossiblyLinkableDatasetNames as $adjustedPossiblyLinkableDatasetName) {
                // column name should not be provided because we just try to link with the dataset
                $referencePath = ReferencePathHelper::assembleReference($adjustedPossiblyLinkableDatasetName, NULL);

                $referencePaths[$referencePath] = FALSE; // FALSE - if we cannot find link it is ok. Not everything could be connected
            }
        }

        $linkBuilder = new ReferenceLinkBuilder();
        $link = $linkBuilder->prepareReferenceBranches($this->primaryDatasetName, $referencePaths);

        return $link;
    }
 public function prepareDatasetSourceStatement(DataControllerCallContext $callcontext, DatasetMetaData $dataset, array $columnNames = NULL)
 {
     $statement = NULL;
     // preparing list of datasets which we need to work with
     $referencePaths = ReferenceLinkBuilder::selectReferencedColumnNames($columnNames);
     if (isset($referencePaths)) {
         $linkBuilder = new ReferenceLinkBuilder();
         $link = $linkBuilder->prepareReferenceBranches($dataset->name, $referencePaths);
         $statement = $this->assembleConnectedDatasetSourceStatement($callcontext, $link, $columnNames);
     } else {
         $statement = $this->assembleDatasetSourceStatement($callcontext, $dataset, $columnNames);
     }
     return $statement;
 }
    public function generateStatement(AbstractSQLDataSourceQueryHandler $datasourceHandler, DataControllerCallContext $callcontext, AbstractCubeQueryRequest $request) {
        $statement = $this->prepareSelectedCubeQueryStatement($datasourceHandler, $callcontext, $request);
        if (!isset($request->referencedRequests)) {
            return $statement;
        }

        $combinedStatement = new Statement();

        $metamodel = data_controller_get_metamodel();

        $cubeName = $request->getCubeName();
        $cube = $metamodel->getCube($cubeName);

        $datasetMappedCubeRequests = array($cube->factsDatasetName => $request);

        // preparing list of reference paths
        $referencePaths = NULL;
        foreach ($request->referencedRequests as $referencedRequest) {
            $referencedCubeName = $referencedRequest->getCubeName();
            $referencedCube = $metamodel->getCube($referencedCubeName);
            $referencedDatasetName = $referencedCube->factsDatasetName;

            $referencePath = ReferencePathHelper::assembleReference($referencedDatasetName, NULL);
            $referencePaths[$referencePath] = TRUE; // TRUE - required reference

            $datasetMappedCubeRequests[$referencedDatasetName] = $referencedRequest;
        }

        // finding ways to link the referenced cubes
        $linkBuilder = new ReferenceLinkBuilder();
        $link = $linkBuilder->prepareReferenceBranches($cube->factsDatasetName, $referencePaths);

        // preparing primary cube aggregation statement
        list($isSubqueryRequired, $assembledPrimaryCubeAggregationSections) = $statement->prepareSections(NULL);
        $primaryCubeAggregationTableSection = new SubquerySection(
            Statement::assemble($isSubqueryRequired, NULL, $assembledPrimaryCubeAggregationSections, SelectStatementPrint::INDENT__SUBQUERY, FALSE),
            self::$TABLE_ALIAS__REFERENCED . $link->linkId);

        // adding columns which are returned by primary aggregation
        foreach ($statement->tables as $table) {
            if (!isset($table->columns)) {
                continue;
            }

            foreach ($table->columns as $column) {
                if (!$column->visible) {
                    continue;
                }

                $primaryCubeAggregationTableSection->columns[] = new ColumnSection($column->alias);
            }
        }

        // registering primary cube statement in resulting statement
        $combinedStatement->tables[] = $primaryCubeAggregationTableSection;

        $this->prepareReferencedCubeQueryStatement($datasourceHandler, $callcontext, $combinedStatement, $datasetMappedCubeRequests, $link);

        return $combinedStatement;
    }