/*
 *    GeoTools - The Open Source Java GIS Toolkit
 *    http://geotools.org
 *
 *    (C) 2002-2008, Open Source Geospatial Foundation (OSGeo)
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License as published by the Free Software Foundation;
 *    version 2.1 of the License.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 */

package org.geotools.swing.tool;

import java.lang.ref.WeakReference;
import java.util.logging.Logger;

import org.geotools.geometry.DirectPosition2D;
import org.geotools.map.MapContent;
import org.geotools.referencing.CRS;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;

/**
 * Abstract base class for helper classes used by {@code InfoTool} to query
 * {@code Layers}. The primary reason for having this class is to avoid
 * loading grid coverage classes unless they are really needed, and thus
 * avoid the need for users to have JAI in the classpath when working with
 * vector data.
 * <p>
 * The type parameter <code>&lt;T&gt;</code> defines the return type of the
 * {@linkplain #getInfo} method.
 *
 * @see InfoTool
 *
 * @author Michael Bedward
 * @since 2.6
 *
 *
 * @source $URL$
 * @version $URL$
 */
public abstract class InfoToolHelper<T> {
    private static final Logger LOGGER = Logger.getLogger(VectorLayerHelper.class.getName());

    private final WeakReference<MapContent> contentRef;
    private CoordinateReferenceSystem dataCRS;
    private boolean transformRequired;
    private boolean transformFailed;
    private MathTransform transform;

    /**
     * Protected constructor.
     *
     * @param content the map content
     * @param dataCRS the coordinate reference system of the feature data that will be queried
     *        by this helper
     */
    protected InfoToolHelper(MapContent content, CoordinateReferenceSystem dataCRS) {
        this.contentRef = new WeakReference<MapContent>(content);
        setCRS(dataCRS);
    }

    /**
     * Get feature data at the given position.
     *
     * @param pos the location to query
     *
     * @param params additional parameters as optionally defined by the sub-class
     *
     * @return data of type {@code T} as defined by the sub-class
     *
     * @see #isValid()
     */
    public abstract T getInfo(DirectPosition2D pos, Object ...params) throws Exception;

    /**
     * Query if this helper has a reference to a {@code MapContent} and {@code Layer}.
     * <p>
     * Helpers only hold a {@linkplain WeakReference} to the map content and layer
     * with which they are working to avoid blocking garbage collection when layers are
     * discarded. If this method returns {@code false} the helper should be re-created.
     * <pre><code>
     * //
     * // Example using a VectorLayerHelper...
     * //
     * VectorLayerHelper helper = ...
     *
     * if (helper != null && helper.isValid()) {
     *     FeatureCollection coll = helper.getInfo(queryLocation, ...);
     *     // do something useful with results
     *
     * } else {
     *     // (Re-)create the helper
     *     // Note: example only; this obviously depends on your use case
     *     helper = new VectorLayerHelper(content, layer);
     * }
     * </code></pre>
     *
     * @return
     */
    public abstract boolean isValid();

    /**
     * Get the {@code MapContent} associated with this helper. The helper maintains
     * only a {@linkplain WeakReference} to the content.
     *
     * @return the map content or null if it is no longer current.
     */
    public MapContent getMapContent() {
        return contentRef != null ? contentRef.get() : null;
    }

    /**
     * Check if queries with this helper involve transforming between coordinate
     * systems.
     *
     * @return true if coordinte transformation is required; false otherwise
     */
    protected boolean isTransformRequired() {
        return transformRequired;
    }

    /**
     * Get the {@code MathTransform} to re-project data from the coordinate system of
     * the {@code MapContent} to that of the {@code Layer}.
     *
     * @return the transform or {@code null} if either the layer's coordinate system is the same
     *         as that of the map content, or either has a {@code null} CRS.
     */
    public MathTransform getTransform() {
        if (transform == null && !transformFailed && dataCRS != null) {
            MapContent content = getMapContent();
            if (content == null) {
                throw new IllegalStateException("null map content");
            }

            CoordinateReferenceSystem contentCRS = content.getCoordinateReferenceSystem();
            try {
                transform = CRS.findMathTransform(contentCRS, dataCRS, true);
            } catch (Exception ex) {
                LOGGER.warning("Can't transform map content to layer CRS");
                transformFailed = true;
            }
        }

        return transform;
    }

    /**
     * Set the coordinate reference system that pertains to the feature data
     * that will be queried by this helper.
     *
     * @param crs data coordinate reference system
     */
    protected void setCRS(CoordinateReferenceSystem crs) {
        this.dataCRS = crs;

        MapContent content = getMapContent();
        if (content == null) {
            throw new IllegalStateException("null map content");
        }

        final CoordinateReferenceSystem contentCRS = content.getCoordinateReferenceSystem();
        transformRequired = false;
        if (contentCRS != null && crs != null && !CRS.equalsIgnoreMetadata(contentCRS, dataCRS)) {
            transformRequired = true;
        }
    }

}


@@ -92,14 +92,14 @@
  200
-2-2008
+8-2011
 , Op
@@ -865,16 +865,58 @@
 ng.CRS;%0A
+import org.geotools.util.logging.Logging;%0A
 import o
@@ -1654,18 +1654,19 @@
 R = Logg
-er
+ing
 .getLogg
@@ -1672,41 +1672,28 @@
 ger(
-VectorLayerHelper.class.getName()
+%22org.geotools.swing%22
 );%0A%0A
@@ -2284,17 +2284,19 @@
         
-s
+doS
 etCRS(da
@@ -5555,24 +5555,113 @@
 stem crs) %7B%0A
+        doSetCRS(crs);%0A    %7D%0A%0A    private void doSetCRS(CoordinateReferenceSystem crs) %7B%0A
         this
@@ -6111,12 +6111,11 @@
 %7D%0A    %7D%0A
-%0A
 %7D%0A%0A

Use GeoTools logging. Fix compiler warning about overridable method in constructor.