/******************************************************************************* * Copyright 2012 Geoscience Australia * * 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. ******************************************************************************/ package au.gov.ga.earthsci.worldwind.common.retrieve; import gov.nasa.worldwind.globes.ElevationModel; import gov.nasa.worldwind.layers.BasicTiledImageLayer; import gov.nasa.worldwind.layers.Layer; import gov.nasa.worldwind.layers.TiledImageLayer; import gov.nasa.worldwind.layers.mercator.BasicMercatorTiledImageLayer; import gov.nasa.worldwind.layers.mercator.MercatorTiledImageLayer; import gov.nasa.worldwind.layers.placename.PlaceNameLayer; import gov.nasa.worldwind.layers.rpf.RPFTiledImageLayer; import gov.nasa.worldwind.render.SurfaceImage; import gov.nasa.worldwind.retrieve.RetrievalPostProcessor; import gov.nasa.worldwind.retrieve.Retriever; import gov.nasa.worldwind.retrieve.URLRetriever; import gov.nasa.worldwind.terrain.BasicElevationModel; import gov.nasa.worldwind.util.Tile; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import au.gov.ga.earthsci.worldwind.common.layers.data.AbstractDataProvider; import au.gov.ga.earthsci.worldwind.common.layers.geonames.GeoNamesLayer; import au.gov.ga.earthsci.worldwind.common.layers.tiled.image.delegate.DelegatorTiledImageLayer; /** * Helper class for pulling out {@link Tile}s, {@link Layer}s, or * {@link ElevationModel}s from a {@link Retriever} object. Uses reflection to * access private fields. * * @author Michael de Hoog (michael.dehoog@ga.gov.au) */ public class RetrievalListenerHelper { private static final Field[] LAYER_FIELDS; private static final Field[] ELEVATION_MODEL_FIELDS; private static final Field[] TILE_FIELDS; static { Class<?>[] classes = new Class<?>[] { DelegatorTiledImageLayer.class, TiledImageLayer.class, BasicElevationModel.class, BasicTiledImageLayer.class, PlaceNameLayer.class, RPFTiledImageLayer.class, SurfaceImage.class, MercatorTiledImageLayer.class, BasicMercatorTiledImageLayer.class, GeoNamesLayer.class, AbstractDataProvider.class }; // Search classes above for declared classes that implement // RetrivalPostProcess AND contain a Field which is a subclass of Tile, // and add those Fields to an array LAYER_FIELDS = getMatchingFieldsFromInnerImplementingClasses(classes, RetrievalPostProcessor.class, Layer.class); ELEVATION_MODEL_FIELDS = getMatchingFieldsFromInnerImplementingClasses(classes, RetrievalPostProcessor.class, ElevationModel.class); TILE_FIELDS = getMatchingFieldsFromInnerImplementingClasses(classes, RetrievalPostProcessor.class, Tile.class); } private static Field[] getMatchingFieldsFromInnerImplementingClasses(Class<?>[] search, Class<?> interfaceType, Class<?> fieldType) { List<Field> fields = new ArrayList<Field>(); for (Class<?> c : search) { //get a list of declared (inner) classes of the class Class<?>[] innerClasses = c.getDeclaredClasses(); for (Class<?> innerClass : innerClasses) { if (interfaceType.isAssignableFrom(innerClass)) { Field[] declaredFields = innerClass.getDeclaredFields(); for (Field field : declaredFields) { if (fieldType.isAssignableFrom(field.getType())) { field.setAccessible(true); fields.add(field); } } } } } return fields.toArray(new Field[fields.size()]); } /** * Get a {@link Layer} from the given {@link Retriever} (if the Retriever * has been instanciated by a Layer). * * @param retriever * @return Layer that instanciated the given Retriever. */ public static Layer getLayer(Retriever retriever) { return getObject(retriever, LAYER_FIELDS, Layer.class); } /** * Get an {@link ElevationModel} from the given {@link Retriever} (if the * Retriever has been instanciated by an ElevationModel). * * @param retriever * @return ElevationModel that instanciated the given Retriever. */ public static ElevationModel getElevationModel(Retriever retriever) { return getObject(retriever, ELEVATION_MODEL_FIELDS, ElevationModel.class); } /** * Get a {@link Tile} from the given {@link Retriever} (if the Retriever was * created to download a Tile). * * @param retriever * @return Tile for the given Retriever. */ public static Tile getTile(Retriever retriever) { return getObject(retriever, TILE_FIELDS, Tile.class); } private static <E> E getObject(Retriever retriever, Field[] fields, Class<? extends E> type) { if (retriever instanceof URLRetriever) { URLRetriever ur = (URLRetriever) retriever; RetrievalPostProcessor rpp = ur.getPostProcessor(); for (Field field : fields) { if (field.getDeclaringClass().isAssignableFrom(rpp.getClass())) { try { Object object = field.get(rpp); if (object != null && type.isAssignableFrom(object.getClass())) { return type.cast(object); } } catch (Exception e) { } } } } return null; } }