/*******************************************************************************
* 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.layers.delegate;
import gov.nasa.worldwind.avlist.AVList;
import gov.nasa.worldwind.globes.Globe;
import gov.nasa.worldwind.render.DrawContext;
import gov.nasa.worldwind.retrieve.RetrievalPostProcessor;
import gov.nasa.worldwind.retrieve.Retriever;
import gov.nasa.worldwind.util.TileKey;
import gov.nasa.worldwind.util.WWXML;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.xml.xpath.XPath;
import org.w3c.dom.Element;
/**
* Abstract generic implementation of the {@link IDelegateKit} interface. Stores
* the delegate objects for each of the delegate types, and forward the delegate
* interface functions to the stored delegate implementations.
*
* @author Michael de Hoog (michael.dehoog@ga.gov.au)
*/
public abstract class AbstractDelegateKit<TILE extends IDelegatorTile, BOUNDS, LEVEL> implements
IDelegateKit<TILE, BOUNDS, LEVEL>
{
//default delegate implementations
protected ITileRequesterDelegate<TILE> requesterDelegate;
protected ITileURLBuilderDelegate tileURLBuilderDelegate;
protected IRetrieverFactoryDelegate retrieverDelegate;
protected ITileFactoryDelegate<TILE, BOUNDS, LEVEL> factoryDelegate;
protected final List<ITileReaderDelegate> readerDelegates = new ArrayList<ITileReaderDelegate>();
protected final List<IImageTransformerDelegate> transformerDelegates = new ArrayList<IImageTransformerDelegate>();
protected final List<IRenderDelegate> renderDelegates = new ArrayList<IRenderDelegate>();
/**
* @return New instance of this {@link IDelegateKit}.
*/
protected abstract AbstractDelegateKit<TILE, BOUNDS, LEVEL> createNewInstance();
/**
* @return {@link IDelegateFactory} for this {@link IDelegateKit}.
*/
protected abstract IDelegateFactory getFactory();
@Override
public Collection<IDelegate> getDelegates()
{
Set<IDelegate> delegates = new HashSet<IDelegate>();
delegates.add(requesterDelegate);
delegates.add(retrieverDelegate);
delegates.add(factoryDelegate);
delegates.addAll(readerDelegates);
delegates.addAll(transformerDelegates);
delegates.addAll(renderDelegates);
return delegates;
}
@Override
public IDelegateKit<TILE, BOUNDS, LEVEL> createFromXML(Element domElement, AVList params)
{
AbstractDelegateKit<TILE, BOUNDS, LEVEL> kit = createNewInstance();
IDelegateFactory factory = getFactory();
XPath xpath = WWXML.makeXPath();
Element delegatesElement = WWXML.getElement(domElement, "Delegates", xpath);
if (delegatesElement != null)
{
Element[] elements = WWXML.getElements(delegatesElement, "Delegate", xpath);
if (elements != null)
{
for (Element element : elements)
{
String definition = element.getTextContent();
if (definition != null && definition.length() > 0)
{
IDelegate delegate = factory.createDelegate(definition, domElement, params);
if (!kit.trySetOrAddDelegate(delegate))
{
throw new IllegalArgumentException("Unrecognized delegate: " + delegate);
}
}
}
}
}
return kit;
}
/**
* Attempt to set or add a delegate; return false if this delegate is not
* recognized and therefore not set or added.
*/
protected boolean trySetOrAddDelegate(IDelegate delegate)
{
if (delegate instanceof IRetrieverFactoryDelegate)
{
setRetrieverFactoryDelegate((IRetrieverFactoryDelegate) delegate);
return true;
}
if (delegate instanceof ITileURLBuilderDelegate)
{
setTileURLBuilderDelegate((ITileURLBuilderDelegate) delegate);
return true;
}
if (delegate instanceof ITileReaderDelegate)
{
addTileReaderDelegate((ITileReaderDelegate) delegate);
return true;
}
if (delegate instanceof IImageTransformerDelegate)
{
addImageTransformerDelegate((IImageTransformerDelegate) delegate);
return true;
}
if (delegate instanceof IRenderDelegate)
{
addRenderDelegate((IRenderDelegate) delegate);
return true;
}
return false;
}
@Override
public Element saveToXML(Element context)
{
Collection<IDelegate> delegates = getDelegates();
Element delegatesElement = WWXML.appendElement(context, "Delegates");
for (IDelegate delegate : delegates)
{
String definition = delegate.toDefinition(context);
//only append the XML element if the delegate is not one of the defaults
if (!isDefault(definition))
{
WWXML.appendText(delegatesElement, "Delegate", definition);
}
}
return context;
}
/* ********************
* Setters and adders *
******************** */
@Override
public void setTileFactoryDelegate(ITileFactoryDelegate<TILE, BOUNDS, LEVEL> delegate)
{
this.factoryDelegate = delegate;
}
@Override
public void setTileURLBuilderDelegate(ITileURLBuilderDelegate delegate)
{
this.tileURLBuilderDelegate = delegate;
}
@Override
public void setRetrieverFactoryDelegate(IRetrieverFactoryDelegate delegate)
{
this.retrieverDelegate = delegate;
}
@Override
public void setTileRequesterDelegate(ITileRequesterDelegate<TILE> delegate)
{
this.requesterDelegate = delegate;
}
@Override
public void addTileReaderDelegate(ITileReaderDelegate delegate)
{
readerDelegates.add(delegate);
}
@Override
public void addRenderDelegate(IRenderDelegate delegate)
{
renderDelegates.add(delegate);
}
@Override
public void addImageTransformerDelegate(IImageTransformerDelegate delegate)
{
transformerDelegates.add(delegate);
}
/* ******************************
* Delegate Interface functions *
****************************** */
@Override
public BufferedImage transformImage(BufferedImage image, IDelegatorTile tile)
{
for (IImageTransformerDelegate transformer : transformerDelegates)
{
image = transformer.transformImage(image, tile);
}
return image;
}
@Override
public <T extends IDelegatorTile> BufferedImage readImage(T tile, URL url, Globe globe) throws IOException
{
for (ITileReaderDelegate reader : readerDelegates)
{
BufferedImage image = reader.readImage(tile, url, globe);
if (image != null)
return image;
}
return null;
}
@Override
public TILE createTextureTile(BOUNDS bounds, LEVEL level, int row, int col)
{
return factoryDelegate.createTextureTile(bounds, level, row, col);
}
@Override
public TileKey transformTileKey(TileKey tileKey)
{
return factoryDelegate.transformTileKey(tileKey);
}
@Override
public Retriever createRetriever(URL url, RetrievalPostProcessor postProcessor)
{
return retrieverDelegate.createRetriever(url, postProcessor);
}
@Override
public void forceTextureLoad(TILE tile, IDelegatorLayer<TILE> layer)
{
requesterDelegate.forceTextureLoad(tile, layer);
}
@Override
public URL getLocalTileURL(TILE tile, IDelegatorLayer<TILE> layer, boolean searchClassPath)
{
return requesterDelegate.getLocalTileURL(tile, layer, searchClassPath);
}
@Override
public Runnable createRequestTask(TILE tile, IDelegatorLayer<TILE> layer)
{
return requesterDelegate.createRequestTask(tile, layer);
}
@Override
public URL getRemoteTileURL(IDelegatorTile tile, String imageFormat) throws java.net.MalformedURLException
{
if (tileURLBuilderDelegate != null)
return tileURLBuilderDelegate.getRemoteTileURL(tile, imageFormat);
return tile.getResourceURL(imageFormat);
}
@Override
public void preRender(DrawContext dc)
{
for (IRenderDelegate renderDelegate : renderDelegates)
{
renderDelegate.preRender(dc);
}
}
@Override
public void postRender(DrawContext dc)
{
for (IRenderDelegate renderDelegate : renderDelegates)
{
renderDelegate.postRender(dc);
}
}
@Override
public IDelegate fromDefinition(String definition, Element layerElement, AVList params)
{
return null;
}
@Override
public String toDefinition(Element layerElement)
{
return null;
}
}