org.talend.repository.nosql.ui.common.AbstractNoSQLRetrieveSchemaForm.java Source code

Java tutorial

Introduction

Here is the source code for org.talend.repository.nosql.ui.common.AbstractNoSQLRetrieveSchemaForm.java

Source

// ============================================================================
//
// Copyright (C) 2006-2016 Talend Inc. - www.talend.com
//
// This source code is available under agreement available at
// %InstallDIR%\features\org.talend.rcp.branding.%PRODUCTNAME%\%PRODUCTNAME%license.txt
//
// You should have received a copy of the agreement
// along with this program; if not, write to Talend SA
// 9 rue Pages 92150 Suresnes, France
//
// ============================================================================
package org.talend.repository.nosql.ui.common;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.commons.lang.StringUtils;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.TreeColumnLayout;
import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.dialogs.ContainerCheckedTreeViewer;
import org.eclipse.ui.dialogs.SearchPattern;
import org.talend.commons.exception.ExceptionHandler;
import org.talend.commons.ui.swt.formtools.Form;
import org.talend.commons.ui.swt.formtools.LabelledText;
import org.talend.core.model.metadata.MetadataToolHelper;
import org.talend.core.model.metadata.builder.connection.MetadataTable;
import org.talend.core.model.properties.ConnectionItem;
import org.talend.repository.nosql.exceptions.NoSQLExtractSchemaException;
import org.talend.repository.nosql.factory.NoSQLRepositoryFactory;
import org.talend.repository.nosql.i18n.Messages;
import org.talend.repository.nosql.metadata.IMetadataProvider;
import org.talend.repository.nosql.metadata.NoSQLSchemaUtil;
import org.talend.repository.nosql.model.ENoSQLSchemaType;
import org.talend.repository.nosql.model.INoSQLSchemaNode;
import org.talend.repository.nosql.ui.provider.IWizardPageProvider;
import org.talend.repository.nosql.ui.provider.NoSQLSelectorTreeViewerProvider;
import org.talend.repository.nosql.ui.thread.RetrieveColumnRunnable;
import org.talend.repository.nosql.ui.thread.RetrieveSchemaThreadPoolExecutor;
import org.talend.repository.nosql.util.NoSQLRepositoryUtil;

/**
 * created by ycbai on 2014-6-17 Detailled comment
 * 
 */
public abstract class AbstractNoSQLRetrieveSchemaForm extends AbstractNoSQLForm {

    private ContainerCheckedTreeViewer schemaViewer;

    private Tree schemaTree;

    private LabelledText filterText;

    protected IWizardPageProvider wizardPageProvider;

    protected IMetadataProvider metadataProvider;

    // Store the added or updated tables.
    protected Map<String, MetadataTable> hitTablesMap = new ConcurrentHashMap<String, MetadataTable>();

    private static final int NTHREDS = 10;

    private RetrieveSchemaThreadPoolExecutor retrieveSchemaExecutor;

    protected AbstractNoSQLRetrieveSchemaForm(Composite parent, ConnectionItem connectionItem,
            String[] existingNames, boolean creation, WizardPage parentWizardPage) {
        super(parent, connectionItem, existingNames, creation, parentWizardPage);
        wizardPageProvider = NoSQLRepositoryFactory.getInstance()
                .getWizardPageProvider(getConnection().getDbType());
        metadataProvider = NoSQLRepositoryFactory.getInstance().getMetadataProvider(getConnection().getDbType());
    }

    protected void addSchemaFields(Composite parent) {
        Group schemaGroup = Form.createGroup(parent, 1,
                Messages.getString("AbstractNoSQLRetrieveSchemaForm.schemaGroup")); //$NON-NLS-1$

        Composite filterComposite = new Composite(schemaGroup, SWT.NONE);
        GridLayout gridLayout = new GridLayout(2, false);
        filterComposite.setLayout(gridLayout);
        GridData filterCompGridData = new GridData(GridData.FILL_HORIZONTAL);
        filterComposite.setLayoutData(filterCompGridData);
        filterText = new LabelledText(filterComposite,
                Messages.getString("AbstractNoSQLRetrieveSchemaForm.nameFilter"), 1); //$NON-NLS-1$

        ScrolledComposite scrolledComposite = new ScrolledComposite(schemaGroup,
                SWT.H_SCROLL | SWT.V_SCROLL | SWT.NONE);
        scrolledComposite.setExpandHorizontal(true);
        scrolledComposite.setExpandVertical(true);
        scrolledComposite.setLayoutData(new GridData(GridData.FILL_BOTH));

        schemaViewer = new ContainerCheckedTreeViewer(scrolledComposite,
                SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.FULL_SELECTION) {

            @Override
            protected void doCheckStateChanged(Object element) {
                super.doCheckStateChanged(element);
                performCheckStateChanged((INoSQLSchemaNode) element);
            }
        };
        schemaViewer.getControl().setLayoutData(new GridData(GridData.FILL_BOTH));
        schemaViewer.setUseHashlookup(true);
        schemaViewer.addFilter(new SchemaViewerFilter());
        schemaTree = schemaViewer.getTree();
        schemaTree.setHeaderVisible(true);
        schemaTree.setLinesVisible(true);

        scrolledComposite.setContent(schemaTree);
        scrolledComposite.setMinSize(schemaTree.computeSize(SWT.DEFAULT, SWT.DEFAULT));

        TreeColumnLayout tcLayout = new TreeColumnLayout();
        scrolledComposite.setLayout(tcLayout);

        TreeColumn column1 = new TreeColumn(schemaTree, SWT.LEFT);
        column1.setText(Messages.getString("AbstractNoSQLRetrieveSchemaForm.name")); //$NON-NLS-1$
        column1.setWidth(300);
        column1.setResizable(true);
        tcLayout.setColumnData(column1, new ColumnWeightData(40, 150));

        TreeColumn column2 = new TreeColumn(schemaTree, SWT.LEFT);
        column2.setText(Messages.getString("AbstractNoSQLRetrieveSchemaForm.type")); //$NON-NLS-1$
        column2.setWidth(150);
        column2.setResizable(true);
        tcLayout.setColumnData(column2, new ColumnWeightData(25, 100));

        TreeColumn column3 = new TreeColumn(schemaTree, SWT.LEFT);
        column3.setText(Messages.getString("AbstractNoSQLRetrieveSchemaForm.colNum")); //$NON-NLS-1$
        column3.setWidth(130);
        column3.setResizable(true);
        tcLayout.setColumnData(column3, new ColumnWeightData(20, 50));

        TreeColumn column4 = new TreeColumn(schemaTree, SWT.LEFT);
        column4.setText(Messages.getString("AbstractNoSQLRetrieveSchemaForm.creationStauts")); //$NON-NLS-1$
        column4.setWidth(120);
        column4.setResizable(true);
        tcLayout.setColumnData(column4, new ColumnWeightData(15, 70));

        try {
            List<INoSQLSchemaNode> nodes = wizardPageProvider.createSchemaNodes(getConnection());
            NoSQLSelectorTreeViewerProvider viewProvider = new NoSQLSelectorTreeViewerProvider();
            schemaViewer.setContentProvider(viewProvider);
            schemaViewer.setLabelProvider(viewProvider);
            schemaViewer.setInput(nodes);
        } catch (NoSQLExtractSchemaException e) {
            ExceptionHandler.process(e);
        }
    }

    @Override
    protected void initialize() {
        super.initialize();
        restoreCheckItems();
        retrieveSchemaExecutor = new RetrieveSchemaThreadPoolExecutor(NTHREDS,
                new ThreadPoolExecutor.CallerRunsPolicy());
    }

    public void restoreCheckItems() {
        Map<TreeItem, AtomicInteger> checkedDBMap = new HashMap<TreeItem, AtomicInteger>();
        TreeItem[] items = schemaTree.getItems();
        for (TreeItem treeItem : items) {
            udpateItemsStatus(treeItem, checkedDBMap);
        }
        Iterator<Entry<TreeItem, AtomicInteger>> iter = checkedDBMap.entrySet().iterator();
        while (iter.hasNext()) {
            Entry<TreeItem, AtomicInteger> entry = iter.next();
            TreeItem item = entry.getKey();
            AtomicInteger count = entry.getValue();
            if (count.intValue() == 0 && item.getData() != null) {
                schemaViewer.collapseToLevel(item.getData(), 1);
            }
        }
    }

    private void udpateItemsStatus(TreeItem treeItem, Map<TreeItem, AtomicInteger> checkedDBMap) {
        Object data = treeItem.getData();
        if (treeItem != null && data != null) {
            INoSQLSchemaNode node = (INoSQLSchemaNode) treeItem.getData();
            ENoSQLSchemaType schemaType = node.getSchemaType();
            if (ENoSQLSchemaType.DATABASE.equals(schemaType)) {
                AtomicInteger checkedCount = checkedDBMap.get(treeItem);
                if (checkedCount == null) {
                    checkedDBMap.put(treeItem, new AtomicInteger(0));
                }
                schemaViewer.expandToLevel(node, 1);
                for (TreeItem item : treeItem.getItems()) {
                    udpateItemsStatus(item, checkedDBMap);
                }
            } else if (ENoSQLSchemaType.TABLE.equals(schemaType)) {
                boolean existTable = isExistTable(node, true);
                if (!existTable) {
                    clearItemStatus(node);
                }
                schemaViewer.setChecked(node, existTable);
                if (treeItem.getChecked()) {
                    TreeItem dbItem = getDBItem(treeItem);
                    if (dbItem != null) {
                        AtomicInteger checkedCount = checkedDBMap.get(dbItem);
                        if (checkedCount != null) {
                            checkedCount.incrementAndGet();
                        }
                    }
                }
            }
        }
    }

    private TreeItem getDBItem(TreeItem treeItem) {
        if (treeItem == null || treeItem.getData() == null) {
            return null;
        }
        INoSQLSchemaNode node = (INoSQLSchemaNode) treeItem.getData();
        ENoSQLSchemaType schemaType = node.getSchemaType();
        if (ENoSQLSchemaType.DATABASE.equals(schemaType)) {
            return treeItem;
        } else {
            return getDBItem(treeItem.getParentItem());
        }
    }

    public Map<String, MetadataTable> getAddedOrUpdatedTables() {
        return hitTablesMap;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.talend.repository.nosql.ui.common.AbstractNoSQLForm#addFieldsListeners()
     */
    @Override
    protected void addFieldsListeners() {
        filterText.addModifyListener(new ModifyListener() {

            @Override
            public void modifyText(ModifyEvent e) {
                schemaViewer.refresh();
            }
        });
        schemaTree.addListener(SWT.Expand, new Listener() {

            @Override
            public void handleEvent(Event event) {
                TreeItem treeItem = (TreeItem) event.item;
                for (TreeItem item : treeItem.getItems()) {
                    if (item.getData() != null) {
                        INoSQLSchemaNode node = (INoSQLSchemaNode) item.getData();
                        if (node != null && node.getSchemaType() == ENoSQLSchemaType.TABLE) {
                            if (isExistTable(node, true)) {
                                item.setChecked(true);
                            } else {
                                item.setChecked(false);
                            }
                        } else {
                            item.setGrayed(item.getChecked());
                        }
                    }
                }
            }
        });
        schemaTree.addSelectionListener(new SelectionAdapter() {

            @Override
            public void widgetSelected(SelectionEvent e) {
                if (e.detail == SWT.CHECK) {
                    try {
                        TreeItem item = (TreeItem) e.item;
                        boolean checked = item.getChecked();
                        retrieving(item, checked);
                    } catch (Exception exception) {
                        ExceptionHandler.process(exception);
                    }
                }
            }
        });
    }

    protected void performCheckStateChanged(INoSQLSchemaNode node) {
        schemaViewer.refresh(node);
    }

    private void retrieving(TreeItem item, boolean checked) {
        if (item.getItemCount() > 0) {
            schemaViewer.expandToLevel(item.getData(), AbstractTreeViewer.ALL_LEVELS);
            TreeItem[] childrenItems = item.getItems();
            for (TreeItem childItem : childrenItems) {
                childItem.setChecked(checked);
                retrieving(childItem, checked);
            }
        } else {
            INoSQLSchemaNode node = (INoSQLSchemaNode) item.getData();
            if (node != null && node.getSchemaType() == ENoSQLSchemaType.TABLE) {
                if (checked) {
                    addTable(item);
                } else {
                    deleteTable(item);
                }
            }
        }
    }

    private boolean isExistTable(INoSQLSchemaNode node, boolean inCurrentDB) {
        if (node != null && node.getSchemaType() == ENoSQLSchemaType.TABLE) {
            return getTable(node, inCurrentDB) != null;
        }
        return false;
    }

    private MetadataTable getTable(INoSQLSchemaNode node, boolean inCurrentDB) {
        if (inCurrentDB) {
            return NoSQLSchemaUtil.getTableByLabel(getConnection(), node.getName(),
                    NoSQLRepositoryUtil.getDBName(node));
        } else {
            return NoSQLSchemaUtil.getTableByLabel(getConnection(), node.getName(), null);
        }

    }

    private void deleteTable(TreeItem item) {
        INoSQLSchemaNode node = (INoSQLSchemaNode) item.getData();
        if (node != null && node.getSchemaType() == ENoSQLSchemaType.TABLE) {
            String tableName = MetadataToolHelper.validateTableName(node.getName());
            NoSQLSchemaUtil.removeTableFromConnection(getConnection(), tableName,
                    NoSQLRepositoryUtil.getDBName(node));
            hitTablesMap.remove(tableName);
            clearItemStatus(node);
            RetrieveColumnRunnable runnable = retrieveSchemaExecutor.getRunnable(node);
            if (runnable != null) {
                runnable.setCanceled(true);
            }
            schemaViewer.refresh(node);
        }
    }

    private void clearItemStatus(INoSQLSchemaNode node) {
        node.setRetrieved(false);
        node.setColNum(0);
        node.setStatus(INoSQLSchemaNode.EMPTY_STR);
    }

    private void addTable(TreeItem item) {
        INoSQLSchemaNode node = (INoSQLSchemaNode) item.getData();
        if (isExistTable(node, false)) {
            MetadataTable table = getTable(node, false);
            orgomg.cwm.objectmodel.core.Package pack = (orgomg.cwm.objectmodel.core.Package) table.eContainer();
            boolean confirm = MessageDialog.openConfirm(Display.getDefault().getActiveShell(),
                    Messages.getString("AbstractNoSQLRetrieveSchemaForm.confirm"), //$NON-NLS-1$
                    Messages.getString("AbstractNoSQLRetrieveSchemaForm.ConfirmMessage", pack.getName())); //$NON-NLS-1$
            if (confirm) {
                TreeItem existItem = getExistItem(table);
                if (existItem != null) {
                    existItem.setChecked(false);
                    deleteTable(existItem);
                }
            } else {
                item.setChecked(false);
                return;
            }
        }
        if (!retrieveSchemaExecutor.isThreadRunning(node) && node.getSchemaType() == ENoSQLSchemaType.TABLE) {
            RetrieveColumnRunnable runnable = new RetrieveColumnRunnable(metadataProvider, getConnection(), node,
                    hitTablesMap) {

                @Override
                protected void refresh(INoSQLSchemaNode schemaNode) {
                    refreshTable(schemaNode);
                }
            };
            retrieveSchemaExecutor.execute(runnable);
        }
    }

    private void refreshTable(final INoSQLSchemaNode node) {
        Display.getDefault().syncExec(new Runnable() {

            @Override
            public void run() {
                if (!retrieveSchemaExecutor.isThreadRunning(node)) {
                    return;
                }
                schemaViewer.refresh(node);
                parentWizardPage.setPageComplete(!retrieveSchemaExecutor.hasThreadRunning());
            }
        });

    }

    /*
     * (non-Javadoc)
     * 
     * @see org.talend.repository.nosql.ui.common.AbstractNoSQLForm#addUtilsButtonListeners()
     */
    @Override
    protected void addUtilsButtonListeners() {
        super.addUtilsButtonListeners();
        if (schemaTree != null) {
            schemaTree.addSelectionListener(new SelectionAdapter() {

                @Override
                public void widgetSelected(SelectionEvent e) {
                    super.widgetSelected(e);
                    parentWizardPage.setPageComplete(false);
                }
            });
        }
    }

    private TreeItem getExistItem(MetadataTable table) {
        if (!schemaTree.isDisposed() && table != null && table.eContainer() != null) {
            String parentName = ((orgomg.cwm.objectmodel.core.Package) table.eContainer()).getName();
            TreeItem[] items = schemaTree.getItems();
            for (TreeItem treeItem : items) {
                if (treeItem.getData() != null) {
                    ENoSQLSchemaType schemaType = ((INoSQLSchemaNode) treeItem.getData()).getSchemaType();
                    if (ENoSQLSchemaType.DATABASE.equals(schemaType)) {
                        for (TreeItem item : treeItem.getItems()) {
                            if (MetadataToolHelper.validateTableName(item.getText(0)).equals(table.getLabel())
                                    && treeItem.getText(0).equals(parentName) && item.getChecked()) {
                                return item;
                            }
                        }
                    } else if (ENoSQLSchemaType.TABLE.equals(schemaType)) {
                        if (MetadataToolHelper.validateTableName(treeItem.getText(0)).equals(table.getLabel())
                                && treeItem.getChecked()) {
                            return treeItem;
                        }
                    }
                }
            }
        }

        return null;
    }

    // @Override
    // public void setVisible(boolean visible) {
    // super.setVisible(visible);
    // if (visible) {
    // // hitTablesMap.clear();
    // }
    // }

    @Override
    protected void processWhenDispose() {
        if (retrieveSchemaExecutor != null) {
            try {
                retrieveSchemaExecutor.shutdownNow();
                retrieveSchemaExecutor.shutdown();
            } catch (SecurityException e) {
                e.printStackTrace();
            }
        }
    }

    private String getNameFilter() {
        return StringUtils.trimToEmpty(filterText.getText());
    }

    class SchemaViewerFilter extends ViewerFilter {

        @Override
        public boolean select(Viewer viewer, Object parentElement, Object element) {
            String pattern = getNameFilter();
            SearchPattern matcher = new SearchPattern();
            matcher.setPattern(pattern);
            if (element instanceof INoSQLSchemaNode) {
                INoSQLSchemaNode node = (INoSQLSchemaNode) element;
                if (ENoSQLSchemaType.TABLE.equals(node.getSchemaType())) {
                    if (!matcher.matches(node.getName())) {
                        return false;
                    }
                }
            }
            return true;
        }

    }

}