/*
* 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.tools.transfer.database;
import org.eclipse.jface.operation.IRunnableContext;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.model.*;
import org.jkiss.dbeaver.model.data.DBDDataReceiver;
import org.jkiss.dbeaver.model.exec.DBCAttributeMetaData;
import org.jkiss.dbeaver.model.exec.DBCException;
import org.jkiss.dbeaver.model.exec.DBCResultSet;
import org.jkiss.dbeaver.model.exec.DBCSession;
import org.jkiss.dbeaver.model.impl.AbstractExecutionSource;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.runtime.VoidProgressMonitor;
import org.jkiss.dbeaver.model.struct.*;
import org.jkiss.dbeaver.ui.UIUtils;
import org.jkiss.utils.CommonUtils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* DatabaseMappingContainer
*/
class DatabaseMappingContainer implements DatabaseMappingObject {
private DatabaseConsumerSettings settings;
private DBSDataContainer source;
private DBSDataManipulator target;
private String targetName;
private DatabaseMappingType mappingType;
private List<DatabaseMappingAttribute> attributeMappings = new ArrayList<>();
public DatabaseMappingContainer(DatabaseConsumerSettings settings, DBSDataContainer source)
{
this.settings = settings;
this.source = source;
this.mappingType = DatabaseMappingType.unspecified;
}
public DatabaseMappingContainer(IRunnableContext context, DatabaseConsumerSettings settings, DBSDataContainer sourceObject, DBSDataManipulator targetObject) throws DBException
{
this.settings = settings;
this.source = sourceObject;
this.target = targetObject;
refreshMappingType(context, DatabaseMappingType.existing);
}
public DatabaseConsumerSettings getSettings() {
return settings;
}
@Override
public DBSDataManipulator getTarget()
{
return target;
}
public void setTarget(DBSDataManipulator target)
{
this.target = target;
}
@Override
public DatabaseMappingType getMappingType()
{
return mappingType;
}
void refreshMappingType(IRunnableContext context, DatabaseMappingType mappingType) throws DBException
{
this.mappingType = mappingType;
final Collection<DatabaseMappingAttribute> mappings = getAttributeMappings(context);
if (!CommonUtils.isEmpty(mappings)) {
for (DatabaseMappingAttribute attr : mappings) {
attr.updateMappingType(new VoidProgressMonitor());
}
}
}
void setMappingType(DatabaseMappingType mappingType)
{
this.mappingType = mappingType;
}
public boolean isCompleted()
{
if (mappingType == DatabaseMappingType.skip) {
return true;
}
for (DatabaseMappingAttribute attr : attributeMappings) {
if (attr.getMappingType() == DatabaseMappingType.unspecified) {
return false;
}
}
return true;
}
@Override
public DBPImage getIcon()
{
return DBIcon.TREE_TABLE;
}
@Override
public DBSDataContainer getSource()
{
return source;
}
@Override
public String getTargetName()
{
switch (mappingType) {
case existing: return target.getName();
case create: return targetName;
case skip: return DatabaseMappingAttribute.TARGET_NAME_SKIP;
default: return "?";
}
}
public void setTargetName(String targetName)
{
this.targetName = targetName;
}
public DatabaseMappingAttribute getAttributeMapping(DBSAttributeBase sourceAttr)
{
for (DatabaseMappingAttribute attr : attributeMappings) {
if (attr.getSource().getName().equalsIgnoreCase(sourceAttr.getName())) {
return attr;
}
}
return null;
}
public Collection<DatabaseMappingAttribute> getAttributeMappings(IRunnableContext runnableContext)
{
if (attributeMappings.isEmpty()) {
try {
// Do not use runnable context! It changes active focus and locks UI which breakes whole jface editing framework
readAttributes(new VoidProgressMonitor());
} catch (DBException e) {
UIUtils.showErrorDialog(null, "Attributes read failed", "Can't get attributes from " + DBUtils.getObjectFullName(source, DBPEvaluationContext.UI), e);
}
}
return attributeMappings;
}
public Collection<DatabaseMappingAttribute> getAttributeMappings(DBRProgressMonitor monitor)
{
if (attributeMappings.isEmpty()) {
try {
readAttributes(monitor);
} catch (DBException e) {
UIUtils.showErrorDialog(null, "Attributes read failed", "Can't get attributes from " + DBUtils.getObjectFullName(source, DBPEvaluationContext.UI), e);
}
}
return attributeMappings;
}
private void readAttributes(DBRProgressMonitor monitor) throws DBException
{
if (source instanceof DBSEntity) {
for (DBSEntityAttribute attr : CommonUtils.safeCollection(((DBSEntity) source).getAttributes(monitor))) {
if (DBUtils.isHiddenObject(attr)) {
continue;
}
addAttributeMapping(monitor, attr);
}
} else {
// Seems to be a dynamic query. Execute it to get metadata
DBPDataSource dataSource = source.getDataSource();
assert (dataSource != null);
try (DBCSession session = DBUtils.openUtilSession(monitor, dataSource, "Read query meta data")) {
MetadataReceiver receiver = new MetadataReceiver();
source.readData(new AbstractExecutionSource(source, session.getExecutionContext(), this), session, receiver, null, 0, 1, DBSDataContainer.FLAG_NONE);
for (DBCAttributeMetaData attr : receiver.attributes) {
if (DBUtils.isHiddenObject(attr)) {
continue;
}
addAttributeMapping(monitor, attr);
}
}
}
}
private void addAttributeMapping(DBRProgressMonitor monitor, DBSAttributeBase attr) throws DBException
{
DatabaseMappingAttribute mapping = new DatabaseMappingAttribute(this, attr);
mapping.updateMappingType(monitor);
attributeMappings.add(mapping);
}
private static class MetadataReceiver implements DBDDataReceiver {
private List<DBCAttributeMetaData> attributes;
@Override
public void fetchStart(DBCSession session, DBCResultSet resultSet, long offset, long maxRows) throws DBCException
{
attributes = resultSet.getMeta().getAttributes();
}
@Override
public void fetchRow(DBCSession session, DBCResultSet resultSet) throws DBCException
{
}
@Override
public void fetchEnd(DBCSession session, DBCResultSet resultSet) throws DBCException
{
}
@Override
public void close()
{
}
}
}