/**
* This program 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, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @author Gabriel Roldan (OpenGeo) 2010
*
*/
package org.geowebcache.georss;
import java.io.IOException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.geowebcache.grid.GridSubset;
import org.geowebcache.layer.TileLayer;
import org.geowebcache.storage.GeometryRasterMaskBuilder;
import com.vividsolutions.jts.geom.Geometry;
/**
* Consumes a GeoRSS feed and creates a tile range filter based on the feed's geometries for the
* given tiled layer.
* <p>
* I'm not sure yet where the georss seeding will be launched from. In any case, whether it is a
* user call or a triggered by a configuration option every X time, it should use this class.
* </p>
*/
class GeoRSSTileRangeBuilder {
private static final Log logger = LogFactory.getLog(GeoRSSTileRangeBuilder.class);
private final TileLayer layer;
private final String gridSetId;
private final int maxMaskLevel;
/**
* Keeps track of the most current GeoRSS entry "updated" property
*/
private String lastEntryUpdate;
/**
*
* @param layer
* The layer to create the mask of affected tiles for
* @param gridSetId
* the gridset identifier of the layer
* @param maxMaskLevel
* index of the maximum zoom level for which to create a tile matrix for, meaning
* greater levels will be downsampled to save memory
*/
public GeoRSSTileRangeBuilder(final TileLayer layer, final String gridSetId,
final int maxMaskLevel) {
if (layer == null) {
throw new NullPointerException("layer");
}
if (gridSetId == null) {
throw new NullPointerException("griSetId");
}
if (maxMaskLevel < 0) {
throw new IllegalArgumentException("maxMaskLevel shall be >= 0: " + maxMaskLevel);
}
this.layer = layer;
this.gridSetId = gridSetId;
this.maxMaskLevel = maxMaskLevel;
this.lastEntryUpdate = "";
final GridSubset gridSubset = layer.getGridSubset(gridSetId);
if (gridSubset == null) {
throw new IllegalArgumentException("no grid subset " + gridSetId + " at "
+ layer.getName());
}
}
public GeometryRasterMaskBuilder buildTileRangeMask(final GeoRSSReader reader,
String previousEntryUpdate) throws IOException {
final GridSubset gridSubset = layer.getGridSubset(gridSetId);
final int[] metaTilingFactors = layer.getMetaTilingFactors();
GeometryRasterMaskBuilder matrix = null;
Entry entry;
Geometry geom;
try {
while ((entry = reader.nextEntry()) != null) {
if (entry.getUpdated() != null && entry.getUpdated().equals(previousEntryUpdate)) {
logger.warn("Skipping entry with id " + entry.getId()
+ " since it has the same date as our last feed update.");
} else {
if (matrix == null) {
matrix = new GeometryRasterMaskBuilder(gridSubset, metaTilingFactors,
maxMaskLevel);
}
// Record the most recent updated entry. Date comparison
// done on the String as the format is like
// "2010-03-02T15:51:55Z" with the most significant part
// first.
if ((entry.getUpdated() != null)
&& ((lastEntryUpdate == null) || (lastEntryUpdate.compareTo(entry
.getUpdated()) < 0))) {
lastEntryUpdate = entry.getUpdated();
}
geom = entry.getWhere();
matrix.setMasksForGeometry(geom);
}
}
} finally {
if (matrix != null) {
matrix.disposeGraphics();
}
}
return matrix;
}
/**
* Returns the value of the most recent updated property value out of all the georss entries
* processed at {@link #buildTileRangeMask(GeoRSSReader)}
*
* @return the latest georss updated value, or {@code null} if none was processed
*/
public String getLastEntryUpdate() {
return lastEntryUpdate;
}
}