/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2008 - 2013, Geomatys
*
* This library 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;
* version 2.1 of the License.
*
* This library 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
* Lesser General Public License for more details.
*/
package org.geotoolkit.display2d.primitive;
import java.util.Collections;
import java.util.logging.Level;
import org.apache.sis.feature.FeatureExt;
import org.apache.sis.internal.feature.AttributeConvention;
import org.apache.sis.storage.DataStoreException;
import org.apache.sis.util.logging.Logging;
import org.geotoolkit.data.FeatureCollection;
import org.geotoolkit.data.FeatureIterator;
import org.geotoolkit.data.query.QueryBuilder;
import org.geotoolkit.display2d.GO2Utilities;
import static org.geotoolkit.display2d.GO2Utilities.FILTER_FACTORY;
import org.geotoolkit.display2d.canvas.RenderingContext2D;
import org.geotoolkit.display2d.canvas.J2DCanvas;
import org.geotoolkit.display2d.container.stateless.StatelessContextParams;
import static org.geotoolkit.display2d.primitive.DefaultProjectedObject.DEFAULT_GEOM;
import org.geotoolkit.map.FeatureMapLayer;
import org.opengis.feature.Feature;
import org.opengis.feature.FeatureType;
import org.opengis.feature.PropertyNotFoundException;
import org.opengis.feature.PropertyType;
import org.opengis.filter.Filter;
import org.opengis.filter.expression.Expression;
import org.opengis.filter.expression.PropertyName;
import org.opengis.filter.identity.FeatureId;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
/**
* Convenient representation of a feature for rendering.
*
* Not thread safe.
* Use it knowing you make clear cache operation in a synchronize way.
*
* @author Johann Sorel (Geomatys)
* @module
*/
public class ProjectedFeature extends DefaultProjectedObject<Feature> {
private final boolean fullFeature;
public ProjectedFeature(final J2DCanvas canvas, final FeatureMapLayer layer, final Feature feature){
super(new StatelessContextParams(canvas,layer),feature);
final RenderingContext2D context = new RenderingContext2D(canvas);
canvas.prepareContext(context, null, null);
params.update(context);
fullFeature = true;
}
public ProjectedFeature(final StatelessContextParams<FeatureMapLayer> params){
this(params,null);
}
public ProjectedFeature(final StatelessContextParams<FeatureMapLayer> params,
final Feature feature){
super(params,feature);
fullFeature = false;
}
/**
* Get the feature itself.
*
* @return Feature
*/
@Override
public Feature getCandidate(){
if(fullFeature){
try {
return getCompleteFeature(getFeatureId());
} catch (DataStoreException ex) {
Logging.getLogger("org.geotoolkit.display2d.primitive").log(Level.WARNING, null, ex);
}
}
//worst case, return the partial feature
return candidate;
}
@Override
public ProjectedGeometry getGeometry(Expression geomExp) {
if(geomExp == null) geomExp = DEFAULT_GEOM;
ProjectedGeometry proj = geometries.get(geomExp);
CoordinateReferenceSystem dataCRS = null;
if(proj == null){
final FeatureType featuretype = candidate.getType();
PropertyType prop = null;
if(!isNullorEmpty(geomExp)) {
if(geomExp instanceof PropertyName){
prop = featuretype.getProperty(((PropertyName)geomExp).getPropertyName());
}else{
//calculated geometry
}
}else if(featuretype != null){
try{
prop = featuretype.getProperty(AttributeConvention.GEOMETRY_PROPERTY.toString());
}catch(PropertyNotFoundException ex){
}
}
if(prop != null){
dataCRS = FeatureExt.getCRS(prop);
}
proj = new ProjectedGeometry(params);
geometries.put(geomExp, proj);
}
//check that the geometry is set
if(!proj.isSet()){
proj.setDataGeometry(GO2Utilities.getGeometry(candidate, geomExp),dataCRS);
}
return proj;
}
private static boolean isNullorEmpty(Expression exp){
if(exp==null || exp==Expression.NIL){
return true;
}else if(exp instanceof PropertyName){
final PropertyName pn = (PropertyName) exp;
final String str = pn.getPropertyName();
if(str==null || str.trim().isEmpty()){
return true;
}
}
return false;
}
/**
* Get the original FeatureMapLayer from where the feature is from.
*
* @return FeatureMapLayer
*/
@Override
public FeatureMapLayer getLayer() {
return (FeatureMapLayer) params.layer;
}
/**
* Get the id of the feature.
*
* @return FeatureId
*/
public FeatureId getFeatureId() {
return FeatureExt.getId(candidate);
}
private Feature getCompleteFeature(final FeatureId id)throws DataStoreException{
final FeatureMapLayer fml = (FeatureMapLayer) params.layer;
if(fml != null){
final Filter filter = FILTER_FACTORY.id(Collections.singleton(id));
Feature feature = null;
final FeatureCollection collection =
fml.getCollection().subCollection(
QueryBuilder.filtered(fml.getCollection().getFeatureType().getName().toString(), filter));
if(!collection.isEmpty()){
final FeatureIterator ite = collection.iterator();
if(ite.hasNext()){
feature = ite.next();
}
ite.close();
}
if(feature == null){
//worst case, return the partial feature
return this.candidate;
}
return feature;
}else{
//worst case, return the partial feature
return candidate;
}
}
}