/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* (c) 2014 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.rest.ecql;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.geoserver.catalog.Catalog;
import org.geoserver.platform.ExtensionPriority;
import org.geoserver.rest.util.RESTUploadPathMapperImpl;
import org.geoserver.rest.util.RESTUtils;
import org.geotools.data.DataUtilities;
import org.geotools.feature.SchemaException;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.filter.FilterAttributeExtractor;
import org.geotools.filter.text.cql2.CQLException;
import org.geotools.filter.text.ecql.ECQL;
import org.geotools.util.logging.Logging;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.filter.expression.Expression;
/**
* RESTUploadPathMapper implementation which executes a CQL expression on the input file name for remapping it
*
* @author Nicola Lagomarsini Geosolutions S.A.S.
*/
public class RESTUploadECQLPathMapper extends RESTUploadPathMapperImpl implements ExtensionPriority {
private static Logger LOGGER = Logging
.getLogger("org.geoserver.rest.cql.RESTUploadCQLPathMapper");
/** MetadataMap key associated to the expression value */
public static final String EXPRESSION_KEY = "expression";
public static final String PATH = "path";
public static final String NAME = "name";
/** Feature type used for creating the input feature associated to the item path */
private static SimpleFeatureType typePath;
/** Feature type used for creating the input feature associated to the item name */
private static SimpleFeatureType typeName;
/** Feature type used for creating the input feature associated to the item name and path */
private static SimpleFeatureType typeAll;
private static FilterAttributeExtractor extractor;
// Feature type initialization
static {
try {
typePath = DataUtilities.createType("type", PATH + ":string");
typeName = DataUtilities.createType("type", NAME + ":string");
typeAll = DataUtilities.createType("type", PATH + ":string," + NAME + ":string");
} catch (SchemaException e) {
LOGGER.log(Level.WARNING, e.getMessage(), e);
}
// Static initialization of an Attribute extractor for checking the attributes inside the ECQL expression
extractor = new FilterAttributeExtractor();
}
public RESTUploadECQLPathMapper(Catalog catalog) {
super(catalog);
}
public void mapItemPath(String workspace, String store, Map<String, String> storeParams,
StringBuilder itemPath, String itemName) throws IOException {
// expression to use for remapping
Expression expression = null;
// Extraction of the ECQL expression from the metadata map
try {
expression = getExpression(workspace, store, catalog);
} catch (CQLException e) {
LOGGER.log(Level.WARNING, e.getMessage(), e);
}
// No expression found, so nothing is executed
if (expression == null) {
return;
}
// extraction of the attributes of the ECQL expression
expression.accept(extractor, null);
List<String> attributes = Arrays.asList(extractor.getAttributeNames());
// Feature associated to the input path
SimpleFeature feature = null;
if (attributes != null) {
if (attributes.contains(PATH)) {
if (attributes.contains(NAME)) {
feature = SimpleFeatureBuilder.build(typeAll, new Object[] { itemPath.toString(),
itemName }, null);
} else {
feature = SimpleFeatureBuilder.build(typePath,
new Object[] { itemPath.toString() }, null);
}
} else if (attributes.contains(NAME)) {
feature = SimpleFeatureBuilder.build(typeName, new Object[] { itemName }, null);
}
}else{
feature = SimpleFeatureBuilder.build(typeAll, new Object[] { itemPath.toString(),
itemName }, null);
}
if (feature == null) {
return;
}
// Perform Regular Expression match
String newPath = expression.evaluate(feature, String.class);
// If nothing is returned, then the initial path is left untouched
if (newPath == null || newPath.isEmpty()) {
return;
}
// Removal of the old input path
itemPath.setLength(0);
// Setting of the new item path
itemPath.append(newPath);
}
@Override
public int getPriority() {
return 1;
}
public static Expression getExpression(String workspaceName, String storeName, Catalog catalog)
throws CQLException {
String expression = RESTUtils.getItem(workspaceName, storeName, catalog, EXPRESSION_KEY);
// returns the expression if not null
if (expression != null) {
return ECQL.toExpression(expression);
}
return null;
}
}