/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
*
* 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.ui.controls.resultset.panel;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IContributionManager;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.viewers.*;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.DBPImage;
import org.jkiss.dbeaver.model.DBValueFormatting;
import org.jkiss.dbeaver.model.data.DBDAttributeBinding;
import org.jkiss.dbeaver.model.data.DBDAttributeBindingMeta;
import org.jkiss.dbeaver.model.exec.DBCExecutionContext;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.runtime.load.DatabaseLoadService;
import org.jkiss.dbeaver.ui.LoadingJob;
import org.jkiss.dbeaver.ui.UIIcon;
import org.jkiss.dbeaver.ui.UIUtils;
import org.jkiss.dbeaver.ui.controls.TreeContentProvider;
import org.jkiss.dbeaver.ui.controls.itemlist.DatabaseObjectListControl;
import org.jkiss.dbeaver.ui.controls.resultset.IResultSetPanel;
import org.jkiss.dbeaver.ui.controls.resultset.IResultSetPresentation;
import org.jkiss.utils.CommonUtils;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
/**
* RSV value view panel
*/
public class MetaDataPanel implements IResultSetPanel {
private static final Log log = Log.getLog(MetaDataPanel.class);
public static final String PANEL_ID = "results-metadata";
private IResultSetPresentation presentation;
private MetaDataTable attributeList;
private List<DBDAttributeBinding> curAttributes;
private Color colorDisabled;
private transient boolean updateSelection = false;
public MetaDataPanel() {
}
@Override
public String getPanelTitle() {
return "MetaData";
}
@Override
public DBPImage getPanelImage() {
return UIIcon.PANEL_METADATA;
}
@Override
public String getPanelDescription() {
return "Resultset metadata";
}
@Override
public Control createContents(final IResultSetPresentation presentation, Composite parent) {
this.presentation = presentation;
this.colorDisabled = presentation.getControl().getDisplay().getSystemColor(SWT.COLOR_WIDGET_DARK_SHADOW);
this.attributeList = new MetaDataTable(parent);
this.attributeList.setFitWidth(false);
this.attributeList.getItemsViewer().addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
DBDAttributeBinding attr = getSelectedAttribute();
if (attr != null && !updateSelection) {
if (isAttributeVisible(attr)) {
updateSelection = true;
try {
presentation.setCurrentAttribute(attr);
} finally {
updateSelection = false;
}
}
}
}
});
if (this.presentation instanceof ISelectionProvider) {
final ISelectionChangedListener listener = new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
if (!updateSelection && MetaDataPanel.this.presentation.getController().getVisiblePanel() == MetaDataPanel.this) {
DBDAttributeBinding attr = presentation.getCurrentAttribute();
if (attr != null && attr != getSelectedAttribute()) {
updateSelection = true;
try {
attributeList.getItemsViewer().setSelection(new StructuredSelection(attr));
} finally {
updateSelection = false;
}
}
}
}
};
((ISelectionProvider) this.presentation).addSelectionChangedListener(listener);
attributeList.getControl().addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent e) {
((ISelectionProvider) presentation).removeSelectionChangedListener(listener);
}
});
}
return this.attributeList;
}
private DBDAttributeBinding getSelectedAttribute() {
IStructuredSelection selection = attributeList.getItemsViewer().getStructuredSelection();
if (!selection.isEmpty()) {
return (DBDAttributeBinding) selection.getFirstElement();
}
return null;
}
private boolean isAttributeVisible(DBDAttributeBinding attr) {
return presentation.getController().getModel().getVisibleAttributes().contains(attr);
}
@Override
public void activatePanel() {
refresh(false);
}
@Override
public void deactivatePanel() {
}
@Override
public void refresh(boolean force) {
if (attributeList.isLoading()) {
return;
}
List<DBDAttributeBinding> newAttributes = Arrays.asList(presentation.getController().getModel().getAttributes());
if (curAttributes != null && curAttributes.size() == newAttributes.size()) {
boolean equals = true;
for (int i = 0; i < curAttributes.size(); i++) {
if (curAttributes.get(i) != newAttributes.get(i)) {
equals = false;
break;
}
}
if (equals) {
// No changes
return;
}
}
curAttributes = newAttributes;
attributeList.clearListData();
attributeList.loadData();
}
@Override
public void contributeActions(ToolBarManager manager) {
}
private class MetaDataTable extends DatabaseObjectListControl<DBDAttributeBinding> {
protected MetaDataTable(Composite parent) {
super(parent, SWT.SHEET, presentation.getController().getSite(), new TreeContentProvider() {
@Override
public Object[] getChildren(Object parentElement) {
List<DBDAttributeBinding> nested = ((DBDAttributeBinding) parentElement).getNestedBindings();
return nested == null ? new Object[0] : nested.toArray(new Object[nested.size()]);
}
@Override
public boolean hasChildren(Object element) {
return !CommonUtils.isEmpty(((DBDAttributeBinding) element).getNestedBindings());
}
});
}
@Override
protected void fillCustomActions(IContributionManager contributionManager) {
contributionManager.add(new Action("Copy column names") {
@Override
public void run() {
StringBuilder text = new StringBuilder();
for (Object item : getItemsViewer().getStructuredSelection().toArray()) {
if (item instanceof DBDAttributeBinding) {
if (text.length() > 0) text.append("\n");
text.append(((DBDAttributeBinding) item).getName());
}
}
UIUtils.setClipboardContents(getDisplay(), TextTransfer.getInstance(), text.toString());
}
});
}
@NotNull
@Override
protected String getListConfigId(List<Class<?>> classList) {
final DBCExecutionContext executionContext = presentation.getController().getExecutionContext();
if (executionContext == null) {
return "MetaData";
}
return "MetaData/" + executionContext.getDataSource().getContainer().getDriver().getId();
}
@Override
protected Object getObjectValue(DBDAttributeBinding item) {
if (item instanceof DBDAttributeBindingMeta) {
return item.getMetaAttribute();
} else {
return item.getAttribute();
}
}
@Nullable
@Override
protected DBPImage getObjectImage(DBDAttributeBinding item) {
return DBValueFormatting.getObjectImage(item.getMetaAttribute());
}
@Override
protected Color getObjectForeground(DBDAttributeBinding item) {
if (item.getParentObject() == null && !isAttributeVisible(item)) {
return colorDisabled;
}
return super.getObjectForeground(item);
}
@Override
protected LoadingJob<Collection<DBDAttributeBinding>> createLoadService() {
return LoadingJob.createService(
new LoadAttributesService(),
new ObjectsLoadVisualizer()
{
@Override
public void completeLoading(Collection<DBDAttributeBinding> items) {
super.completeLoading(items);
((TreeViewer)attributeList.getItemsViewer()).expandToLevel(2);
}
});
}
}
private class LoadAttributesService extends DatabaseLoadService<Collection<DBDAttributeBinding>> {
protected LoadAttributesService()
{
super("Load sessions", presentation.getController().getExecutionContext());
}
@Override
public Collection<DBDAttributeBinding> evaluate(DBRProgressMonitor monitor)
throws InvocationTargetException, InterruptedException
{
return curAttributes;
}
}
}