/* * 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.wizard; import org.eclipse.jface.dialogs.DialogSettings; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.operation.IRunnableContext; import org.eclipse.jface.wizard.IWizardPage; import org.jkiss.code.Nullable; import org.jkiss.dbeaver.DBException; import org.jkiss.dbeaver.Log; import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor; import org.jkiss.dbeaver.registry.transfer.DataTransferNodeDescriptor; import org.jkiss.dbeaver.registry.transfer.DataTransferProcessorDescriptor; import org.jkiss.dbeaver.registry.transfer.DataTransferRegistry; import org.jkiss.dbeaver.tools.transfer.IDataTransferConsumer; import org.jkiss.dbeaver.tools.transfer.IDataTransferNode; import org.jkiss.dbeaver.tools.transfer.IDataTransferProducer; import org.jkiss.dbeaver.tools.transfer.IDataTransferSettings; import org.jkiss.dbeaver.ui.UIUtils; import org.jkiss.utils.ArrayUtils; import org.jkiss.utils.CommonUtils; import java.util.*; /** * DataTransferSettings */ public class DataTransferSettings { private static final Log log = Log.getLog(DataTransferSettings.class); private static final int DEFAULT_THREADS_NUM = 1; public static class NodeSettings { DataTransferNodeDescriptor sourceNode; IDataTransferSettings settings; IWizardPage[] pages; private NodeSettings(DataTransferNodeDescriptor sourceNode) throws DBException { this.sourceNode = sourceNode; this.settings = sourceNode.createSettings(); this.pages = sourceNode.createWizardPages(); } } private List<DataTransferPipe> dataPipes; private DataTransferNodeDescriptor producer; private DataTransferNodeDescriptor consumer; private DataTransferProcessorDescriptor processor; private Map<DataTransferProcessorDescriptor, Map<Object,Object>> processorPropsHistory = new HashMap<>(); private Map<Class, NodeSettings> nodeSettings = new LinkedHashMap<>(); private boolean consumerOptional; private int maxJobCount = DEFAULT_THREADS_NUM; private transient int curPipeNum = 0; public DataTransferSettings(@Nullable IDataTransferProducer[] producers, @Nullable IDataTransferConsumer[] consumers) { dataPipes = new ArrayList<>(); if (!ArrayUtils.isEmpty(producers) && !ArrayUtils.isEmpty(consumers)) { if (producers.length != consumers.length) { throw new IllegalArgumentException("Producers number must match consumers number"); } // Make pipes for (int i = 0; i < producers.length; i++) { dataPipes.add(new DataTransferPipe(producers[i], consumers[i])); } consumerOptional = false; } else if (!ArrayUtils.isEmpty(producers)) { // Make pipes for (IDataTransferProducer source : producers) { dataPipes.add(new DataTransferPipe(source, null)); } // Set default producer Class<? extends IDataTransferProducer> producerType = dataPipes.get(0).getProducer().getClass(); DataTransferNodeDescriptor producerDesc = DataTransferRegistry.getInstance().getNodeByType(producerType); if (producerDesc != null) { selectProducer(producerDesc); consumerOptional = true; } else { UIUtils.showErrorDialog(null, "Can't find producer", "Can't find data propducer descriptor in registry"); } } else if (!ArrayUtils.isEmpty(consumers)) { // Make pipes for (IDataTransferConsumer target : consumers) { dataPipes.add(new DataTransferPipe(null, target)); } // Set default consumer Class<? extends IDataTransferConsumer> consumerType = dataPipes.get(0).getConsumer().getClass(); DataTransferNodeDescriptor consumerDesc = DataTransferRegistry.getInstance().getNodeByType(consumerType); if (consumerDesc != null) { selectConsumer(consumerDesc, null); consumerOptional = false; } else { UIUtils.showErrorDialog(null, "Can't find producer", "Can't find data propducer descriptor in registry"); } } else { throw new IllegalArgumentException("Producers or consumers must be specified"); } Collection<Class<?>> objectTypes = getObjectTypes(); List<DataTransferNodeDescriptor> nodes = new ArrayList<>(); DataTransferRegistry registry = DataTransferRegistry.getInstance(); if (ArrayUtils.isEmpty(producers)) { nodes.addAll(registry.getAvailableProducers(objectTypes)); } else { for (IDataTransferProducer source : producers) { DataTransferNodeDescriptor node = registry.getNodeByType(source.getClass()); if (node != null && !nodes.contains(node)) { nodes.add(node); } } } if (ArrayUtils.isEmpty(consumers)) { nodes.addAll(registry.getAvailableConsumers(objectTypes)); } else { for (IDataTransferConsumer target : consumers) { DataTransferNodeDescriptor node = registry.getNodeByType(target.getClass()); if (node != null && !nodes.contains(node)) { nodes.add(node); this.consumer = node; } } } for (DataTransferNodeDescriptor node : nodes) { addNodeSettings(node); } } private void addNodeSettings(DataTransferNodeDescriptor node) { if (node == null) { return; } Class<? extends IDataTransferNode> nodeClass = node.getNodeClass(); if (nodeSettings.containsKey(nodeClass)) { return; } try { nodeSettings.put(nodeClass, new NodeSettings(node)); } catch (DBException e) { log.error("Can't add node '" + node.getId() + "'", e); } } void addWizardPages(DataTransferWizard wizard) { for (NodeSettings nodeSettings : this.nodeSettings.values()) { if (nodeSettings.pages != null) { for (IWizardPage page : nodeSettings.pages) { wizard.addPage(page); } } } } public boolean isConsumerOptional() { return consumerOptional; } public boolean isPageValid(IWizardPage page) { return isPageValid(page, producer) || isPageValid(page, consumer); } private boolean isPageValid(IWizardPage page, DataTransferNodeDescriptor node) { NodeSettings nodeSettings = node == null ? null : this.nodeSettings.get(node.getNodeClass()); return nodeSettings != null && ArrayUtils.contains(nodeSettings.pages, page); } public Collection<Class<?>> getObjectTypes() { List<DataTransferPipe> dataPipes = getDataPipes(); Set<Class<?>> objectTypes = new HashSet<>(); for (DataTransferPipe transferPipe : dataPipes) { if (transferPipe.getProducer() != null) { objectTypes.add(transferPipe.getProducer().getSourceObject().getClass()); } } return objectTypes; } public IDataTransferSettings getNodeSettings(IWizardPage page) { for (NodeSettings nodeSettings : this.nodeSettings.values()) { if (nodeSettings.pages != null) { for (IWizardPage nodePage : nodeSettings.pages) { if (nodePage == page) { return nodeSettings.settings; } } } } return null; } public IDataTransferSettings getNodeSettings(IDataTransferNode node) { NodeSettings nodeSettings = this.nodeSettings.get(node.getClass()); return nodeSettings == null ? null : nodeSettings.settings; } public Map<Object, Object> getProcessorProperties() { if (processor == null) { throw new IllegalStateException("No processor selected"); } return processorPropsHistory.get(processor); } public void setProcessorProperties(Map<Object, Object> properties) { if (processor == null) { throw new IllegalStateException("No processor selected"); } processorPropsHistory.put(processor, properties); } public List<DataTransferPipe> getDataPipes() { return dataPipes; } public synchronized DataTransferPipe acquireDataPipe(DBRProgressMonitor monitor) { if (curPipeNum >= dataPipes.size()) { // End of transfer // Signal last pipe about it if (!dataPipes.isEmpty()) { dataPipes.get(dataPipes.size() - 1).getConsumer().finishTransfer(monitor, true); } return null; } DataTransferPipe result = dataPipes.get(curPipeNum); curPipeNum++; return result; } public DataTransferNodeDescriptor getProducer() { return producer; } public DataTransferNodeDescriptor getConsumer() { return consumer; } public DataTransferProcessorDescriptor getProcessor() { return processor; } private void selectProducer(DataTransferNodeDescriptor producer) { this.producer = producer; } void selectConsumer(DataTransferNodeDescriptor consumer, DataTransferProcessorDescriptor processor) { this.consumer = consumer; this.processor = processor; if (consumer != null && processor != null) { if (!processorPropsHistory.containsKey(processor)) { processorPropsHistory.put(processor, new HashMap<>()); } } // Configure pipes for (DataTransferPipe pipe : dataPipes) { if (consumer != null) { try { pipe.setConsumer((IDataTransferConsumer) consumer.createNode()); } catch (DBException e) { log.error(e); pipe.setConsumer(null); } } else { pipe.setConsumer(null); } } } public int getMaxJobCount() { return maxJobCount; } public void setMaxJobCount(int maxJobCount) { if (maxJobCount > 0) { this.maxJobCount = maxJobCount; } } void loadFrom(IRunnableContext runnableContext, IDialogSettings dialogSettings) { try { maxJobCount = dialogSettings.getInt("maxJobCount"); } catch (NumberFormatException e) { maxJobCount = DEFAULT_THREADS_NUM; } String producerId = dialogSettings.get("producer"); if (!CommonUtils.isEmpty(producerId)) { DataTransferNodeDescriptor producerNode = DataTransferRegistry.getInstance().getNodeById(producerId); if (producerNode != null) { this.producer = producerNode; } } if (consumerOptional) { DataTransferNodeDescriptor savedConsumer = null; String consumerId = dialogSettings.get("consumer"); if (!CommonUtils.isEmpty(consumerId)) { DataTransferNodeDescriptor consumerNode = DataTransferRegistry.getInstance().getNodeById(consumerId); if (consumerNode != null) { savedConsumer = consumerNode; } } DataTransferProcessorDescriptor savedProcessor = null; if (savedConsumer != null) { String processorId = dialogSettings.get("processor"); if (!CommonUtils.isEmpty(processorId)) { savedProcessor = savedConsumer.getProcessor(processorId); } } if (savedConsumer != null) { selectConsumer(savedConsumer, savedProcessor); } } // Load nodes' settings for (Map.Entry<Class, NodeSettings> entry : nodeSettings.entrySet()) { IDialogSettings nodeSection = DialogSettings.getOrCreateSection(dialogSettings, entry.getKey().getSimpleName()); entry.getValue().settings.loadSettings(runnableContext, this, nodeSection); } IDialogSettings processorsSection = dialogSettings.getSection("processors"); if (processorsSection != null) { for (IDialogSettings procSection : ArrayUtils.safeArray(processorsSection.getSections())) { String processorId = procSection.getName(); String nodeId = procSection.get("@node"); String propNamesId = procSection.get("@propNames"); DataTransferNodeDescriptor node = DataTransferRegistry.getInstance().getNodeById(nodeId); if (node != null) { Map<Object, Object> props = new HashMap<>(); DataTransferProcessorDescriptor nodeProcessor = node.getProcessor(processorId); if (nodeProcessor != null) { for (String prop : CommonUtils.splitString(propNamesId, ',')) { props.put(prop, procSection.get(prop)); } processorPropsHistory.put(nodeProcessor, props); NodeSettings nodeSettings = this.nodeSettings.get(node.getNodeClass()); if (nodeSettings != null) { } } } } } } void saveTo(IDialogSettings dialogSettings) { dialogSettings.put("maxJobCount", maxJobCount); // Save nodes' settings for (Map.Entry<Class, NodeSettings> entry : nodeSettings.entrySet()) { IDialogSettings nodeSection = DialogSettings.getOrCreateSection(dialogSettings, entry.getKey().getSimpleName()); entry.getValue().settings.saveSettings(nodeSection); } if (producer != null) { dialogSettings.put("producer", producer.getId()); } if (consumer != null) { dialogSettings.put("consumer", consumer.getId()); } if (processor != null) { dialogSettings.put("processor", processor.getId()); } // Save processors' properties IDialogSettings processorsSection = DialogSettings.getOrCreateSection(dialogSettings, "processors"); for (DataTransferProcessorDescriptor procDescriptor : processorPropsHistory.keySet()) { IDialogSettings procSettings = DialogSettings.getOrCreateSection(processorsSection, procDescriptor.getId()); procSettings.put("@node", procDescriptor.getNode().getId()); Map<Object, Object> props = processorPropsHistory.get(procDescriptor); if (props != null) { StringBuilder propNames = new StringBuilder(); for (Map.Entry<Object,Object> prop : props.entrySet()) { propNames.append(prop.getKey()).append(','); } procSettings.put("@propNames", propNames.toString()); for (Map.Entry<Object,Object> prop : props.entrySet()) { procSettings.put(CommonUtils.toString(prop.getKey()), CommonUtils.toString(prop.getValue())); } } } } }