Package org.locationtech.udig.catalog.ui.workflow

Source Code of org.locationtech.udig.catalog.ui.workflow.EndConnectionState

/*
*    uDig - User Friendly Desktop Internet GIS client
*    http://udig.refractions.net
*    (C) 2004-2011, 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.ui.workflow;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.locationtech.udig.catalog.CatalogPlugin;
import org.locationtech.udig.catalog.ICatalog;
import org.locationtech.udig.catalog.IGeoResource;
import org.locationtech.udig.catalog.IRepository;
import org.locationtech.udig.catalog.IResolve;
import org.locationtech.udig.catalog.IService;
import org.locationtech.udig.catalog.IServiceFactory;
import org.locationtech.udig.catalog.ui.CatalogUIPlugin;
import org.locationtech.udig.catalog.ui.UDIGConnectionFactory;
import org.locationtech.udig.catalog.ui.UDIGConnectionFactoryDescriptor;
import org.locationtech.udig.catalog.ui.internal.Messages;
import org.locationtech.udig.core.Pair;
import org.locationtech.udig.ui.PlatformGIS;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.widgets.Display;

/**
* This is the "end of the line" when using an import wizard to add services
* to the catalog.
* <p>
* This wizard State is responsible for trying to connect to services.
* <ul>
* <li>If it can connect the method {@link #getServices()} makes the list
* available to the {@link CatalogImport#performFinish} which will
* add the servies to the catalog
* </li>
* <li>
* If it cannot connect it is responsible for indicating the connection error
* to the user so they can fix things
* </li>
* </ul>
* This  approach, while annoying as  developer, prevents us needing to create services
* twice. You may also find the code looking in the local catalog to see if we already
* have a connection.
* @author putnal
* @since 1.2.0
*/
public class EndConnectionState extends State {

    /** selected descriptor from previous page * */
    UDIGConnectionFactoryDescriptor descriptor;

    /** the connection factory * */
    ;
    UDIGConnectionFactory factory;

    /** connection errors * */
    Map<IService, Throwable> errors;

    /** collection of services * */
    Collection<IService> services=new HashSet<IService>();

    /***********************************************************************************************
     * 52�North added next State
     **********************************************************************************************/
    EndConnectionState nextState;

    private boolean validateServices;

    private Collection<URL> selectedResources;

    /**
     * Create instance
     *
     * @param descriptor The connection factory descriptor to use in state
     * @param validateServices indicates whether the service should be probed for its members and
     *        metadata.
     */
    public EndConnectionState( UDIGConnectionFactoryDescriptor descriptor, boolean validateServices ) {
        this.descriptor = descriptor;
        factory = descriptor.getConnectionFactory();
        this.validateServices = validateServices;
    }
   
    @Override
    public void init( IProgressMonitor monitor ) throws IOException {
        super.init(monitor);
        disposeOldServices(monitor);
    }

    @Override
    public Pair<Boolean, State> dryRun() {
        boolean hasServices = !services.isEmpty();
        return new Pair<Boolean, State>(hasServices, null);
    }

   
    @Override
    public boolean run( IProgressMonitor monitor ) throws IOException {
        if (factory == null)
            return false; // something went wrong, abort

        if( !services.isEmpty() ){
            return true;
        }
       
        ICatalog catalog = CatalogPlugin.getDefault().getLocalCatalog();
        List<IService> availableServices;
       
        monitor.beginTask(Messages.ConnectionState_task, IProgressMonitor.UNKNOWN);
       
        errors = null;
        try {
                // use the context object to try to build connection info
            Object context = getWorkflow().getContext();
   
            if( context instanceof IService ){
                services.add((IService)context);
                //services = Collections.singleton((IService)context);
            }else if (context instanceof IGeoResource){
                IService service = ((IGeoResource) context).service(monitor);
                services.add((IService)context);
                services.add(service);
            }else{
           
                Map<String, Serializable> params = factory.createConnectionParameters(context);
               
                URL url = factory.createConnectionURL(context)
       
                if (params == null && url == null)
                    return false; // could not build connection info
               
                if(url != null){
                    availableServices = catalog.constructServices(url, monitor);
                    if(!availableServices.isEmpty()){
                        services.add(availableServices.iterator().next());
                        return true;
                    }
                }
               
                if(params != null && !params.isEmpty()){
                    availableServices = catalog.constructServices(params, monitor);
                    if(!availableServices.isEmpty()){
                        services.add(availableServices.iterator().next());
                    }
                }
            }
        } catch (Throwable t) {
            CatalogPlugin.log(t.getLocalizedMessage(), t);
            return false;
        }


        // even if errors occured, we are still done
        // return true;
        return errors == null || errors.isEmpty();
    }
   
    private void disposeOldServices( IProgressMonitor monitor ) {
        if (services == null || services.isEmpty()) {
            return;
        }

        final List<IService> toDispose = new ArrayList<IService>(services);
        services.clear();

        IRunnableWithProgress runnable = new IRunnableWithProgress(){
            public void run(IProgressMonitor monitor) {
                monitor.beginTask("Disposing dereferenced services", toDispose.size());
                // dispose old services
                for( IService service : toDispose ) {
                    if( service.parent(monitor)==null){
                        service.dispose(SubMonitor.convert(monitor));
                    }
                    monitor.worked(1);
                }
            }
        };
       
        // disposing of services could take a long time so do it in a non-UI thread
        if( Display.getCurrent()!=null ){
            PlatformGIS.run(runnable);
        }else{
            try {
                runnable.run(new NullProgressMonitor());
            } catch (InvocationTargetException e) {
                throw (RuntimeException) new RuntimeException( ).initCause( e );
            } catch (InterruptedException e) {
                throw (RuntimeException) new RuntimeException( ).initCause( e );
            }
        }
    }

    /**
     * Deprecated use CatalogImpl.constructServices();
     * <p>
     * Responsible for providing a list of services produced either/and connection parameters or urls.
     * <p>
     * Calling code is responsible for adding these to the local catalog (or otherwise cleaning up
     * the mess).
     *
     * @param monitor
     * @param params
     * @param urls
     * @return List of matching Services (may be created from service factory or retrieved from local catalog)
     */
    @Deprecated
    public static Collection<IService> constructServices( IProgressMonitor monitor, Map<String, Serializable> params, Collection<URL> urls ) {
        // use the parameters/url to acquire a set of services
        //
        IServiceFactory sFactory = CatalogPlugin.getDefault().getServiceFactory();
       
        monitor.setTaskName(Messages.ConnectionState_task);

        Collection<IService> services = new HashSet<IService>();
        if (urls != null && !urls.isEmpty()) {       
            for( URL url : urls ) {
                Collection<IService> searchResult = searchLocalCatalog(url, monitor);
                if (searchResult.isEmpty()) {
                    List<IService> created = sFactory.createService(url);
                    services.addAll(created);
                } else {
                    services.addAll(searchResult);
                }
            }
        }
       
        if( params!=null && !params.isEmpty()){
            Set<IService> results = new HashSet<IService>(sFactory.createService(params));           
            for( IService service : results ) {
                Collection<IService> searchResult = searchLocalCatalog(service.getIdentifier(), monitor);
                if (searchResult.isEmpty() ) {
                    services.add(service);
                } else {
                    services.addAll(searchResult);
                }
            }
        }       
        return services;
    }

    private static Collection<IService> searchLocalCatalog( URL url, IProgressMonitor monitor ) {
        ICatalog localCatalog = CatalogPlugin.getDefault().getLocalCatalog();
       
        List<IResolve> resolves = localCatalog.find(url, monitor);
        ArrayList<IService> services = new ArrayList<IService>();
        for( IResolve iResolve : resolves ) {
            if (iResolve instanceof IService) {
                IService service = (IService) iResolve;
                services.add(service);
            }
        }
       
        return services;

    }

    private String formatServiceID( IService service ) {
        URL identifier = service.getIdentifier();
        if ("file".equals(identifier.getProtocol())) { //$NON-NLS-1$
            File file = new File(identifier.getFile());
            return file.getName();
        }
        String host = identifier.getHost();
        return host;
    }

    /**
     * 52�North added return true, if there are no errors and there is a successor state(which can
     * be the same state)
     */
    @Override
    public boolean hasNext() {
        return (errors != null && !errors.isEmpty()) || nextState != null;
    }

    /**
     * 52�North changed Method returns null if there is not a succesor state. Method returns a
     * ConnectionErrorState, if any errors have occured. Method returns a State, if there are no
     * errors and there is a successor state
     */
    @Override
    public State next() {
        // if errors occured, go a handling state, otherwise defer back to pipe
        if ((errors == null || errors.isEmpty()) && nextState == null) {
            return null;
        } else {
            if (errors != null && !errors.isEmpty()) {
                return new ConnectionErrorState(errors);
            } else {
                return nextState;
            }
        }

    }

    public UDIGConnectionFactoryDescriptor getDescriptor() {
        return descriptor;
    }

    public UDIGConnectionFactory getConnectionFactory() {
        return factory;
    }

    public Collection<IService> getServices() {
        return services;
    }

    @Override
    public String getName() {
        return Messages.ConnectionState_name;
    }

    public boolean isValidateState() {
        return validateServices;
    }

    public void setValidateState( boolean validateState ) {
        this.validateServices = validateState;
    }

    public Map<IService, Throwable> getErrors() {
        if (errors == null)
            return Collections.emptyMap();
        return errors;
    }

    /**
     * 52�North added
     *
     * @param state
     */
    public void setNextState( EndConnectionState state ) {
        nextState = state;
    }

    /**
     * Sets the collection of "Selected" or "preferred" resources. This allows the connection page
     * to specify a set of preferred resource for the next states.
     *
     * @param resourceIDs the ids of the preferred resources
     */
    public void setSelectedResources( Collection<URL> resourceIDs ) {
        this.selectedResources = new ArrayList<URL>(resourceIDs);
    }

    /**
     * Returns the collection of "Selected" or "preferred" resources. This allows the connection page
     * to specify a set of preferred resource for the next states. returns the ids of the preferred
     * resources
     */
    public Collection<URL> getSelectedResources() {
        if( selectedResources==null ){
            return Collections.emptyList();
        }
        return selectedResources;
    }

    public void setServices( Collection<IService> services2 ) {
        disposeOldServices(new NullProgressMonitor());
        services.addAll(services2);
    }

}
TOP

Related Classes of org.locationtech.udig.catalog.ui.workflow.EndConnectionState

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.