/*
* uDig - User Friendly Desktop Internet GIS client
* http://udig.refractions.net
* (C) 2012, Refractions Research Inc.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* (http://www.eclipse.org/legal/epl-v10.html), and the Refractions BSD
* License v1.0 (http://udig.refractions.net/files/bsd3-v10.html).
*/
package org.locationtech.udig.catalog.internal.ui.actions;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.locationtech.udig.catalog.CatalogPlugin;
import org.locationtech.udig.catalog.IResolve;
import org.locationtech.udig.catalog.URLUtils;
import org.locationtech.udig.catalog.ui.CatalogUIPlugin;
import org.locationtech.udig.catalog.ui.UDIGConnectionFactory;
import org.locationtech.udig.catalog.ui.wizard.CatalogImport;
import org.locationtech.udig.core.internal.CorePlugin;
import org.locationtech.udig.core.internal.ExtensionPointProcessor;
import org.locationtech.udig.core.internal.ExtensionPointUtil;
import org.locationtech.udig.internal.ui.Trace;
import org.locationtech.udig.internal.ui.UiPlugin;
import org.locationtech.udig.ui.IDropAction;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
/**
* Handles data being dropped on the catalog. Pretty generic
*
* @author jdeolive
* @author Jesse
*/
public class CatalogImportDropAction extends IDropAction {
PageProcessor p;
public CatalogImportDropAction() {
super();
}
@Override
public boolean accept() {
Object data = getData();
if (data.getClass().isArray()) {
Object[] objects = ((Object[]) data);
for( Object object : objects ) {
if (canAccept(object)) {
return true;
}
}
return false;
} else if (canAccept(data)) {
return true;
}
return canAccept(data);
}
private boolean canAccept( Object data ) {
if (data instanceof IResolve) {
IResolve resolve = (IResolve) data;
List<IResolve> find = CatalogPlugin.getDefault().getLocalCatalog().find(
resolve.getIdentifier(), new NullProgressMonitor());
if (find != null && !find.isEmpty())
return false;
return canImport(data);
}
return canImport(data);
}
/**
* True if the data can be imported into the catalog (irregardless if it is already in
* catalog).
* <p>
* This is where we check if the data is some form of URL, or file that is worth sending
* in the direction of the catalog code.
* </p>
* @param data data to import
* @return true if the data can be imported into the catalog irregardless if it is already in
* catalog
*/
protected boolean canImport( Object data1 ) {
Object data = data1;
if (getData() instanceof String) {
URL url = extractURL((String) getData());
if (url != null) {
data = url;
}
}
// process the wizard page extension point to determine if anyone
// can process the object
p = new PageProcessor(data);
ExtensionPointUtil.process(CatalogUIPlugin.getDefault(), UDIGConnectionFactory.XPID, p);
Set<String> found = p.ids;
return !found.isEmpty();
}
@Override
public void perform( IProgressMonitor monitor ) {
Object data = getData();
if (data.getClass().isArray()) {
Object[] array = (Object[]) data;
for (Object object : array) {
if( canAccept(object)){
doImportSingleItem(monitor, object);
}
}
}else{
doImportSingleItem(monitor, data);
}
}
private void doImportSingleItem(IProgressMonitor monitor, Object data) {
if (data instanceof String) {
URL url = extractURL((String) data);
if (url != null) {
data = url;
}
}
CatalogImport catalogImport = new CatalogImport();
catalogImport.run(monitor, data);
}
/**
* Searches a String looking for URLs and returns the first one it can find.
*
* @param data
* @return
*/
protected URL extractURL( String data ) {
String decoded = data;
try {
decoded = URLDecoder.decode(decoded, "UTF-8");
} catch (UnsupportedEncodingException e2) {
// so ignore...
}
decoded = decoded.replaceAll("amp;", "&");
URL result = null;
String line = decoded.replace("\\S+", ""); //$NON-NLS-1$
result = matchAnchorTag(line);
if (result != null) {
return formatFileURL(result);
}
result = matchGotoTag(line);
if (result != null) {
return formatFileURL(result);
}
result = matchHttpTag(result, line);
if (result != null) {
return formatFileURL(result);
}
try {
result = new URL(line);
} catch (MalformedURLException e) {
}
if (result == null && !line.contains(":/")) {
// maybe its a file?
// try {
result = URLUtils.fileToURL(new File(line));
// String string = "file:" + line;
// result = new URL(string);
// } catch (MalformedURLException e2) {
// }
}
if (result == null) {
try {
result = new URL(null, line, CorePlugin.RELAXED_HANDLER);
} catch (MalformedURLException e1) {
// worth a try
}
}
return formatFileURL(result);
}
/**
* Make sure that if the url is a file URL getFile will get the full path including the drive on
* windows/
*
* @param result
* @return
*/
private URL formatFileURL( URL result ) {
if (result != null && result.getProtocol().equalsIgnoreCase("file")) { //$NON-NLS-1$
try {
return new URL(result.toExternalForm());
} catch (MalformedURLException e) {
return result;
}
}
return result;
}
private URL matchHttpTag( URL result, String line ) {
// search for URL
Pattern urlPattern = Pattern.compile("([hH][Tt][Tt][Pp]\\S*)"); //$NON-NLS-1$
Matcher urlMatcher = urlPattern.matcher(line);
if (urlMatcher.find()) {
String group = urlMatcher.group(1);
try {
int index = group.indexOf('"');
if (index != -1)
group = group.substring(0, index);
index = group.indexOf('>');
if (index != -1)
group = group.substring(0, index);
result = new URL(group);
} catch (MalformedURLException e) {
UiPlugin.trace(Trace.DND, CatalogImportDropAction.class,"failure to create url from "+group, e);
}
}
return result;
}
private URL matchGotoTag( String line ) {
Pattern anchorPattern = Pattern.compile("goto=(\\S+)"); //$NON-NLS-1$
Matcher anchorMatcher = anchorPattern.matcher(line);
URL result = null;
if (anchorMatcher.find()) {
try {
String group = anchorMatcher.group(1);
int index = group.indexOf("\""); //$NON-NLS-1$
if (index == -1)
index = group.length();
result = new URL(group.substring(0, index));
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
return result;
}
private URL matchAnchorTag( String line ) {
// search for anchor tags
Pattern anchorPattern = Pattern.compile("<a.*href=\"(\\S+)\"\\S*"); //$NON-NLS-1$
Matcher anchorMatcher = anchorPattern.matcher(line);
URL result = null;
if (anchorMatcher.find()) {
try {
String group = anchorMatcher.group(1);
int index = group.indexOf("\""); //$NON-NLS-1$
if (index == -1)
index = group.length();
result = new URL(group.substring(0, index));
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
return result;
}
static class PageProcessor implements ExtensionPointProcessor {
Object data;
Set<String> ids = new LinkedHashSet<String>();
PageProcessor( Object data ) {
this.data = data;
}
public void process( IExtension extension, IConfigurationElement element ) throws Exception {
try {
if (!"factory".equals(element.getName())) //$NON-NLS-1$
return;
UDIGConnectionFactory factory = (UDIGConnectionFactory) element
.createExecutableExtension("class"); //$NON-NLS-1$
if (factory.canProcess(data)) {
// get the id
IConfigurationElement[] elements = extension.getConfigurationElements();
for( int i = 0; i < elements.length; i++ ) {
if( elements[i].getAttribute("id") != null){
ids.add(elements[i].getAttribute("id")); //$NON-NLS-1$
}
}
}
} catch (Throwable t) {
String msg = "Error processing wizard page"; //$NON-NLS-1$
CatalogPlugin.log(msg, t);
}
}
}
// class CatalogWizard extends CatalogImportWizard {
//
// List<String> ids;
//
// CatalogWizard(List<String> ids) {
// this.ids = ids;
//
// }
//
// @Override
// protected WizardPage[] getPrimaryPages() {
//
// DataSourceSelectionPage page = new DataSourceSelectionPage();
// page.select(ids);
//
// return new WizardPage[] { page };
//
// }
//
// }
//
// class MapWizard extends AddLayersWizard {
//
// List<String> ids;
//
// MapWizard(List<String> ids) {
// this.ids = ids;
// }
//
// @Override
// protected WizardPage[] getPrimaryPages() {
//
// DataSourceSelectionPage page = new DataSourceSelectionPage();
// page.select(ids);
//
// ResourceSelectionPage rpage = new ResourceSelectionPage(
// Messages.AddLayersWizard_layerSelection
// );
//
// return new WizardPage[] { page, rpage };
//
// }
//
// }
}