/* * Geotoolkit - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2008 - 2011, 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.map; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.logging.Level; import org.apache.sis.feature.FeatureExt; import org.geotoolkit.data.FeatureCollection; import org.geotoolkit.data.FeatureIterator; import org.geotoolkit.data.query.Query; import org.geotoolkit.data.query.QueryBuilder; import org.geotoolkit.filter.visitor.ListingPropertyVisitor; import org.apache.sis.geometry.Envelope2D; import org.apache.sis.storage.DataStoreException; import org.geotoolkit.style.MutableStyle; import static org.apache.sis.util.ArgumentChecks.*; import org.apache.sis.measure.NumberRange; import org.apache.sis.measure.Range; import org.geotoolkit.util.collection.NotifiedCheckedList; import org.opengis.feature.Feature; import org.opengis.filter.expression.Expression; import org.opengis.geometry.Envelope; import org.opengis.referencing.crs.CoordinateReferenceSystem; /** * Default implementation of the MapLayer. * * @author Johann Sorel (Geomatys) * @module */ final class DefaultFeatureMapLayer extends DefaultCollectionMapLayer implements FeatureMapLayer { private Query query = null; private final List<DimensionDef> extraDims = new NotifiedCheckedList<DimensionDef>(DimensionDef.class) { @Override protected void notifyAdd(DimensionDef item, int index) { firePropertyChange(PROP_EXTRA_DIMENSIONS, null, extraDims); } @Override protected void notifyAdd(Collection<? extends DimensionDef> items, NumberRange<Integer> range) { firePropertyChange(PROP_EXTRA_DIMENSIONS, null, extraDims); } @Override protected void notifyChange(DimensionDef oldItem, DimensionDef newItem, int index) { firePropertyChange(PROP_EXTRA_DIMENSIONS, null, extraDims); } @Override protected void notifyRemove(DimensionDef item, int index) { firePropertyChange(PROP_EXTRA_DIMENSIONS, null, extraDims); } @Override protected void notifyRemove(Collection<? extends DimensionDef> items, NumberRange<Integer> range) { firePropertyChange(PROP_EXTRA_DIMENSIONS, null, extraDims); } }; /** * Creates a new instance of DefaultFeatureMapLayer * * @param collection : the data source for this layer * @param style : the style used to represent this layer */ DefaultFeatureMapLayer(final FeatureCollection collection, final MutableStyle style) { super(collection,style); } /** * {@inheritDoc } */ @Override public Query getQuery() { if(query == null){ query = QueryBuilder.all(getCollection().getFeatureType().getName()); } return query; } /** * Sets a filter query for this layer. * * <p> * Query filters should be used to reduce searched or displayed feature * when rendering or analyzing this layer. * </p> * * @param query the full filter for this layer. can not be null. */ @Override public void setQuery(final Query query) { ensureNonNull("query", query); final Query oldQuery; synchronized (this) { oldQuery = getQuery(); if(oldQuery.equals(query)){ return; } this.query = query; } firePropertyChange(QUERY_PROPERTY, oldQuery, this.query); } /** * {@inheritDoc } */ @Override public FeatureCollection getCollection() { return (FeatureCollection) super.getCollection(); } /** * {@inheritDoc } */ @Override public Envelope getBounds() { final FeatureCollection featureCol = getCollection(); final CoordinateReferenceSystem sourceCrs = FeatureExt.getCRS(featureCol.getFeatureType()); Envelope env = null; try { env = featureCol.getEnvelope(); } catch (DataStoreException e) { LOGGER.log(Level.WARNING, "Could not create referecenced envelope.",e); } if(env == null){ //no data //never return a null envelope, we better return an infinite envelope env = new Envelope2D(sourceCrs,Double.NaN,Double.NaN,Double.NaN,Double.NaN); // Envelope crsEnv = CRS.getEnvelope(sourceCrs); // if(crsEnv != null){ // //we couldn't estime the features envelope, return the crs envelope if possible // //we assume the features are not out of the crs valide envelope // env = new GeneralEnvelope(crsEnv); // }else{ // //never return a null envelope, we better return an infinite envelope // env = new Envelope2D(sourceCrs,Double.NaN,Double.NaN,Double.NaN,Double.NaN); // } } return env; } @Override public List<DimensionDef> getExtraDimensions() { return extraDims; } @Override public Collection<Range> getDimensionRange(final DimensionDef def) throws DataStoreException{ final List<Range> values = new ArrayList<Range>(); final Expression lower = def.getLower(); final Expression upper = def.getUpper(); final Set<String> properties = new HashSet<String>(); lower.accept(ListingPropertyVisitor.VISITOR, properties); upper.accept(ListingPropertyVisitor.VISITOR, properties); final QueryBuilder qb = new QueryBuilder(); qb.setTypeName(getCollection().getFeatureType().getName()); qb.setProperties(properties.toArray(new String[properties.size()])); final FeatureCollection col = getCollection().subCollection(qb.buildQuery()); final FeatureIterator ite = col.iterator(); while(ite.hasNext()){ Feature f = ite.next(); final Comparable c1 = (Comparable) lower.evaluate(f); final Comparable c2 = (Comparable) upper.evaluate(f); values.add( new Range(Comparable.class, c1, true, c2, true)); } ite.close(); return values; } }