protected function permitNonLookupDatasetStorageChanges(DataControllerCallContext $callcontext, DatasetMetaData $originalLogicalDataset, DatasetMetaData $modifiedLogicalDataset) {
        // it needs to be update dataset structure operation
        if (!isset($callcontext->changeAction)) {
            return;
        }

        // checking if we try to exclude some columns
        if (!isset($callcontext->changeAction->excludedColumns)) {
            return;
        }

        // checking if we try to exclude reference column
        // If we do we need to delete persistence storage
        // That would delete reference to lookup dataset and in the future the system will not generate unexpected errors related to incorrect data in excluded column
        foreach ($callcontext->changeAction->excludedColumns as $excludedColumn) {
            $originalLogicalColumn = $originalLogicalDataset->getColumn($excludedColumn->name);
            if ($originalLogicalColumn->type->getReferencedDatasetName() == NULL) {
                continue;
            }

            if (!isset($callcontext->changeAction->updatedDataTypeExcludedColumns[$excludedColumn->name])) {
                $callcontext->changeAction->updatedDataTypeExcludedColumns[$excludedColumn->name] = $excludedColumn;
            }
        }
    }
 public function prepareDimension(MetaModel $metamodel, DatasetMetaData $dataset, $columnName, CubeMetaData $cube)
 {
     $column = $dataset->getColumn($columnName);
     $sourceDatasetColumn = $cube->sourceDataset->getColumn($columnName);
     $dimension = $cube->getDimension($columnName);
     $this->prepareYearLevel($dimension, $column);
     // cube source dataset column contains a reference to year identifier
     $sourceDatasetColumn->initializeTypeFrom(Sequence::getSequenceColumnType());
     // adding a reference to date dataset
     $referenceName = DateDimensionDatasetNames::LEVEL_YEARS;
     $metamodel->registerSimpleReferencePoint($referenceName, DateDimensionDatasetNames::LEVEL_YEARS, 'year_id');
     $metamodel->registerSimpleReferencePoint($referenceName, $cube->sourceDatasetName, $columnName);
 }
    public function prepareDimension(MetaModel $metamodel, DatasetMetaData $dataset, $columnName, CubeMetaData $cube) {
        $logicalColumn = $dataset->getColumn($columnName);
        $column = $cube->factsDataset->getColumn($columnName);
        $dimension = $cube->getDimension($columnName);

        // preparing the dimension properties
        $dimension->attributeColumnName = $columnName;
        $dimension->setDatasetName(StarSchemaNamingConvention::getAttributeRelatedName($dataset->name, $columnName));

        // preparing dimension dataset
        $dimension->dataset = new DatasetMetaData();
        $dimension->dataset->name = $dimension->datasetName;
        $dimension->dataset->publicName = $dataset->publicName . " [$logicalColumn->publicName]";
        $dimension->dataset->description = t("Lookup table to store unique values from '@columnName' column", array('@columnName' => $logicalColumn->publicName));
        $dimension->dataset->datasourceName = $dataset->datasourceName;
        $dimension->dataset->source = StarSchemaNamingConvention::getAttributeRelatedName($dataset->source, $columnName);
        $dimension->dataset->markAsPrivate();
        // adding dimension dataset aliases
        if (isset($dataset->aliases)) {
            foreach ($dataset->aliases as $alias) {
                $dimension->dataset->aliases[] = StarSchemaNamingConvention::getAttributeRelatedName($alias, $columnName);
            }
        }

        // adding key column
        $keyColumn = $dimension->dataset->registerColumn($columnName);
        $keyColumn->publicName = $logicalColumn->publicName;
        $keyColumn->description = t("System generated ID to identify each unique value from '@columnName' column", array('@columnName' => $logicalColumn->publicName));
        $keyColumn->initializeTypeFrom(Sequence::getSequenceColumnType());
        $keyColumn->key = TRUE;
        $keyColumn->visible = FALSE;
        
        // adding 'value' column
        $valueColumn = $dimension->dataset->registerColumn('value');
        $valueColumn->publicName = $logicalColumn->publicName;
        $valueColumn->description = t("Actual value from '@columnName' column", array('@columnName' => $logicalColumn->publicName));
        $valueColumn->initializeTypeFrom($logicalColumn->type);

        // facts dataset column contains a reference to lookup
        $column->initializeTypeFrom(Sequence::getSequenceColumnType());
        $column->type->logicalApplicationType = StringDataTypeHandler::DATA_TYPE;

        // marking that the dimension dataset object contains complete meta data & registering it in meta model
        $dimension->dataset->markAsComplete();
        $metamodel->registerDataset($dimension->dataset);

        // adding a reference to the dimension dataset
        $referenceName = $dimension->datasetName;
        $metamodel->registerSimpleReferencePoint($referenceName, $dimension->datasetName, $columnName);
        $metamodel->registerSimpleReferencePoint($referenceName, $cube->factsDatasetName, $columnName);
    }
    public function dropColumnStorage(DataControllerCallContext $callcontext, DataSourceStructureHandler $datasourceStructureHandler, DatasetMetaData $dataset, $columnName, $stage) {
        if ($stage == DatasetStorageObserver::STAGE__AFTER) {
            $environment_metamodel = data_controller_get_environment_metamodel();

            $originalLogicalColumn = $this->originalLogicalDataset->getColumn($columnName);
            $originalColumn = $dataset->getColumn($columnName);

            $datasource = $environment_metamodel->getDataSource($dataset->datasourceName);
            $datasourceQueryHandler = DataSourceQueryFactory::getInstance()->getHandler($datasource->type);

            $generator = new FunctionDateDimensionMetaDataGenerator($datasourceQueryHandler);
            $generator->clean($originalColumn);
            $generator->clean($originalLogicalColumn);
        }

        parent::dropColumnStorage($callcontext, $datasourceStructureHandler, $dataset, $columnName, $stage);
    }
    protected function prepareColumnUIMetaData(array $datasetStack, $referencePath, DatasetMetaData $dataset, $columnName) {
        $column = $dataset->getColumn($columnName);

        $columnUIMetaData = new AttributeUIMetaData();
        $columnUIMetaData->name = self::prepareColumnUIMetaDataName($referencePath, $dataset->name, $column->name);
        $columnUIMetaData->publicName = $column->publicName;
        $columnUIMetaData->description = $column->description;
        $columnUIMetaData->columnIndex = $column->columnIndex;
        $columnUIMetaData->type = clone $column->type;

        list($referencedDatasetName) = ReferencePathHelper::splitReference($column->type->getLogicalApplicationType());
        if (isset($referencedDatasetName)) {
            $metamodel = data_controller_get_metamodel();
            $referencedDataset = $metamodel->getDataset($referencedDatasetName);

            if (!isset($datasetStack[$referencedDataset->name])) {
                $datasetStack[$referencedDataset->name] = TRUE;

                $branchReferencePath = isset($referencePath)
                    ? self::prepareReferencedElementName($referencePath, $dataset->name, $column->name)
                    : ReferencePathHelper::assembleReference($dataset->name, $column->name);

                foreach ($referencedDataset->getColumns() as $referencedColumn) {
                    if (!$referencedColumn->isVisible()) {
                        continue;
                    }

                    $referencedColumnMetaData = $this->prepareColumnUIMetaData($datasetStack, $branchReferencePath, $referencedDataset, $referencedColumn->name);
                    if ($referencedColumn->isKey()) {
                        if (count($referencedColumnMetaData->elements) == 0) {
                            continue;
                        }

                        $referencedColumnMetaData->publicName = $referencedDataset->publicName;
                        $referencedColumnMetaData->description = $referencedDataset->description;
                        $referencedColumnMetaData->isSelectable = FALSE;
                    }

                    $columnUIMetaData->registerElement($referencedColumnMetaData);
                }
            }
        }

        return $columnUIMetaData;
    }
 protected function fixDropPrimaryKeyColumnProblem(DataSourceHandler $handler, DatasetMetaData $dataset, array $originalKeyColumnNames)
 {
     // when a column is used in primary key MySQL creates 'NOT NULL' constraint automatically
     // when the column is excluded from primary key the constraint is not deleted
     // with the following fix we recreate the column without such constraint
     $sql = '';
     foreach ($originalKeyColumnNames as $columnName) {
         $column = $dataset->getColumn($columnName);
         if ($sql != '') {
             $sql .= ', ';
         }
         $sql .= 'MODIFY COLUMN ' . $this->prepareColumnCreateStatement($handler, $column, FALSE);
     }
     return $sql;
 }
    public function prepareDimension(MetaModel $metamodel, DatasetMetaData $dataset, $columnName, CubeMetaData $cube) {
        $column = $dataset->getColumn($columnName);
        $dimension = $cube->getDimension($columnName);

        $dimension->attributeColumnName = $column->name;
    }
    public function dropColumnStorage(DataControllerCallContext $callcontext, DataSourceStructureHandler $datasourceStructureHandler, DatasetMetaData $dataset, $columnName, $stage) {
        if ($stage == DatasetStorageObserver::STAGE__AFTER) {
            $originalColumn = $dataset->getColumn($columnName);

            $node = node_load($this->getColumn_NID($dataset, $columnName));

            $node->field_column_persistence[$node->language][0]['value'] = $originalColumn->persistence;
            $node->status = $originalColumn->isUsed() ? NODE_PUBLISHED : NODE_NOT_PUBLISHED;

            node_save($node);
        }

        parent::dropColumnStorage($callcontext, $datasourceStructureHandler, $dataset, $columnName, $stage);
    }
 public static function deinitializeByColumn(CubeMetaData $cube, DatasetMetaData $dataset, $columnName)
 {
     $metamodel = data_controller_get_metamodel();
     $column = $dataset->getColumn($columnName);
     $handler = DimensionLookupFactory::getInstance()->getHandler($column->type->getLogicalApplicationType());
     $handler->unprepareDimension($metamodel, $dataset, $column->name);
     // removing dimension
     $dimension = $cube->unregisterDimension($columnName);
     // removing measure which counts unique values
     $attributeName = ParameterNameHelper::assemble($dimension->name);
     $measureName = StarSchemaNamingConvention::getAttributeRelatedMeasureName($attributeName, StarSchemaNamingConvention::$MEASURE_NAME_SUFFIX__DISTINCT_COUNT);
     $measure = $cube->findMeasure($measureName);
     if (isset($measure)) {
         $cube->unregisterMeasure($measureName);
     }
     self::deinitializeColumnMeasures($cube, $dataset, $columnName);
 }
    public function dropColumnStorage(DataControllerCallContext $callcontext, DataSourceStructureHandler $datasourceStructureHandler, DatasetMetaData $dataset, $columnName, $stage) {
        if ($stage == DatasetStorageObserver::STAGE__AFTER) {
            $originalLogicalColumn = $this->originalLogicalDataset->getColumn($columnName);
            $originalColumn = $dataset->getColumn($columnName);

            $originalLogicalColumn->persistence = $originalColumn->persistence;
            $originalLogicalColumn->used = $originalColumn->used;

            $handler = DimensionFactory::getInstance()->getHandler($originalLogicalColumn->type->getLogicalApplicationType());
            $handler->dropDimensionStorage($callcontext, $datasourceStructureHandler, $this->originalLogicalDataset, $columnName);
        }

        parent::dropColumnStorage($callcontext, $datasourceStructureHandler, $dataset, $columnName, $stage);
    }
    /**
     * @param DataControllerCallContext $callcontext
     * @param DatasetMetaData $originalDataset
     * @param DatasetMetaData $modifiedDataset
     * @param DatasetStorageObserver[] $observers
     * @throws Exception
     */
    protected function updateProperties(DataControllerCallContext $callcontext, DatasetMetaData $originalDataset, DatasetMetaData $modifiedDataset, array $observers = NULL) {
        $justPersistedColumns = NULL;
        ArrayHelper::merge($justPersistedColumns, $callcontext->changeAction->newIncludedColumns);
        ArrayHelper::merge($justPersistedColumns, $callcontext->changeAction->restoredColumns);
        ArrayHelper::merge($justPersistedColumns, $callcontext->changeAction->updatedDataTypeIncludedColumns);

        $columns = $justPersistedColumns;
        ArrayHelper::merge($columns, $callcontext->changeAction->updatedColumns);
        if ($callcontext->changeAction->isDatasetUpdated || isset($columns) || $callcontext->changeAction->isKeyUpdated) {
            MetaModelFactory::getInstance()->startGlobalModification();
            try {
                $transaction = db_transaction();
                try {
                    if (isset($columns)) {
                        foreach ($columns as $column) {
                            if (isset($justPersistedColumns[$column->name])) {
                                $column->used = TRUE;
                            }

                            if (isset($callcontext->changeAction->updatedColumns[$column->name])) {
                                $modifiedColumn = $modifiedDataset->getColumn($column->name);

                                $column->publicName = $modifiedColumn->publicName;
                                $column->description = $modifiedColumn->description;
                                $column->source = $modifiedColumn->source;
                                $column->key = $modifiedColumn->key;
                            }

                            if (isset($observers)) {
                                foreach ($observers as $observer) {
                                    $observer->updateColumn($callcontext, $originalDataset, $column->name);
                                }
                            }
                        }
                    }

                    if ($callcontext->changeAction->isDatasetUpdated) {
                        $originalDataset->publicName = $modifiedDataset->publicName;
                        $originalDataset->description = $modifiedDataset->description;
                        $originalDataset->initializeSourceFrom($modifiedDataset->source, TRUE);
                        $originalDataset->initializeAliasesFrom($modifiedDataset->aliases, TRUE);

                        if (isset($observers)) {
                            foreach ($observers as $observer) {
                                $observer->updateDataset($callcontext, $originalDataset);
                            }
                        }
                    }

                    if ($callcontext->changeAction->isKeyUpdated) {
                        $modifiedDatasetKeyColumnNames = $modifiedDataset->findKeyColumnNames();
                        if (isset($modifiedDatasetKeyColumnNames)) {
                            $this->executeDatasetUpdateOperations(
                                $callcontext,
                                $originalDataset,
                                array(new CreateDatasetKeyOperation()));
                        }
                    }
                }
                catch (Exception $e) {
                    $transaction->rollback();
                    throw $e;
                }
            }
            catch (Exception $e) {
                MetaModelFactory::getInstance()->finishGlobalModification(FALSE);
                throw $e;
            }
            MetaModelFactory::getInstance()->finishGlobalModification(TRUE);
        }
    }
    protected function prepareTableUpdateOperation(DataSourceHandler $handler, DataControllerCallContext $callcontext, DatasetMetaData $dataset, AbstractDatasetStorageOperation $operation, $indent, &$sql) {
        $classname = get_class($operation);
        switch ($classname) {
            case 'CreateColumnOperation':
                $column = $dataset->getColumn($operation->columnName);
                $sql .= "\n{$indent}ADD " . $this->prepareColumnCreateStatement($handler, $column, FALSE);
                break;
            case 'DropColumnOperation':
                $sql .= "\n{$indent}" . $this->prepareColumnDeleteStatement($handler, $dataset, $operation->columnName);
                break;
            case 'CreateColumnReferenceOperation':
                $referencedDataset = DatasetSourceTypeFactory::getInstance()->getTableDataset($operation->referencedDatasetName);

                $referencedTableName = $referencedDataset->source;
                $referencedColumnName = $referencedDataset->getKeyColumn()->name;

                $sql .= "\n{$indent}ADD " . $this->prepareForeignKeyCreateStatement($handler, $dataset, $operation->columnName, $referencedTableName, $referencedColumnName);
                break;
            case 'DropColumnReferenceOperation':
                $sql .= "\n{$indent}" . $this->prepareForeignKeyDeleteStatement($handler, $dataset, $operation->columnName);
                break;
            case 'CreateDatasetKeyOperation':
                $this->allowPrimaryKeyCreation($handler, $callcontext, $dataset);

                $statement = $this->preparePrimaryKeyCreateStatement4Update($handler, $dataset);
                if (isset($statement)) {
                    $sql .= "\n{$indent}{$statement}";
                }
                break;
            case 'DropDatasetKeyOperation':
                $sql .= "\n{$indent}" . $this->preparePrimaryKeyDeleteStatement($handler, $dataset, $operation->originalKeyColumnNames);
                break;
            default:
                throw new IllegalArgumentException(t('Unsupported dataset update operation: %classname', array('%classname' => $classname)));
        }
    }