/*
* Copyright (c) 2012 Data Harmonisation Panel
*
* All rights reserved. This program and the accompanying materials are made
* available under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution. If not, see <http://www.gnu.org/licenses/>.
*
* Contributors:
* HUMBOLDT EU Integrated Project #030962
* Data Harmonisation Panel <http://www.dhpanel.eu>
*/
package eu.esdihumboldt.hale.ui.transformation;
import java.io.File;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.ListViewer;
import org.eclipse.jface.wizard.IWizardContainer;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.PlatformUI;
import eu.esdihumboldt.hale.common.core.io.IOProvider;
import eu.esdihumboldt.hale.common.core.io.project.model.IOConfiguration;
import eu.esdihumboldt.hale.common.core.io.project.model.Resource;
import eu.esdihumboldt.hale.common.core.io.report.IOReport;
import eu.esdihumboldt.hale.common.core.io.report.IOReporter;
import eu.esdihumboldt.hale.common.core.io.supplier.FileIOSupplier;
import eu.esdihumboldt.hale.common.core.io.supplier.Locatable;
import eu.esdihumboldt.hale.common.core.io.supplier.LocatableInputSupplier;
import eu.esdihumboldt.hale.common.headless.transform.ExportJob;
import eu.esdihumboldt.hale.common.headless.transform.ValidationJob;
import eu.esdihumboldt.hale.common.instance.io.InstanceIO;
import eu.esdihumboldt.hale.common.instance.io.InstanceValidator;
import eu.esdihumboldt.hale.common.instance.io.InstanceWriter;
import eu.esdihumboldt.hale.common.instance.model.InstanceCollection;
import eu.esdihumboldt.hale.common.schema.SchemaSpaceID;
import eu.esdihumboldt.hale.ui.DefaultReportHandler;
import eu.esdihumboldt.hale.ui.HaleUI;
import eu.esdihumboldt.hale.ui.io.instance.InstanceExportWizard;
import eu.esdihumboldt.hale.ui.io.instance.InstanceImportWizard;
import eu.esdihumboldt.hale.ui.service.project.ProjectResourcesUtil;
import eu.esdihumboldt.hale.ui.service.project.ProjectService;
import eu.esdihumboldt.hale.ui.service.schema.SchemaService;
import eu.esdihumboldt.hale.ui.util.io.ThreadProgressMonitor;
import eu.esdihumboldt.hale.ui.util.wizard.HaleWizardDialog;
/**
* Page for selection of source data files for the {@link TransformDataWizard}.
*
* @author Kai Schwierczek
*/
public class TransformDataWizardSourcePage extends WizardPage {
private final InternalInstanceExportWizard exportWizard;
private final List<InstanceCollection> sourceCollections = new ArrayList<InstanceCollection>();
private ExportJob exportJob;
private ValidationJob validationJob;
private final TransformationSinkProxy targetSink;
private final boolean useProjectData;
/**
* Creates the transform data wizard page for selecting source data files.
* The pages next page is the starting page of the export wizard. For that
* it needs the target instance collection.
*
* @param container the wizard container
* @param targetSink the target sink
* @param useProjectData <code>true</code> if the source data registered in
* the project should be used, <code>false</code> if the user
* specify different data
*/
public TransformDataWizardSourcePage(IWizardContainer container,
TransformationSinkProxy targetSink, boolean useProjectData) {
super("sourceSelection");
this.targetSink = targetSink;
this.useProjectData = useProjectData;
if (useProjectData) {
setTitle("Source data");
setDescription(
"The data sources that are imported into the project and will be transformed");
}
else {
setTitle("Source instance selection");
setDescription("Add all source data files which you want to transform.");
}
setPageComplete(false);
exportWizard = new InternalInstanceExportWizard();
exportWizard.setContainer(container);
exportWizard.setAdvisor(new TransformDataExportAdvisor(targetSink.getInstanceCollection()),
null);
// add pages after setting the advisor, because it creates new config
// pages
exportWizard.addPages();
}
/**
* @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
*/
@Override
public void createControl(Composite parent) {
Composite content = new Composite(parent, SWT.NONE);
content.setLayout(GridLayoutFactory.swtDefaults().create());
final ListViewer listViewer = new ListViewer(content);
listViewer.getControl()
.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create());
if (!useProjectData) {
Button addButton = new Button(content, SWT.PUSH);
addButton.setText("Add source file");
addButton.setLayoutData(
GridDataFactory.swtDefaults().align(SWT.END, SWT.CENTER).create());
addButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
InstanceImportWizard importWizard = new InstanceImportWizard();
TransformDataImportAdvisor advisor = new TransformDataImportAdvisor();
// specifying null as actionId results in no call to
// ProjectService.rememberIO
importWizard.setAdvisor(advisor, null);
if (new HaleWizardDialog(getShell(), importWizard).open() == Dialog.OK) {
if (advisor.getInstances() != null) {
sourceCollections.add(advisor.getInstances());
listViewer.add(advisor.getLocation());
getContainer().updateButtons();
}
}
}
});
}
else {
// initialize project source data
IRunnableWithProgress op = new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor)
throws InvocationTargetException, InterruptedException {
monitor.beginTask("Prepare data sources", IProgressMonitor.UNKNOWN);
ProjectService ps = PlatformUI.getWorkbench().getService(ProjectService.class);
final List<URI> locations = new ArrayList<>();
for (Resource resource : ps.getResources()) {
if (InstanceIO.ACTION_LOAD_SOURCE_DATA.equals(resource.getActionId())) {
// resource is source data
IOConfiguration conf = resource.copyConfiguration(true);
TransformDataImportAdvisor advisor = new TransformDataImportAdvisor();
ProjectResourcesUtil.executeConfiguration(conf, advisor, false, null);
if (advisor.getInstances() != null) {
sourceCollections.add(advisor.getInstances());
locations.add(advisor.getLocation());
}
}
}
PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
@Override
public void run() {
for (URI location : locations) {
listViewer.add(location);
}
}
});
monitor.done();
}
};
try {
ThreadProgressMonitor.runWithProgressDialog(op, false);
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
setControl(content);
}
/**
* @see org.eclipse.jface.wizard.WizardPage#getNextPage()
*/
@Override
public IWizardPage getNextPage() {
return exportWizard.getStartingPage();
}
/**
* @see org.eclipse.jface.wizard.WizardPage#canFlipToNextPage()
*/
@Override
public boolean canFlipToNextPage() {
return !sourceCollections.isEmpty();
}
/**
* Returns all selected source instance collections.
*
* @return all selected source instance collections
*/
public List<InstanceCollection> getSourceInstances() {
return sourceCollections;
}
/**
* Returns the export job.
*
* @return the export job
*/
public ExportJob getExportJob() {
return exportJob;
}
/**
* Returns the validation job.
*
* @return the validation job, may be null
*/
public ValidationJob getValidationJob() {
return validationJob;
}
/**
* InstanceExportWizard with custom performFinish behavior.
*/
private class InternalInstanceExportWizard extends InstanceExportWizard {
/**
* @see eu.esdihumboldt.hale.ui.io.instance.InstanceExportWizard#performValidation()
*/
@Override
protected boolean performValidation() {
// Customize validation to run as a ValidationJob
validationJob = new ValidationJob(getValidators(), DefaultReportHandler.getInstance(),
null, HaleUI.getServiceProvider()) {
@Override
protected IStatus run(IProgressMonitor monitor) {
/*
* Reconfigure validators because when it was created the
* writer was not executed yet (and the validation schemas
* thus not updated if applicable)
*/
// set schemas
List<? extends Locatable> schemas = getProvider().getValidationSchemas();
for (InstanceValidator validator : getValidators()) {
validator.setSchemas(schemas.toArray(new Locatable[schemas.size()]));
if (getProvider().getTarget() instanceof FileIOSupplier) {
// set source
FileIOSupplier fileIO = (FileIOSupplier) getProvider().getTarget();
LocatableInputSupplier<? extends InputStream> source = new FileIOSupplier(
new File(fileIO.getLocation()));
validator.setSource(source);
// apply target content type
validator.setContentType(getContentType());
}
}
return super.run(monitor);
}
};
return true;
}
@Override
protected IOReport execute(final IOProvider provider, final IOReporter defaultReporter) {
if (exportJob == null) {
InstanceWriter writer = (InstanceWriter) provider;
// init sink
try {
targetSink.init(!writer.isPassthrough());
SchemaService ss = PlatformUI.getWorkbench().getService(SchemaService.class);
targetSink.setTypes(ss.getSchemas(SchemaSpaceID.TARGET));
} catch (Exception e) {
throw new IllegalStateException("Failed to initialize target sink", e);
}
// create export job
exportJob = new ExportJob(targetSink, writer, getAdvisor(),
DefaultReportHandler.getInstance());
}
else {
throw new IllegalStateException("Unknown calls to export wizard's execute.");
}
return null;
}
}
}