public function generate(DatasetUIMetaData $datasetUIMetaData, DatasetMetaData $dataset, $referencePath = NULL) {
        // to prevent recursive references
        $datasetStack = array($dataset->name => TRUE);

        $datasetUIMetaData->name = $dataset->name;
        $datasetUIMetaData->publicName = $dataset->publicName;
        $datasetUIMetaData->description = $dataset->description;

        foreach ($dataset->getColumns() as $column) {
            if (!$column->isVisible()) {
                continue;
            }

            $columnUIMetaData = $this->prepareColumnUIMetaData($datasetStack, $referencePath, $dataset, $column->name);
            $datasetUIMetaData->registerAttribute($columnUIMetaData);
        }
    }
    protected function generateDatasetMeasures(__CubeUIMetaDataGenerator_CallContext $callcontext, DatasetUIMetaData $datasetUIMetaData, CubeMetaData $cube, $referencePath) {
        if (isset($callcontext->usedMeasureNames)) {
            // preparing list of dataset-wide measures (those are measures which were not used by any columns)
            foreach ($callcontext->usedMeasureNames as $measureName => $used) {
                if ($used) {
                    continue;
                }

                // we do not need to show several 'Record Count' measures
                if (isset($referencePath) && ($measureName === StarSchemaNamingConvention::$MEASURE_NAME__RECORD_COUNT)) {
                    continue;
                }

                // checking if the measure could be linked to facts
                $possibleFactColumnNames = StarSchemaNamingConvention::preparePossibleOwners4Measure($measureName);
                if (isset($possibleFactColumnNames)) {
                    foreach ($possibleFactColumnNames as $possibleFactColumnName) {
                        $possibleFactUIMetaDataName = self::prepareColumnUIMetaDataName($referencePath, $cube->factsDatasetName, $possibleFactColumnName);
                        $attributeUIMetaData = $datasetUIMetaData->findAttribute($possibleFactUIMetaDataName);
                        if (isset($attributeUIMetaData)) {
                            $this->prepareAttributeCustomMeasure($attributeUIMetaData, $referencePath, $cube, $measureName);
                            continue 2;
                        }
                    }
                }

                // adding dataset custom measure
                $measure = $cube->measures[$measureName];

                $measureUIMetaData = new CubeMeasureUIMetaData();
                $measureUIMetaData->name = self::prepareMeasureUIMetaDataName($referencePath, $cube, $measureName);
                $measureUIMetaData->publicName = $measure->publicName;
                $measureUIMetaData->description = $measure->description;
                $measureUIMetaData->type = clone $measure->type;

                $datasetUIMetaData->registerMeasure($measureUIMetaData);
            }
        }
    }
    public function connectWith(DatasetUIMetaData $primaryDatasetUIMetaData, $datasetName, $referencePath = NULL) {
        // do not store generated UI meta data if reference path is provided for the following reasons:
        //   * there is unlimited number of possible reference paths;
        //   * it is almost impossible to delete cached items if dataset structure changes
        $isSelfReferenced = $this->isSelfReferenced($referencePath);
        $connectedDatasetCacheEntryName = isset($isSelfReferenced) ? $this->prepareCacheEntryName($datasetName, TRUE) : NULL;

        $connectedDatasetUIMetaData = isset($connectedDatasetCacheEntryName)
            ? $this->cache->getCachedEntry($connectedDatasetCacheEntryName)
            : NULL;
        if (!isset($connectedDatasetUIMetaData)) {
            $connectReferencePath = isset($referencePath) ? $referencePath : self::$REFERENCE_PATH__DEFAULT;
            $connectedDatasetUIMetaData = $this->generateDatasetUIMetaData($datasetName, $connectReferencePath);

            if (isset($connectedDatasetCacheEntryName)) {
                $this->cache->cacheEntry($connectedDatasetCacheEntryName, $connectedDatasetUIMetaData);
            }
        }

        $primaryDatasetUIMetaData->registerConnectedDataset($connectedDatasetUIMetaData);
    }