/* * 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.io.source; import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.net.URI; import java.text.MessageFormat; import java.util.Collection; import java.util.HashSet; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.content.IContentType; import org.eclipse.jface.dialogs.DialogPage; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.preference.FieldEditor; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.ComboViewer; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.ui.PlatformUI; import eu.esdihumboldt.hale.common.core.io.HaleIO; import eu.esdihumboldt.hale.common.core.io.IOProvider; import eu.esdihumboldt.hale.common.core.io.ImportProvider; import eu.esdihumboldt.hale.common.core.io.extension.IOProviderDescriptor; import eu.esdihumboldt.hale.common.core.io.supplier.DefaultInputSupplier; import eu.esdihumboldt.hale.common.core.io.supplier.LocatableInputSupplier; import eu.esdihumboldt.hale.ui.internal.HALEUIPlugin; import eu.esdihumboldt.hale.ui.io.ImportSource; /** * URL import source * * @param <P> the supported {@link IOProvider} type * * @author Simon Templer * @since 2.5 */ public class URLSource<P extends ImportProvider> extends AbstractProviderSource<P> { /** * The file field editor for the source URL */ private URLSourceURIFieldEditor sourceURL; /** * The set of supported content types */ private Set<IContentType> supportedTypes; private ComboViewer types; private Button detect; private Image detectImage; /** * @see ImportSource#createControls(Composite) */ @Override public void createControls(Composite parent) { parent.setLayout(new GridLayout(3, false)); detectImage = HALEUIPlugin.getImageDescriptor("icons/find_obj.gif").createImage(); // source file sourceURL = new URLSourceURIFieldEditor("sourceURL", "Source URL:", parent) { @Override protected void onHistorySelected(URI location, IContentType contentType) { // select the content type associated with the recent URL types.setSelection(new StructuredSelection(contentType)); updateState(false); } }; sourceURL.setPage(getPage()); // set content types for file field Collection<IOProviderDescriptor> factories = getConfiguration().getFactories(); supportedTypes = new HashSet<IContentType>(); for (IOProviderDescriptor factory : factories) { supportedTypes.addAll(factory.getSupportedTypes()); } sourceURL.setContentTypes(supportedTypes); sourceURL.setPropertyChangeListener(new IPropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent event) { if (event.getProperty().equals(FieldEditor.IS_VALID)) { getPage().setMessage(null); updateState(false); } else if (event.getProperty().equals(FieldEditor.VALUE)) { getPage().setMessage(null); updateState(false); } } }); // content type selection // label Label typesLabel = new Label(parent, SWT.NONE); typesLabel.setText("Content type"); // types combo Composite group = new Composite(parent, SWT.NONE); group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1)); group.setLayout(GridLayoutFactory.fillDefaults().numColumns(2).create()); types = new ComboViewer(group, SWT.DROP_DOWN | SWT.READ_ONLY); types.getControl().setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); types.setContentProvider(ArrayContentProvider.getInstance()); types.setLabelProvider(new LabelProvider() { @Override public String getText(Object element) { if (element instanceof IContentType) { return ((IContentType) element).getName(); } return super.getText(element); } }); types.setInput(supportedTypes); // process selection changes types.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { updateState(true); } }); // detect button detect = new Button(group, SWT.PUSH); detect.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false)); detect.setText("Detect"); detect.setImage(detectImage); detect.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { runDetectContentType(); } }); // provider selection // label Label providerLabel = new Label(parent, SWT.NONE); providerLabel.setText("Import as"); // create provider combo ComboViewer providers = createProviders(parent); providers.getControl().setLayoutData( new GridData(SWT.FILL, SWT.BEGINNING, true, false, 2, 1)); // initial state update updateState(true); } /** * Run content type detection. */ protected void runDetectContentType() { try { getPage().getWizard().getContainer().run(false, false, new IRunnableWithProgress() { @Override public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { monitor.beginTask("Detect content type", IProgressMonitor.UNKNOWN); final IContentType detected = detectContentType(); PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { @Override public void run() { if (detected != null) { types.setSelection(new StructuredSelection(detected)); getPage().setMessage( MessageFormat.format("Detected {0} as content type", detected.getName()), DialogPage.INFORMATION); updateState(true); } else { types.setSelection(new StructuredSelection()); getPage() .setMessage( "Could not detect content type. The resource might be not available or it has no matching content type.", DialogPage.WARNING); updateState(true); } } }); monitor.done(); } }); } catch (Throwable t) { getPage().setErrorMessage("Starting the task to detect the content type failed"); } } /** * Detect the content type * * @return the detected content type or <code>null</code> */ private IContentType detectContentType() { final Display display = PlatformUI.getWorkbench().getDisplay(); final AtomicReference<String> sourceString = new AtomicReference<String>(); final AtomicReference<URI> sourceURI = new AtomicReference<URI>(); display.syncExec(new Runnable() { @Override public void run() { if (sourceURL.isValid() && sourceURL.getURI() != null) { sourceString.set(sourceURL.getStringValue()); try { sourceURI.set(sourceURL.getURI()); } catch (Throwable e) { getPage().setErrorMessage(e.getLocalizedMessage()); } } } }); if (sourceURI.get() != null && sourceString.get() != null) { // determine content type Collection<IContentType> filteredTypes; filteredTypes = HaleIO.findContentTypesFor(supportedTypes, new DefaultInputSupplier( sourceURI.get()), sourceString.get()); if (!filteredTypes.isEmpty()) { return filteredTypes.iterator().next(); } } return null; } /** * @see AbstractProviderSource#updateContentType() */ @Override protected void updateContentType() { IContentType ct = null; ISelection typeSel = types.getSelection(); if (!typeSel.isEmpty() && typeSel instanceof IStructuredSelection) { ct = (IContentType) ((IStructuredSelection) typeSel).getFirstElement(); } getConfiguration().setContentType(ct); super.updateContentType(); } /** * @see AbstractProviderSource#updateState(boolean) */ @Override protected void updateState(boolean updateContentType) { boolean enableSelection = sourceURL.isValid() && sourceURL.getURI() != null; detect.setEnabled(enableSelection); types.getControl().setEnabled(enableSelection); if (!enableSelection && types.getSelection() != null && !types.getSelection().isEmpty()) { types.setSelection(new StructuredSelection()); updateContentType = true; } super.updateState(updateContentType); } /** * @see AbstractProviderSource#isValidSource() */ @Override protected boolean isValidSource() { return sourceURL.isValid() && sourceURL.getURI() != null; } /** * @see AbstractProviderSource#getSource() */ @Override protected LocatableInputSupplier<? extends InputStream> getSource() { URI uri = sourceURL.getURI(); if (uri != null) { return new DefaultInputSupplier(uri); } return null; } /** * @see AbstractSource#dispose() */ @Override public void dispose() { if (detectImage != null) { detectImage.dispose(); } } /** * @see AbstractSource#onActivate() */ @Override public void onActivate() { sourceURL.setFocus(); } }