Java tutorial
/*************************************************************************** * This package is part of Relations application. * Copyright (C) 2004-2013, Benno Luthiger * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package org.elbe.relations.internal.wizards; import java.lang.reflect.InvocationTargetException; import java.util.Collection; import java.util.Vector; import javax.inject.Inject; import javax.inject.Named; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.e4.core.contexts.ContextInjectionFactory; import org.eclipse.e4.core.contexts.IEclipseContext; import org.eclipse.e4.core.services.log.Logger; import org.eclipse.e4.ui.di.UISynchronize; import org.eclipse.e4.ui.services.IServiceConstants; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.ProgressMonitorDialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.wizard.Wizard; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IImportWizard; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.internal.progress.ProgressMonitorJobsDialog; import org.elbe.relations.RelationsConstants; import org.elbe.relations.RelationsMessages; import org.elbe.relations.data.bom.BOMHelper; import org.elbe.relations.data.bom.RelationHome; import org.elbe.relations.db.IDataService; import org.elbe.relations.internal.actions.DBDeleteAction; import org.elbe.relations.internal.actions.IDBChange; import org.elbe.relations.internal.actions.IndexerAction; import org.elbe.relations.internal.backup.XMLImport; import org.elbe.relations.internal.backup.XMLImport.RelationReplaceHelper; import org.elbe.relations.internal.backup.ZippedXMLImport; import org.elbe.relations.internal.controls.RelationsStatusLineManager; import org.elbe.relations.internal.data.DBSettings; import org.elbe.relations.internal.utility.AbstractRunnableWithProgress; import org.elbe.relations.internal.utility.DBPreconditionException; import org.elbe.relations.internal.utility.WizardHelper; import org.hip.kernel.bom.KeyObject; import org.hip.kernel.bom.impl.KeyObjectImpl; import org.hip.kernel.bom.impl.UpdateStatement; import org.hip.kernel.exc.VException; /** * Wizard to import the database content from a (zipped) XML file.<br /> * Note: this is an Eclipse 3 wizard. To make it e4, let the values for the * annotated field be injected (instead of using the method init()). * * @author Luthiger Created on 13.10.2008 */ @SuppressWarnings("restriction") public class ImportFromXML extends Wizard implements IImportWizard { private ImportFromXMLPage page; @Inject private IEclipseContext context; @Inject private Logger log; @Inject @Named(IServiceConstants.ACTIVE_SHELL) private Shell shell; @Inject private UISynchronize sync; @Inject private IDataService dataService; @Inject private DBSettings dbSettings; @Inject private RelationsStatusLineManager statusLine; @Override public void init(final IWorkbench inWorkbench, final IStructuredSelection inSelection) { context = (IEclipseContext) inWorkbench.getAdapter(IEclipseContext.class); log = (Logger) inWorkbench.getAdapter(Logger.class); shell = inWorkbench.getDisplay().getActiveShell(); sync = (UISynchronize) inWorkbench.getAdapter(UISynchronize.class); dataService = (IDataService) inWorkbench.getAdapter(IDataService.class); dbSettings = (DBSettings) inWorkbench.getAdapter(DBSettings.class); statusLine = WizardHelper.getFromWorkbench(RelationsStatusLineManager.class, inWorkbench); setWindowTitle(RelationsMessages.getString("ImportFromXML.window.title")); //$NON-NLS-1$ } @Override public void addPages() { page = new ImportFromXMLPage("ImportFromXMLPage", context, log); //$NON-NLS-1$ addPage(page); } @Override public boolean performFinish() { page.saveToHistory(); final String lImportFile = page.getFileName(); statusLine.showStatusLineMessage( String.format(RelationsMessages.getString("ImportFromXML.msg.status"), lImportFile)); //$NON-NLS-1$ final IDBChange lCreateDB = page.getResultObject(); getShell().setVisible(false); try { lCreateDB.checkPreconditions(); if (createAndFill(lCreateDB, lImportFile)) { // load the data dataService.loadData(RelationsConstants.TOPIC_DB_CHANGED_RELOAD); // index data final IndexerAction lAction = ContextInjectionFactory.make(IndexerAction.class, context); lAction.setSilent(true); lAction.run(); } else { getShell().setVisible(true); return false; } } catch (final DBPreconditionException exc) { MessageDialog.openError(new Shell(Display.getCurrent()), RelationsMessages.getString("FormDBConnection.error.title"), exc.getMessage()); //$NON-NLS-1$ getShell().setVisible(true); return false; } return true; } private boolean createAndFill(final IDBChange inCreateDB, final String inImportFile) { final XMLImport lImport = inImportFile.endsWith(".zip") ? new ZippedXMLImport(inImportFile) //$NON-NLS-1$ : new XMLImport(inImportFile); final int lWorkItemsCount = 6; // run catalog creation and data import with progress monitor IRunnableWithProgress lJob = new AbstractRunnableWithProgress() { @Override protected final Runnable getRunnableInitialize(final IProgressMonitor inMonitor) { return new Runnable() { @Override public void run() { inMonitor.beginTask( String.format(RelationsMessages.getString("ImportFromXML.job.import.start"), //$NON-NLS-1$ inImportFile), lWorkItemsCount); } }; } /** * Create tables in database catalog - Parse XML file and create * table entries */ @Override protected final int process(final IProgressMonitor inMonitor) throws InvocationTargetException, InterruptedException { int outNumberOfImported = 0; sync.syncExec(new Runnable() { @Override public void run() { inCreateDB.execute(); } }); inMonitor.worked(1); if (inMonitor.isCanceled()) { throw new InterruptedException(); } try { outNumberOfImported = lImport.processFile(inMonitor, dbSettings.getDBConnectionConfig().canSetIdentityField()); monitorWorked(inMonitor); } catch (final InterruptedException exc) { throw exc; } catch (final Exception exc) { throw new InvocationTargetException(exc); } return outNumberOfImported; } @Override protected final Runnable getRunnableFeedback(final int inNumberOfProcessed) { final String lFeedback = String.format( RelationsMessages.getString("ImportFromXML.job.import.feedback"), inNumberOfProcessed); //$NON-NLS-1$ return new Runnable() { @Override public void run() { if (dbSettings.getDBConnectionConfig().canSetIdentityField()) { MessageDialog.openInformation(shell, RelationsMessages.getString("ImportFromXML.job.import.success"), lFeedback); //$NON-NLS-1$ } else { statusLine.showStatusLineMessage(lFeedback); } } }; } }; final ProgressMonitorDialog lImportDialog = new ProgressMonitorJobsDialog(shell); lImportDialog.open(); try { lImportDialog.run(true, true, lJob); } catch (final InvocationTargetException exc) { log.error(exc, exc.getMessage()); restorePrevious(inCreateDB); return false; } catch (final InterruptedException exc) { log.debug("Import of data interrupted by user."); //$NON-NLS-1$ restorePrevious(inCreateDB); return false; } finally { lImportDialog.close(); } if (!dbSettings.getDBConnectionConfig().canSetIdentityField()) { // run relation rebind with progress monitor final Collection<RelationReplaceHelper> lRelationsToRebind = lImport.getRelationsToRebind(); lJob = new AbstractRunnableWithProgress() { @Override protected Runnable getRunnableInitialize(final IProgressMonitor inMonitor) { return new Runnable() { @Override public void run() { inMonitor.beginTask(RelationsMessages.getString("ImportFromXML.job.rebind.start"), //$NON-NLS-1$ lRelationsToRebind.size()); } }; } @Override protected int process(final IProgressMonitor inMonitor) throws InvocationTargetException, InterruptedException { return processRebind(lRelationsToRebind, inMonitor); } @Override protected Runnable getRunnableFeedback(final int inNumberOfProcessed) { final String lFeedback = String.format( RelationsMessages.getString("ImportFromXML.job.rebind.feedback"), inNumberOfProcessed); //$NON-NLS-1$ return new Runnable() { @Override public void run() { MessageDialog.openInformation(shell, RelationsMessages.getString("ImportFromXML.job.rebind.success"), lFeedback); //$NON-NLS-1$ } }; } }; final ProgressMonitorDialog lRebindDialog = new ProgressMonitorJobsDialog(shell); lRebindDialog.open(); try { lRebindDialog.run(true, true, lJob); } catch (final InvocationTargetException exc) { log.error(exc, exc.getMessage()); return false; } catch (final InterruptedException exc) { return false; } finally { lRebindDialog.close(); } } return true; } private void monitorWorked(final IProgressMonitor inMonitor) { if (inMonitor != null) { inMonitor.worked(1); } } private int processRebind(final Collection<RelationReplaceHelper> inRelationsToRebind, final IProgressMonitor inMonitor) throws InvocationTargetException, InterruptedException { int outNumberOfEntries = 0; final int CHUNK_LEN = 20; final RelationHome lHome = BOMHelper.getRelationHome(); UpdateStatement lStatement; try { final Collection<String> lUpdates = new Vector<String>(CHUNK_LEN); for (final RelationReplaceHelper lRelationToRebind : inRelationsToRebind) { createUpdates(lHome, lRelationToRebind, lUpdates); // update in chunks to improve performance if (lUpdates.size() >= CHUNK_LEN) { lStatement = new UpdateStatement(lHome); lStatement.setUpdates(lUpdates); lStatement.executeUpdate(); lUpdates.clear(); } inMonitor.worked(1); outNumberOfEntries++; if (inMonitor.isCanceled()) { throw new InterruptedException(); } } // update the last chunk if (lUpdates.size() > 0) { lStatement = new UpdateStatement(lHome); lStatement.setUpdates(lUpdates); lStatement.executeUpdate(); } } catch (final InterruptedException exc) { throw exc; } catch (final Exception exc) { throw new InvocationTargetException(exc); } return outNumberOfEntries; } private void restorePrevious(final IDBChange inChangeDB) { if (dbSettings.getDBConnectionConfig().isEmbedded()) { DBDeleteAction.deleteEmbedded(dbSettings, log); } inChangeDB.restore(); dataService.loadData(RelationsConstants.TOPIC_DB_CHANGED_RELOAD); } private void createUpdates(final RelationHome inHome, final RelationReplaceHelper inRelationToRebind, final Collection<String> inUpdates) throws VException { // item1 KeyObject lChange = new KeyObjectImpl(); lChange.setValue(RelationHome.KEY_ITEM1, new Long(inRelationToRebind.newID.itemID)); KeyObject lWhere = new KeyObjectImpl(); lWhere.setValue(RelationHome.KEY_TYPE1, new Integer(inRelationToRebind.oldID.itemType)); lWhere.setValue(RelationHome.KEY_ITEM1, new Long(inRelationToRebind.oldID.itemID)); inUpdates.add(inHome.createUpdateString(lChange, lWhere)); // item2 lChange = new KeyObjectImpl(); lChange.setValue(RelationHome.KEY_ITEM2, new Long(inRelationToRebind.newID.itemID)); lWhere = new KeyObjectImpl(); lWhere.setValue(RelationHome.KEY_TYPE2, new Integer(inRelationToRebind.oldID.itemType)); lWhere.setValue(RelationHome.KEY_ITEM2, new Long(inRelationToRebind.oldID.itemID)); inUpdates.add(inHome.createUpdateString(lChange, lWhere)); } @Override public void dispose() { if (page != null) page.dispose(); } }