/*******************************************************************************
* 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.mercator.delegate;
import gov.nasa.worldwind.avlist.AVList;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.w3c.dom.Element;
import au.gov.ga.earthsci.worldwind.common.layers.delegate.IDelegate;
import au.gov.ga.earthsci.worldwind.common.layers.delegate.IDelegatorTile;
import au.gov.ga.earthsci.worldwind.common.layers.delegate.ITileURLBuilderDelegate;
/**
* {@link ITileURLBuilderDelegate} implementation that builds tile URLs for
* certain mercator dataset servers. The delegate definition string can define a
* url that contains placeholders which get replaced by tile parameters such as
* the service url, dataset, level, row and column.
* <p>
* <code><Delegate>MercatorTileURLBuilder(skipLevels,{format})</Delegate></code>
* <p>
* <ul>
* <li><code>skipLevels</code> = number of levels to skip in the source dataset</li>
* <li>
* <code>format</code> = URL format string containing tile parameter
* placeholders. Must be surrounded by braces { }. The following placeholders
* are supported:
* <ul>
* <li><code>%service%</code> = replaced with the service url</li>
* <li><code>%dataset%</code> = replaced with the dataset name</li>
* <li><code>%level%</code> = replaced with the tile's level</li>
* <li><code>%row%</code> = replaced with the tile's row</li>
* <li><code>%column%</code> = replaced with the tile's column</li>
* </ul>
* For example, <code>%service%%level%/%column%/%row%.png</code>, where
* (service=http://a.tile.openstreetmap.org/, level=2, column=1, row=0), would
* result in the following URL:
* <code>http://a.tile.openstreetmap.org/2/1/0.png</code>.</li>
* </ul>
*
* @author Michael de Hoog (michael.dehoog@ga.gov.au)
*/
public class MercatorTileURLBuilderDelegate implements ITileURLBuilderDelegate
{
protected final static String DEFINITION_STRING = "MercatorTileURLBuilder";
protected final static String SERVICE_PLACEHOLDER = "%service%";
protected final static String DATASET_PLACEHOLDER = "%dataset%";
protected final static String LEVEL_PLACEHOLDER = "%level%";
protected final static String ROW_PLACEHOLDER = "%row%";
protected final static String COLUMN_PLACEHOLDER = "%column%";
protected final int skipLevels;
protected final String format;
@SuppressWarnings("unused")
private MercatorTileURLBuilderDelegate()
{
this(3, "%service%%level%/%column%/%row%.png");
}
public MercatorTileURLBuilderDelegate(int skipLevels, String format)
{
this.skipLevels = skipLevels;
this.format = format;
}
@Override
public IDelegate fromDefinition(String definition, Element layerElement, AVList params)
{
if (definition.startsWith(DEFINITION_STRING))
{
Pattern pattern = Pattern.compile("(?:\\((\\d+),\\{([^}]+)\\}\\))");
Matcher matcher = pattern.matcher(definition);
if (matcher.find())
{
int skipLevels = Integer.parseInt(matcher.group(1));
String format = matcher.group(2);
return new MercatorTileURLBuilderDelegate(skipLevels, format);
}
}
return null;
}
@Override
public String toDefinition(Element layerElement)
{
return DEFINITION_STRING + "(" + skipLevels + "," + format + ")";
}
@Override
public URL getRemoteTileURL(IDelegatorTile tile, String imageFormat) throws MalformedURLException
{
int level = tile.getLevelNumber() + skipLevels;
int column = tile.getColumn();
int row = (1 << level) - 1 - tile.getRow(); //reverse the row integer (mercator rows are top to bottom)
String url = format;
url = url.replaceAll(SERVICE_PLACEHOLDER, tile.getService());
url = url.replaceAll(DATASET_PLACEHOLDER, tile.getDataset());
url = url.replaceAll(LEVEL_PLACEHOLDER, level + "");
url = url.replaceAll(COLUMN_PLACEHOLDER, column + "");
url = url.replaceAll(ROW_PLACEHOLDER, row + "");
return new URL(url);
}
}