All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.geotools.data.view.DefaultView Maven / Gradle / Ivy

Go to download

The main module contains the GeoTools public interfaces that are used by other GeoTools modules (and GeoTools applications). Where possible we make use industry standard terms as provided by OGC and ISO standards. The formal GeoTools public api consists of gt-metadata, jts and the gt-main module. The main module contains the default implementations that are available provided to other GeoTools modules using our factory system. Factories are obtained from an appropriate FactoryFinder, giving applications a chance configure the factory used using the Factory Hints facilities. FilterFactory ff = CommonFactoryFinder.getFilterFactory(); Expression expr = ff.add( expression1, expression2 ); If you find yourself using implementation specific classes chances are you doing it wrong: Expression expr = new AddImpl( expression1, expressiom2 );

The newest version!
/*
 *    GeoTools - The Open Source Java GIS Toolkit
 *    http://geotools.org
 *
 *    (C) 2004-2008, Open Source Geospatial Foundation (OSGeo)
 *
 *    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.geotools.data.view;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;
import org.geotools.data.DataSourceException;
import org.geotools.data.DataStore;
import org.geotools.data.DataUtilities;
import org.geotools.data.FeatureListener;
import org.geotools.data.FeatureSource;
import org.geotools.data.Query;
import org.geotools.data.QueryCapabilities;
import org.geotools.data.ResourceInfo;
import org.geotools.data.crs.ForceCoordinateSystemFeatureResults;
import org.geotools.data.crs.ReprojectFeatureResults;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.feature.SchemaException;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.Name;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory;
import org.opengis.referencing.crs.CoordinateReferenceSystem;

/**
 * Wrapper for SimpleFeatureSource constrained by a Query.
 *
 * 

Support SimpleFeatureSource decorator that takes care of mapping a Query & SimpleFeatureSource * with the schema and definition query configured for it. * *

Because GeoServer requires that attributes always be returned in the same order we need a way * to smoothly inforce this. Could we use this class to do so? * *

WARNING: this class is a placeholder for ideas right now - it may not always impement * FeatureSource. * * @author Gabriel Rold�n */ public class DefaultView implements SimpleFeatureSource { /** Shared package logger */ private static final Logger LOGGER = org.geotools.util.logging.Logging.getLogger(DefaultView.class); /** SimpleFeatureSource being served up */ protected SimpleFeatureSource source; /** Schema generated by provided constraintQuery */ private SimpleFeatureType schema; /** Query provided as a constraint */ private Query constraintQuery; /** * Creates a new GeoServerFeatureSource object. * *

Grabs the following from query: * *

    *
  • typeName - only used if client does not supply *
  • cs - only used if client does not supply *
  • csForce - only used if client does not supply *
  • filter - combined with client filter *
  • propertyNames - combined with client filter (indicate property names that *must* be * included) *
* * Schema is generated based on this information. * * @param source a FeatureSource * @param query Filter used to limit results */ public DefaultView(SimpleFeatureSource source, Query query) throws SchemaException { this.source = source; this.constraintQuery = query; SimpleFeatureType origionalType = source.getSchema(); CoordinateReferenceSystem cs = null; if (query.getCoordinateSystemReproject() != null) { cs = query.getCoordinateSystemReproject(); } else if (query.getCoordinateSystem() != null) { cs = query.getCoordinateSystem(); } schema = DataUtilities.createSubType( origionalType, query.getPropertyNames(), cs, query.getTypeName(), null); } /** * @see FeatureSource#getName() * @since 2.5 */ public Name getName() { return getSchema().getName(); } /** * Factory that make the correct decorator for the provided featureSource. * *

This factory method is public and will be used to create all required subclasses. By * comparison the constructors for this class have package visibiliy. TODO: revisit this - I am * not sure I want write access to views (especially if they do reprojection). */ public static SimpleFeatureSource create(SimpleFeatureSource source, Query query) throws SchemaException { return new DefaultView(source, query); } /** * Takes a query and adapts it to match re definitionQuery filter configured for a feature type. * It won't handle coordinate system changes * *

Grabs the following from query: * *

    *
  • typeName - only used if client does not supply *
  • filter - combined with client filter *
  • propertyNames - combined with client filter (indicate property names that *must* be * included) *
* * @param query Query against this DataStore * @return Query restricted to the limits of definitionQuery * @throws IOException See DataSourceException * @throws DataSourceException If query could not meet the restrictions of definitionQuery */ protected Query makeDefinitionQuery(Query query) throws IOException { if ((query == Query.ALL) || query.equals(Query.ALL)) { return new Query(constraintQuery); } try { String[] propNames = extractAllowedAttributes(query); String typeName = query.getTypeName(); if (typeName == null) { typeName = constraintQuery.getTypeName(); } URI namespace = query.getNamespace(); if (namespace == null || namespace == Query.NO_NAMESPACE) { namespace = constraintQuery.getNamespace(); } Filter filter = makeDefinitionFilter(query.getFilter()); int maxFeatures = Math.min(query.getMaxFeatures(), constraintQuery.getMaxFeatures()); String handle = query.getHandle(); if (handle == null) { handle = constraintQuery.getHandle(); } else if (constraintQuery.getHandle() != null) { handle = handle + "(" + constraintQuery.getHandle() + ")"; } Query Query = new Query(typeName, namespace, filter, maxFeatures, propNames, handle); Query.setSortBy(query.getSortBy()); return Query; } catch (Exception ex) { throw new DataSourceException( "Could not restrict the query to the definition criteria: " + ex.getMessage(), ex); } } /** * List of allowed attributes. * *

Creates a list of FeatureTypeInfo's attribute names based on the attributes requested by * query and making sure they not contain any non exposed attribute. * *

Exposed attributes are those configured in the "attributes" element of the * FeatureTypeInfo's configuration * * @param query User's origional query * @return List of allowed attribute types */ private String[] extractAllowedAttributes(Query query) { String[] propNames = null; if (query.retrieveAllProperties()) { propNames = new String[schema.getAttributeCount()]; for (int i = 0; i < schema.getAttributeCount(); i++) { propNames[i] = schema.getDescriptor(i).getLocalName(); } } else { String[] queriedAtts = query.getPropertyNames(); int queriedAttCount = queriedAtts.length; List allowedAtts = new LinkedList(); for (int i = 0; i < queriedAttCount; i++) { if (schema.getDescriptor(queriedAtts[i]) != null) { allowedAtts.add(queriedAtts[i]); } else { LOGGER.info( "queried a not allowed property: " + queriedAtts[i] + ". Ommitting it from query"); } } propNames = (String[]) allowedAtts.toArray(new String[allowedAtts.size()]); } return propNames; } /** * If a definition query has been configured for the FeatureTypeInfo, makes and return a new * Filter that contains both the query's filter and the layer's definition one, by logic AND'ing * them. * * @param filter Origional user supplied Filter * @return Filter adjusted to the limitations of definitionQuery * @throws DataSourceException If the filter could not meet the limitations of definitionQuery */ protected Filter makeDefinitionFilter(Filter filter) throws DataSourceException { Filter newFilter = filter; Filter constraintFilter = constraintQuery.getFilter(); try { if (constraintFilter != Filter.INCLUDE) { FilterFactory ff = CommonFactoryFinder.getFilterFactory(null); newFilter = ff.and(constraintFilter, filter); } } catch (Exception ex) { throw new DataSourceException("Can't create the constraint filter", ex); } return newFilter; } /** * Implement getDataStore. * *

Description ... * * @return @see org.geotools.data.FeatureSource#getDataStore() */ public DataStore getDataStore() { return (DataStore) source.getDataStore(); } /** * Implement addFeatureListener. * *

Description ... * * @see org.geotools.data.FeatureSource#addFeatureListener(org.geotools.data.FeatureListener) */ public void addFeatureListener(FeatureListener listener) { source.addFeatureListener(listener); } /** * Implement removeFeatureListener. * *

Description ... * * @see org.geotools.data.FeatureSource#removeFeatureListener(org.geotools.data.FeatureListener) */ public void removeFeatureListener(FeatureListener listener) { source.removeFeatureListener(listener); } /** * Implement getFeatures. * *

Description ... * * @see org.geotools.data.FeatureSource#getFeatures(org.geotools.data.Query) */ public SimpleFeatureCollection getFeatures(Query query) throws IOException { Query mergedQuery = makeDefinitionQuery(query); SimpleFeatureCollection results = source.getFeatures(mergedQuery); // Get all the coordinate systems involved in the two queries CoordinateReferenceSystem cCs = constraintQuery.getCoordinateSystem(); CoordinateReferenceSystem cCsr = constraintQuery.getCoordinateSystemReproject(); CoordinateReferenceSystem qCs = query.getCoordinateSystem(); CoordinateReferenceSystem qCsr = query.getCoordinateSystemReproject(); /* * Here we create all the needed transformations. We assume for the * moment that the data stores are incapable of any kind of cs * transformation and neither capable of forcing cs. We also assume that * concatenating multiple forced and reprojected wrappers is inexpensive * since they are optimized to recognize each other and to avoid useless * object creation */ try { if (qCsr != null && cCsr != null) { if (cCs != null) results = new ForceCoordinateSystemFeatureResults(results, cCs); results = new ReprojectFeatureResults(results, cCsr); if (qCs != null) results = new ForceCoordinateSystemFeatureResults(results, qCs); results = new ReprojectFeatureResults(results, qCsr); } else if (qCs != null && cCsr != null) { // complex case 2, reprojected then forced // mergedQuery.setCoordinateSystem(cCs); // mergedQuery.setCoordinateSystemReproject(cCsr); try { if (cCs != null) results = new ForceCoordinateSystemFeatureResults(results, cCs); results = new ReprojectFeatureResults(source.getFeatures(mergedQuery), cCsr); results = new ForceCoordinateSystemFeatureResults(results, qCs); } catch (SchemaException e) { throw new DataSourceException("This should not happen", e); } } else { // easy case, we can just put toghether one forced cs and one // reprojection cs // in the mixed query and let it go // mergedQuery.setCoordinateSystem(qCs != null ? qCs : cCs); // mergedQuery.setCoordinateSystemReproject(qCsr != null ? qCsr // : cCsr); CoordinateReferenceSystem forcedCS = qCs != null ? qCs : cCs; CoordinateReferenceSystem reprojectCS = qCsr != null ? qCsr : cCsr; if (forcedCS != null) results = new ForceCoordinateSystemFeatureResults(results, forcedCS); if (reprojectCS != null) results = new ReprojectFeatureResults(results, reprojectCS); } } catch (IOException e) { throw e; } catch (Exception e) { throw new DataSourceException( "A problem occurred while handling forced " + "coordinate systems and reprojection", e); } return results; } /** * Implement getFeatures. * *

Description ... */ public SimpleFeatureCollection getFeatures(Filter filter) throws IOException { return getFeatures(new Query(schema.getTypeName(), filter)); } /** * Implement getFeatures. * *

Description ... * * @see org.geotools.data.FeatureSource#getFeatures() */ public SimpleFeatureCollection getFeatures() throws IOException { return getFeatures(Query.ALL); } /** * Implement getSchema. * *

Description ... * * @return @see org.geotools.data.FeatureSource#getSchema() */ public SimpleFeatureType getSchema() { return schema; } public ResourceInfo getInfo() { return new ResourceInfo() { final Set words = new HashSet(); { words.add("features"); words.add("view"); words.add(DefaultView.this.getSchema().getTypeName()); } public ReferencedEnvelope getBounds() { try { return DefaultView.this.getBounds(); } catch (IOException e) { return null; } } public CoordinateReferenceSystem getCRS() { return DefaultView.this.getSchema().getCoordinateReferenceSystem(); } public String getDescription() { return null; } public Set getKeywords() { return words; } public String getName() { return DefaultView.this.getSchema().getTypeName(); } public URI getSchema() { Name name = DefaultView.this.getSchema().getName(); URI namespace; try { namespace = new URI(name.getNamespaceURI()); return namespace; } catch (URISyntaxException e) { return null; } } public String getTitle() { Name name = DefaultView.this.getSchema().getName(); return name.getLocalPart(); } }; } /** * Retrieves the total extent of this FeatureSource. * *

Please note this extent will reflect the provided definitionQuery. * * @return Extent of this FeatureSource, or null if no optimizations exist. * @throws IOException If bounds of definitionQuery */ public ReferencedEnvelope getBounds() throws IOException { if (constraintQuery.getCoordinateSystemReproject() == null) { if (constraintQuery.getFilter() == null || constraintQuery.getFilter() == Filter.INCLUDE || Filter.INCLUDE.equals(constraintQuery.getFilter())) { return source.getBounds(); } return source.getBounds(constraintQuery); } // this will create a feature results that can reproject the // features, and will // properly compute the bouds return getFeatures().getBounds(); } /** * Retrive the extent of the Query. * *

This method provides access to an optimized getBounds opperation. If no optimized * opperation is available null will be returned. * *

You may still make use of getFeatures( Query ).getCount() which will return the correct * answer (even if it has to itterate through all the results to do so. * * @param query User's query * @return Extend of Query or null if no optimization is available * @throws IOException If a problem is encountered with source */ public ReferencedEnvelope getBounds(Query query) throws IOException { if (constraintQuery.getCoordinateSystemReproject() == null) { try { query = makeDefinitionQuery(query); } catch (IOException ex) { return null; } return source.getBounds(query); } // this will create a feature results that can reproject the // features, and will // properly compute the bouds return getFeatures(query).getBounds(); } /** * Adjust query and forward to source. * *

This method provides access to an optimized getCount opperation. If no optimized * opperation is available -1 will be returned. * *

You may still make use of getFeatures( Query ).getCount() which will return the correct * answer (even if it has to itterate through all the results to do so). * * @param query User's query. * @return Number of Features for Query, or -1 if no optimization is available. */ public int getCount(Query query) { try { query = makeDefinitionQuery(query); } catch (IOException ex) { return -1; } try { return source.getCount(query); } catch (IOException e) { return 0; } } public Set getSupportedHints() { return source.getSupportedHints(); } public QueryCapabilities getQueryCapabilities() { return source.getQueryCapabilities(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy