All Downloads are FREE. Search and download functionalities are using the official Maven repository.

it.tidalwave.geo.viewer.impl.DefaultGeoViewProviderManager Maven / Gradle / Ivy

/***********************************************************************************************************************
 *
 * forceTen - open source geography
 * Copyright (C) 2007-2012 by Tidalwave s.a.s. (http://www.tidalwave.it)
 *
 ***********************************************************************************************************************
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations under the License.
 *
 ***********************************************************************************************************************
 *
 * WWW: http://forceten.tidalwave.it
 * SCM: https://bitbucket.org/tidalwave/forceten-src
 *
 **********************************************************************************************************************/
package it.tidalwave.geo.viewer.impl;

import javax.annotation.Nonnull;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Provider;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.text.Collator;
import javax.swing.SwingUtilities;
import org.jdesktop.observablecollections.ObservableCollections;
import org.jdesktop.observablecollections.ObservableList;
import org.openide.util.Lookup;
import org.openide.util.Parameters;
import org.openide.util.RequestProcessor;
import it.tidalwave.util.logging.Logger;
import it.tidalwave.netbeans.windows.role.PresentationLocker;
import it.tidalwave.geo.Coordinate;
import it.tidalwave.geo.viewer.GeoViewProviderManager;
import it.tidalwave.geo.viewer.spi.GeoViewProviderSupport;
import it.tidalwave.geo.viewer.spi.GeoViewProvider;
import it.tidalwave.geo.viewer.impl.spi.VoidGeoViewProvider;
import org.netbeans.platformx.inject.api.Injector;

/***********************************************************************************************************************
 *
 * @author  Fabrizio Giudici
 * @version $Id$
 *
 **********************************************************************************************************************/
public class DefaultGeoViewProviderManager implements GeoViewProviderManager
  {
    private static final String CLASS = DefaultGeoViewProviderManager.class.getName();
    private static final Logger logger = Logger.getLogger(CLASS);

    private static final int PROVIDER_INITIALIZATION_TIMEOUT = 3000;

    private static final GeoViewProviderSupport VOID_GEO_VIEW_PROVIDER = new VoidGeoViewProvider();

    private static final Comparator COMP1 = new Comparator()
      {
        private final Collator collator = Collator.getInstance();

        @Override
        public int compare (final GeoViewProvider gp1, final GeoViewProvider gp2)
          {
            return collator.compare(gp1.getName(), gp2.getName());
          }
      };

    private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);

    @Inject
    protected Lookup lookup;

    @Inject
    protected Provider presentationLocker;
    
    protected final ObservableList geoViewProviders =
            ObservableCollections.observableList(new ArrayList());

    protected GeoViewProviderSupport selectedGeoViewProvider = VOID_GEO_VIEW_PROVIDER;

    /*******************************************************************************************************************
     *
     * {@inheritDoc}
     *
     ******************************************************************************************************************/
    @Override
    public void setSelectedGeoViewProvider (final @Nonnull GeoViewProvider selectedGeoViewProvider)
      {
        logger.fine("setSelectedGeoViewProvider(%s)", selectedGeoViewProvider);

        if (selectedGeoViewProvider == null) // FIXME: shouldn't be there, but it gets invoked at boot
          {
            return;
          }

        Parameters.notNull("selectedGeoViewProvider", selectedGeoViewProvider);
        assert selectedGeoViewProvider != null; // for FindBugs

        if (!selectedGeoViewProvider.isReady())
          {
            return;
          }

        final GeoViewProvider oldSelectedGeoViewProvider = this.selectedGeoViewProvider;
        final Coordinate centerPosition = this.selectedGeoViewProvider.getCenterPosition();
        final int zoom = this.selectedGeoViewProvider.getZoom() - this.selectedGeoViewProvider.getMaximumZoomLevel();
        final GeoViewProvider.LifeCycle oldLifeCycle = this.selectedGeoViewProvider;

        presentationLocker.get().lock("");

        oldLifeCycle.deactivating();
        selectedGeoViewProvider.setCoordinatesTracker(GeoViewProvider.CoordinateTracker.VOID);
        oldLifeCycle.deactivated();
        this.selectedGeoViewProvider = (GeoViewProviderSupport)selectedGeoViewProvider; // FIXME: drop the cast
        final GeoViewProvider.LifeCycle newLifeCycle = this.selectedGeoViewProvider;
        newLifeCycle.activating();

        if (centerPosition != null)
          {
            try
              {
                selectedGeoViewProvider.setCenterPosition(centerPosition);
              }
            catch (Exception e) // FIXME: the above gives problems with WWJ
              {
                logger.severe(e.toString());
              }

            selectedGeoViewProvider.setZoom(zoom + selectedGeoViewProvider.getMaximumZoomLevel());
          }

        newLifeCycle.activated();
        presentationLocker.get().unlock();
        propertyChangeSupport.firePropertyChange(PROP_SELECTED_GEO_VIEW_PROVIDER, oldSelectedGeoViewProvider, selectedGeoViewProvider);
      }

    /*******************************************************************************************************************
     *
     * {@inheritDoc}
     *
     ******************************************************************************************************************/
    @Override
    @Nonnull
    public GeoViewProvider getSelectedGeoViewProvider()
      {
        return selectedGeoViewProvider;
      }

    /*******************************************************************************************************************
     *
     * {@inheritDoc}
     *
     ******************************************************************************************************************/
    @Override
    @Nonnull
    public ObservableList getGeoViewProviders()
      {
        return geoViewProviders;
      }

    /*******************************************************************************************************************
     *
     * {@inheritDoc}
     *
     ******************************************************************************************************************/
    @Override
    public void addPropertyChangeListener (final @Nonnull PropertyChangeListener listener)
      {
        propertyChangeSupport.addPropertyChangeListener(listener);
      }

    /*******************************************************************************************************************
     *
     * {@inheritDoc}
     *
     ******************************************************************************************************************/
    @Override
    public void removePropertyChangeListener (final @Nonnull PropertyChangeListener listener)
      {
        propertyChangeSupport.removePropertyChangeListener(listener);
      }
    
    /*******************************************************************************************************************
     *
     *
     *
     ******************************************************************************************************************/
    @PostConstruct
    @SuppressWarnings("PMD.UnusedPrivateMethod") @edu.umd.cs.findbugs.annotations.SuppressWarnings("UPM_UNCALLED_PRIVATE_METHOD")
    protected void initialize() // FIXME: make private once you can invoke it from tests
      {
        if (!SwingUtilities.isEventDispatchThread())
          {
            throw new IllegalStateException("Must be called inside the AWT Thread");
          }

        installProviders();
        selectInitialProvider();
      }

    /*******************************************************************************************************************
     *
     * Scans for all GeoViewProviders and puts them in the combobox model.
     *
     ******************************************************************************************************************/
    @edu.umd.cs.findbugs.annotations.SuppressWarnings("SIC_INNER_SHOULD_BE_STATIC_ANON")
    private void installProviders()
      {
        logger.info("installProviders()");
        
        geoViewProviders.clear();
        geoViewProviders.addAll(lookup.lookupAll(GeoViewProvider.class));
        Collections.sort(geoViewProviders, COMP1);

        logger.info(">>>> found GeoViewProviders: %s", geoViewProviders);
        
        for (final GeoViewProvider geoViewProvider : geoViewProviders)
          {
            logger.fine(">>>>>>>> initializing: %s...", geoViewProvider);
            Injector.getDefault().inject(geoViewProvider, lookup);
            RequestProcessor.getDefault().post(new Runnable()
              {
                 @Override
                 public void run()
                  {
                    geoViewProvider.initResources();
                  }
              });
          }
      }

    /*******************************************************************************************************************
     *
     * Select an initial provider. Providers are initialized in background to avoid blocking the GUI, but we have to
     * wait at least until the first provider is ready since having no selected provider would cause NPEs later.
     *
     ******************************************************************************************************************/
    private void selectInitialProvider()
      {
        logger.info("selectInitialProvider()");
        
        assert SwingUtilities.isEventDispatchThread() : "Must be called from the AWT Thread";
        final long startTime = System.currentTimeMillis();

        while (System.currentTimeMillis() - startTime < PROVIDER_INITIALIZATION_TIMEOUT)
          {
            for (final GeoViewProvider geoViewProvider : geoViewProviders)
              {
                logger.fine(">>>> %s is ready: %s", geoViewProvider, geoViewProvider.isReady());

                if (geoViewProvider.isReady())
                  {
                    logger.info(">>>> %s selected as default", geoViewProvider);
                    setSelectedGeoViewProvider(geoViewProvider);
                    return;
                  }
              }

            logger.warning("No providers ready, retrying...");

            try
              {
                Thread.sleep(100);
              }
            catch (InterruptedException e)
              {
                break;
              }
          }

        logger.severe("Couldn't set a default provider.");
      }
  }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy