/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
* Copyright (C) 2011-2012 Eugene Fradkin (eugene.fradkin@gmail.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jkiss.dbeaver.ext.postgresql.tools;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.*;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.core.DBeaverUI;
import org.jkiss.dbeaver.ext.postgresql.model.PostgreDataSource;
import org.jkiss.dbeaver.ext.postgresql.model.PostgreSchema;
import org.jkiss.dbeaver.ext.postgresql.model.PostgreTableBase;
import org.jkiss.dbeaver.model.DBIcon;
import org.jkiss.dbeaver.model.DBUtils;
import org.jkiss.dbeaver.model.runtime.AbstractJob;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.runtime.VoidProgressMonitor;
import org.jkiss.dbeaver.model.struct.DBSObject;
import org.jkiss.dbeaver.ui.DBeaverIcons;
import org.jkiss.dbeaver.ui.UIUtils;
import org.jkiss.dbeaver.ui.controls.CustomSashForm;
import org.jkiss.utils.CommonUtils;
import java.util.*;
import java.util.List;
class PostgreBackupWizardPageObjects extends PostgreWizardPageSettings<PostgreBackupWizard>
{
private static final Log log = Log.getLog(PostgreBackupWizardPageObjects.class);
private Table schemasTable;
private Table tablesTable;
private Map<PostgreSchema, Set<PostgreTableBase>> checkedObjects = new HashMap<>();
private PostgreSchema curSchema;
private PostgreDataSource dataSource;
PostgreBackupWizardPageObjects(PostgreBackupWizard wizard)
{
super(wizard, "Schemas/tables");
setTitle("Choose objects to export");
setDescription("Schemas/tables/views which will be exported");
}
@Override
public boolean isPageComplete()
{
return super.isPageComplete();
}
@Override
public void createControl(Composite parent)
{
Composite composite = UIUtils.createPlaceholder(parent, 1);
Group objectsGroup = UIUtils.createControlGroup(composite, "Objects", 1, GridData.FILL_HORIZONTAL, 0);
objectsGroup.setLayoutData(new GridData(GridData.FILL_BOTH));
SashForm sash = new CustomSashForm(objectsGroup, SWT.VERTICAL);
sash.setLayoutData(new GridData(GridData.FILL_BOTH));
{
Composite catPanel = UIUtils.createPlaceholder(sash, 1);
catPanel.setLayoutData(new GridData(GridData.FILL_BOTH));
schemasTable = new Table(catPanel, SWT.BORDER | SWT.CHECK);
schemasTable.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
TableItem item = (TableItem) event.item;
PostgreSchema catalog = (PostgreSchema) item.getData();
if (event.detail == SWT.CHECK) {
schemasTable.select(schemasTable.indexOf(item));
checkedObjects.remove(catalog);
}
loadTables(catalog);
updateState();
}
});
GridData gd = new GridData(GridData.FILL_BOTH);
gd.heightHint = 50;
schemasTable.setLayoutData(gd);
Composite buttonsPanel = UIUtils.createPlaceholder(catPanel, 3, 5);
buttonsPanel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
new Label(buttonsPanel, SWT.NONE).setLayoutData(new GridData(GridData.GRAB_HORIZONTAL));
createCheckButtons(buttonsPanel, schemasTable);
}
final Button exportViewsCheck;
{
Composite tablesPanel = UIUtils.createPlaceholder(sash, 1);
tablesPanel.setLayoutData(new GridData(GridData.FILL_BOTH));
tablesTable = new Table(tablesPanel, SWT.BORDER | SWT.CHECK);
GridData gd = new GridData(GridData.FILL_BOTH);
gd.heightHint = 50;
tablesTable.setLayoutData(gd);
tablesTable.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
if (event.detail == SWT.CHECK) {
updateCheckedTables();
updateState();
}
}
});
Composite buttonsPanel = UIUtils.createPlaceholder(tablesPanel, 3, 5);
buttonsPanel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
exportViewsCheck = UIUtils.createCheckbox(buttonsPanel, "Show views", false);
exportViewsCheck.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
wizard.showViews = exportViewsCheck.getSelection();
loadTables(null);
}
});
exportViewsCheck.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL));
createCheckButtons(buttonsPanel, tablesTable);
}
dataSource = null;
Set<PostgreSchema> activeCatalogs = new LinkedHashSet<>();
for (DBSObject object : wizard.getDatabaseObjects()) {
if (object instanceof PostgreSchema) {
activeCatalogs.add((PostgreSchema) object);
dataSource = ((PostgreSchema) object).getDataSource();
} else if (object instanceof PostgreTableBase) {
PostgreSchema catalog = ((PostgreTableBase) object).getContainer();
dataSource = catalog.getDataSource();
activeCatalogs.add(catalog);
Set<PostgreTableBase> tables = checkedObjects.get(catalog);
if (tables == null) {
tables = new HashSet<>();
checkedObjects.put(catalog, tables);
}
tables.add((PostgreTableBase) object);
if (((PostgreTableBase) object).isView()) {
wizard.showViews = true;
exportViewsCheck.setSelection(true);
}
} else if (object.getDataSource() instanceof PostgreDataSource) {
dataSource = (PostgreDataSource) object.getDataSource();
}
}
if (dataSource != null) {
boolean tablesLoaded = false;
try {
for (PostgreSchema schema : dataSource.getDefaultInstance().getSchemas(new VoidProgressMonitor())) {
if (schema.isSystem() || schema.isUtility()) {
continue;
}
TableItem item = new TableItem(schemasTable, SWT.NONE);
item.setImage(DBeaverIcons.getImage(DBIcon.TREE_DATABASE));
item.setText(0, schema.getName());
item.setData(schema);
if (activeCatalogs.contains(schema)) {
item.setChecked(true);
schemasTable.select(schemasTable.indexOf(item));
if (!tablesLoaded) {
loadTables(schema);
tablesLoaded = true;
}
}
}
} catch (DBException e) {
log.error(e);
}
}
updateState();
setControl(composite);
}
private void updateCheckedTables() {
Set<PostgreTableBase> checkedTables = new HashSet<>();
TableItem[] tableItems = tablesTable.getItems();
for (TableItem item : tableItems) {
if (item.getChecked()) {
checkedTables.add((PostgreTableBase) item.getData());
}
}
TableItem catalogItem = schemasTable.getItem(schemasTable.getSelectionIndex());
catalogItem.setChecked(!checkedTables.isEmpty());
if (checkedTables.isEmpty() || checkedTables.size() == tableItems.length) {
checkedObjects.remove(curSchema);
} else {
checkedObjects.put(curSchema, checkedTables);
}
}
private boolean isChecked(PostgreSchema catalog) {
for (TableItem item : schemasTable.getItems()) {
if (item.getData() == catalog) {
return item.getChecked();
}
}
return false;
}
private void loadTables(final PostgreSchema catalog) {
if (catalog != null) {
curSchema = catalog;
}
if (curSchema == null) {
return;
}
final boolean isCatalogChecked = isChecked(curSchema);
final Set<PostgreTableBase> checkedObjects = this.checkedObjects.get(curSchema);
new AbstractJob("Load '" + curSchema.getName() + "' tables") {
{
setUser(true);
}
@Override
protected IStatus run(DBRProgressMonitor monitor) {
try {
final List<PostgreTableBase> objects = new ArrayList<>();
objects.addAll(curSchema.getTables(monitor));
if (wizard.showViews) {
objects.addAll(curSchema.getViews(monitor));
}
Collections.sort(objects, DBUtils.nameComparator());
DBeaverUI.syncExec(new Runnable() {
@Override
public void run() {
tablesTable.removeAll();
for (PostgreTableBase table : objects) {
TableItem item = new TableItem(tablesTable, SWT.NONE);
item.setImage(DBeaverIcons.getImage(table.isView() ? DBIcon.TREE_VIEW : DBIcon.TREE_TABLE));
item.setText(0, table.getName());
item.setData(table);
item.setChecked(isCatalogChecked && (checkedObjects == null || checkedObjects.contains(table)));
}
}
});
} catch (DBException e) {
UIUtils.showErrorDialog(null, "Table list", "Can't read table list", e);
}
return Status.OK_STATUS;
}
}.schedule();
}
public void saveState() {
wizard.objects.clear();
List<PostgreSchema> schemas = new ArrayList<>();
List<PostgreTableBase> tables = new ArrayList<>();
for (TableItem item : schemasTable.getItems()) {
if (item.getChecked()) {
PostgreSchema schema = (PostgreSchema) item.getData();
Set<PostgreTableBase> checkedTables = checkedObjects.get(schema);
if (CommonUtils.isEmpty(checkedTables)) {
// All tables checked
schemas.add(schema);
} else {
// Only a few tables checked
tables.addAll(checkedTables);
}
}
}
PostgreDatabaseBackupInfo info = new PostgreDatabaseBackupInfo(dataSource.getDefaultInstance(), schemas, tables);
wizard.objects.add(info);
}
private void updateState()
{
boolean complete = false;
if (!checkedObjects.isEmpty()) {
complete = true;
}
for (TableItem item : schemasTable.getItems()) {
if (item.getChecked()) {
complete = true;
break;
}
}
setPageComplete(complete);
}
}