protected function gatherChanges(DataControllerCallContext $callcontext, DatasetMetaData $originalDataset, DatasetMetaData $modifiedDataset, array $observers = NULL) {
        foreach ($modifiedDataset->getColumns(FALSE) as $modifiedColumn) {
            $originalColumn = $originalDataset->findColumn($modifiedColumn->name);
            if (!isset($originalColumn)) {
                // preparing new included & excluded columns
                if ($modifiedColumn->isUsed()) {
                    $callcontext->changeAction->newIncludedColumns[$modifiedColumn->name] = $modifiedColumn;
                }
                else {
                    $callcontext->changeAction->newExcludedColumns[$modifiedColumn->name] = $modifiedColumn;
                }

                // checking if new column marked as part of primary key
                if ($modifiedColumn->isKey()) {
                    $callcontext->changeAction->isKeyUpdated = TRUE;
                }
            }
        }

        foreach ($originalDataset->getColumns(FALSE) as $originalColumn) {
            $modifiedColumn = $modifiedDataset->findColumn($originalColumn->name);
            if (isset($modifiedColumn)) {
                $isColumnUpdated = FALSE;

                // preparing restored columns
                if (!$originalColumn->isUsed() && $modifiedColumn->isUsed()) {
                    $callcontext->changeAction->restoredColumns[$originalColumn->name] = $originalColumn;
                }

                // preparing excluded columns
                if ($originalColumn->isUsed() && !$modifiedColumn->isUsed()) {
                    $callcontext->changeAction->excludedColumns[$originalColumn->name] = $originalColumn;
                    // excluding a column which is part of primary key
                    if ($originalColumn->isKey()) {
                        $callcontext->changeAction->isKeyUpdated = TRUE;
                    }
                }

                // preparing relocated columns
                if ($originalColumn->columnIndex != $modifiedColumn->columnIndex) {
                    $callcontext->changeAction->updatedIndexColumns[$originalColumn->name] = $originalColumn;
                }

                // preparing columns with changed data type
                if (($originalColumn->type->applicationType != $modifiedColumn->type->applicationType)
                        || ($originalColumn->type->getLogicalApplicationType() != $modifiedColumn->type->getLogicalApplicationType())) {
                    // marking that the column data type was updated
                    if ($modifiedColumn->isUsed()) {
                        $callcontext->changeAction->updatedDataTypeIncludedColumns[$originalColumn->name] = $originalColumn;
                        // updating type a column which is part of the primary key
                        if ($originalColumn->isKey()) {
                            $callcontext->changeAction->isKeyUpdated = TRUE;
                        }
                    }
                    else {
                        $callcontext->changeAction->updatedDataTypeExcludedColumns[$originalColumn->name] = $originalColumn;
                    }
                    // checking if old & new types are compatible
                    if ($this->checkIfDataTypeCompatible($originalColumn->type, $modifiedColumn->type)) {
                        $callcontext->changeAction->updatedDataTypeCompatibleColumns[$originalColumn->name] = $originalColumn;
                    }

                    $isColumnUpdated = TRUE;
                }

                // checking if any column properties were updated
                if (($originalColumn->publicName != $modifiedColumn->publicName)
                        || ($originalColumn->description != $modifiedColumn->description)
                        || ($originalColumn->source != $modifiedColumn->source)) {
                    $isColumnUpdated = TRUE;
                }

                // checking if a column in primary key was added or removed
                if ($originalColumn->isKey() != $modifiedColumn->isKey()) {
                    $isColumnUpdated = TRUE;
                    $callcontext->changeAction->isKeyUpdated = TRUE;
                }

                // preparing updated columns
                if ($isColumnUpdated) {
                    $callcontext->changeAction->updatedColumns[$originalColumn->name] = $originalColumn;
                }
            }
            else {
                // preparing deleted columns
                $callcontext->changeAction->deletedColumns[$originalColumn->name] = $originalColumn;

                // deleting a column which is part of the primary key
                if ($originalColumn->isKey()) {
                    $callcontext->changeAction->isKeyUpdated = TRUE;
                }
            }
        }

        // preparing updated dataset
        if (($originalDataset->publicName != $modifiedDataset->publicName)
                || ($originalDataset->description != $modifiedDataset->description)
                || (compare_values($originalDataset->source, $modifiedDataset->source) != 0)
                || (compare_values($originalDataset->aliases, $modifiedDataset->aliases) != 0)) {
            $callcontext->changeAction->isDatasetUpdated = TRUE;
        }
    }