<div dir="ltr"><div class="gmail-d-flex gmail-flex-column gmail-flex-md-row gmail-gh-header" style="box-sizing:border-box;color:rgb(36,41,46);font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";font-size:14px;display:flex"><div dir="ltr" style="color:rgb(34,34,34);font-family:Arial,Helvetica,sans-serif;font-size:small"><span style="font-variant-numeric:normal;font-variant-east-asian:normal">Hi </span></div><div dir="ltr" style="color:rgb(34,34,34);font-family:Arial,Helvetica,sans-serif;font-size:small"><span style="font-variant-numeric:normal;font-variant-east-asian:normal">Everyone,</span></div><div dir="ltr" style="color:rgb(34,34,34);font-family:Arial,Helvetica,sans-serif;font-size:small;font-variant-numeric:normal;font-variant-east-asian:normal"><br>This is my final report for the period for GSoC 2020.  The updated report can also be found at the project wiki page <a href="https://wiki.osgeo.org/wiki/GSoC_2020_Develop_CQL_Filter_implementation_for_pygeoapi" target="_blank">https://wiki.osgeo.org/wiki/GSoC_2020_CQL_Filter_implementation_on_pygeoapi</a>. The forked repo of the project can be found here <a href="https://github.com/FarheenB/pygeoapi" target="_blank">https://github.com/FarheenB/pygeoapi</a></div><br></div><div id="gmail-wiki-content" class="gmail-mt-4" style="box-sizing:border-box;color:rgb(36,41,46);font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";font-size:14px;margin-top:24px"><div class="gmail-gutter-condensed gmail-gutter-lg gmail-flex-column gmail-flex-md-row gmail-d-flex" style="box-sizing:border-box;display:flex"><div class="gmail-flex-shrink-0 gmail-col-12 gmail-col-md-9 gmail-mb-4 gmail-mb-md-0" style="box-sizing:border-box;width:935.976px;margin-bottom:0px;padding-right:16px;padding-left:16px"><div id="gmail-wiki-body" class="gmail-gollum-markdown-content" style="box-sizing:border-box"><div class="gmail-markdown-body" style="box-sizing:border-box;font-size:16px;line-height:1.5"><h1 style="box-sizing:border-box;margin:0px 0px 16px;line-height:1.25;padding-bottom:0.3em;border-bottom:1px solid rgb(234,236,239)"><a id="gmail-user-content-cql-implementation-on-pygeoapi" class="gmail-anchor" href="https://github.com/FarheenB/pygeoapi/wiki/Final-Report-GSoC-2020#cql-implementation-on-pygeoapi" style="box-sizing:border-box;background-color:initial;color:rgb(3,102,214);text-decoration-line:none;float:left;padding-right:4px;line-height:1"></a>CQL implementation on pygeoapi</h1><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px"><img src="https://user-images.githubusercontent.com/59408650/91727285-16adef00-ebbf-11ea-9f71-faacd3eb9011.png" alt="pygeoapi-logo" style="box-sizing: initial; border-style: none; max-width: 100%;"></p><h2 style="box-sizing:border-box;margin-top:24px;margin-bottom:16px;line-height:1.25;padding-bottom:0.3em;border-bottom:1px solid rgb(234,236,239)"><a id="gmail-user-content-google-summer-of-code-2020" class="gmail-anchor" href="https://github.com/FarheenB/pygeoapi/wiki/Final-Report-GSoC-2020#google-summer-of-code-2020" style="box-sizing:border-box;background-color:initial;color:rgb(3,102,214);text-decoration-line:none;float:left;padding-right:4px;line-height:1"></a>Google Summer of Code 2020</h2><ul style="box-sizing:border-box;padding-left:2em;margin-top:0px;margin-bottom:16px"><li style="box-sizing:border-box">Author - <a href="https://wiki.osgeo.org/wiki/User:FarheenBano" rel="nofollow" style="box-sizing:border-box;background-color:initial;color:rgb(3,102,214);text-decoration-line:none">Farheen Bano</a></li><li style="box-sizing:border-box;margin-top:0.25em">Mentor 1 - <a href="https://wiki.osgeo.org/wiki/User:Francbartoli" rel="nofollow" style="box-sizing:border-box;background-color:initial;color:rgb(3,102,214);text-decoration-line:none">Francesco Bartoli</a></li><li style="box-sizing:border-box;margin-top:0.25em">Mentor 2 - <a href="https://wiki.osgeo.org/wiki/User:Jjesus" rel="nofollow" style="box-sizing:border-box;background-color:initial;color:rgb(3,102,214);text-decoration-line:none">Jorge Samuel Mendes de Jesus</a></li><li style="box-sizing:border-box;margin-top:0.25em">Organization - <a href="https://www.osgeo.org/" rel="nofollow" style="box-sizing:border-box;background-color:initial;color:rgb(3,102,214);text-decoration-line:none">OSGeo,</a> <a href="https://pygeoapi.io/" rel="nofollow" style="box-sizing:border-box;background-color:initial;color:rgb(3,102,214);text-decoration-line:none">pygeoapi</a></li></ul><h3 style="box-sizing:border-box;margin-top:24px;margin-bottom:16px;font-size:1.25em;line-height:1.25"><a id="gmail-user-content-abstract" class="gmail-anchor" href="https://github.com/FarheenB/pygeoapi/wiki/Final-Report-GSoC-2020#abstract" style="box-sizing:border-box;background-color:initial;color:rgb(3,102,214);text-decoration-line:none;float:left;padding-right:4px;line-height:1"></a>Abstract</h3><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px">pygeoapi is a Python server implementation of the OGC API suite of standards. OGC API standards define modular API building blocks to spatially enable Web API in a consistent way. This standard specifies the fundamental API building blocks for interacting with features. pygeoapi provides the capability for organizations to deploy a RESTful OGC API endpoint using OpenAPI, GeoJSON, and HTML. Project/code is structured to provide functionality via plugins where data can be fetched from any backend services like remote services or local files.</p><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px"><span style="box-sizing:border-box;font-weight:600">Querying</span> is one of the fundamental operations performed on a collection of features. It is in order to obtain a subset of the data which contains feature instances that satisfy some filtering criteria. This project implements these enhanced filtering criteria in a request to a server. CQL is used to specify how resource instances in a source collection should be filtered to identify a result set. Typically, CQL is used here in query operations because it can be written in human readable format. So its the best query language that can be used to identify the subset of resources that should be included in a response document. Each resource instance in the source collection is evaluated using a filtering expression. The overall filter expression always evaluates to true or false. If the expression evaluates to true, the resource instance satisfies the expression and is marked as being in the result set. If the overall filter expression evaluates to false, the data instance is not in the result set.</p><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px">This project is based on <a href="http://docs.opengeospatial.org/DRAFTS/19-079.html" rel="nofollow" style="box-sizing:border-box;background-color:initial;color:rgb(3,102,214);text-decoration-line:none">OGC API - Features - Part 3: Common Query Language document</a> that defines the schema for a JSON document that exposes the set of properties or keys that may be used to construct CQL expressions for pygeoapi.</p><h3 style="box-sizing:border-box;margin-top:24px;margin-bottom:16px;font-size:1.25em;line-height:1.25"><a id="gmail-user-content-motivation" class="gmail-anchor" href="https://github.com/FarheenB/pygeoapi/wiki/Final-Report-GSoC-2020#motivation" style="box-sizing:border-box;background-color:initial;color:rgb(3,102,214);text-decoration-line:none;float:left;padding-right:4px;line-height:1"></a>Motivation</h3><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px">pygeoapi has various data provider plugins like OGR, GeoJSON, CSV, PostGreSQL, Sqlite, Elasticsearch etc. Feature filtering was not yet been implemented at API level in pygeoapi. If this functionality is implemented that this wwould gives pygeoapi an advantage in the GIS community because this helps in delivering appropriate results based on the set of conditions specified by the client. Thus increases the client’s usage capabilities.</p><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px">On developing CQL feature filter implementation with JSON encoding, any combination of bbox, datetime and parameters for filtering on feature properties will be allowed on pygeoapi. The requirements on these parameters imply that only features matching all the predicates are in the result set. i.e., the logical operator between the predicates is 'AND'. The API definition may be used to determine details, e.g., on filter parameters. This depends on the needs of the client. These are clients that are in general able to use multiple APIs as long as it implements OGC API Features.</p><h3 style="box-sizing:border-box;margin-top:24px;margin-bottom:16px;font-size:1.25em;line-height:1.25"><a id="gmail-user-content-pygeoapi-before-gsoc-2020" class="gmail-anchor" href="https://github.com/FarheenB/pygeoapi/wiki/Final-Report-GSoC-2020#pygeoapi-before-gsoc-2020" style="box-sizing:border-box;background-color:initial;color:rgb(3,102,214);text-decoration-line:none;float:left;padding-right:4px;line-height:1"></a>pygeoapi before GSoC 2020</h3><ul style="box-sizing:border-box;padding-left:2em;margin-top:0px;margin-bottom:16px"><li style="box-sizing:border-box">The pygeoapi package integrates Flask as a web framework for defining the API routes/endpoints and WSGI support. Web Server Gateway Interface (WSGI) is a standard for forwarding requests to web applications written in Python language. pygeoapi supports structured metadata about a deployed instance, and is also capable of presenting feature data as structured data.</li><li style="box-sizing:border-box;margin-top:0.25em">The REST structure and payload are defined using yaml file structures</li><li style="box-sizing:border-box;margin-top:0.25em">The API is accessible at /openapi endpoint.</li><li style="box-sizing:border-box;margin-top:0.25em">The API page has REST description but also integrated clients that can be used to send requests to the REST endpoints and see the response provided.</li><li style="box-sizing:border-box;margin-top:0.25em">Each dataset is represented as a REST endpoint under collections.</li><li style="box-sizing:border-box;margin-top:0.25em">The service collection metadata contains a description of the collections provided by the server.</li><li style="box-sizing:border-box;margin-top:0.25em">/features/items composing the data are aggregated on the /items endpoint, in this REST endpoint it is possible to obtain all dataset, or restrict /features/items to a numerical limit, bounding box, time stamp, paging (start index).</li><li style="box-sizing:border-box;margin-top:0.25em">For each feature in the dataset we have a specific identifier (noticed that the identifier is not part of the JSON properties).</li><li style="box-sizing:border-box;margin-top:0.25em">pygeoapi has implemented various data provider plugins.</li><li style="box-sizing:border-box;margin-top:0.25em">pygeoapi serves custom output formats.</li></ul><h3 style="box-sizing:border-box;margin-top:24px;margin-bottom:16px;font-size:1.25em;line-height:1.25"><a id="gmail-user-content-updates-in-pygeoapi-during-gsoc-2020" class="gmail-anchor" href="https://github.com/FarheenB/pygeoapi/wiki/Final-Report-GSoC-2020#updates-in-pygeoapi-during-gsoc-2020" style="box-sizing:border-box;background-color:initial;color:rgb(3,102,214);text-decoration-line:none;float:left;padding-right:4px;line-height:1"></a>Updates in pygeoapi during GSoC 2020</h3><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px">CQL filter capabilities are added to pygeoapi as an extension to their software. This implementation allows user to request for features with an underlying layer of multiple simple or complex filter expressions. Thus providing an enhanced flexibility and better user control over response results. The added implementations are as follows:</p><ul style="box-sizing:border-box;padding-left:2em;margin-top:0px;margin-bottom:16px"><li style="box-sizing:border-box"><p style="box-sizing:border-box;margin-top:16px;margin-bottom:16px"><span style="box-sizing:border-box;font-weight:600">OpenAPI Documentation</span>: Implementation of CQL extension on pygeoapi by following OGC Standards and generated an OpenAPI Document with CQL specifications. Whether a data provider supports CQL filter extension or not is decided from the configuration file. The related CQL schema, components and filter parameters are added in the document.</p></li><li style="box-sizing:border-box;margin-top:0.25em"><p style="box-sizing:border-box;margin-top:16px;margin-bottom:16px"><span style="box-sizing:border-box;font-weight:600">Abstract Syntax Tree for CQL filter expression:</span> Validation of CQL filter expressions and generation of Abstract Syntax Tree from the filter expression. Usage of lexer and parser from pycql library.</p></li><li style="box-sizing:border-box;margin-top:0.25em"><p style="box-sizing:border-box;margin-top:16px;margin-bottom:16px"><span style="box-sizing:border-box;font-weight:600">CQL for CSV and GeoJSON data providers:</span> Evaluation of the Abstract Syntax Tree to filter the feature collections supported by CSV and GeoJSON data providers. pycql library has implementation connection to databases using ORM, but in pygeoapi the data providers don't work with ORM. So the evaluation for all the CQL query operations are developed from scratch and by using efficient methodlogy. The evaluated output is the response from the API.</p></li><li style="box-sizing:border-box;margin-top:0.25em"><p style="box-sizing:border-box;margin-top:16px;margin-bottom:16px"><span style="box-sizing:border-box;font-weight:600">CQL for SQLite data provider:</span> Evaluation of the Abstract Syntax Tree to filter the feature collections supported by SQLite data provider. The AST of the CQL filter request is translated into SQL queries and then used as a request to the database. The evaluated output from the SQLite database is the response from the API.</p></li><li style="box-sizing:border-box;margin-top:0.25em"><p style="box-sizing:border-box;margin-top:16px;margin-bottom:16px"><b>CQL for PostGreSQL data provider:</b> Evaluation of the Abstract Syntax Tree to filter the feature collections supported by PostGreSQL data provider. Like SQLite quesries, the AST of the CQL filter request is translated into PostGreSQL queries by following the syntax of psycopg2 database adapter. The query is then used as a request to the database. The evaluated output from the PostGreSQL database is the response from the API.</p></li><li style="box-sizing:border-box;margin-top:0.25em"><p style="box-sizing:border-box;margin-top:16px;margin-bottom:16px"><span style="box-sizing:border-box;font-weight:600">CQL predicates:</span> Implementation of the following CQL predicates in pygeoapi to support filtering functionality on features. <em style="box-sizing:border-box"><span style="box-sizing:border-box;font-weight:600">Simple Condition Predicate, Combination Predicate, Not Condition Predicate, Between Predicate, Like Predicate, In Predicate, Null Predicate, BBox Predicate, Spatial Predicate and Temporal Predicate</span></em></p></li></ul><h3 style="box-sizing:border-box;margin-top:24px;margin-bottom:16px;font-size:1.25em;line-height:1.25"><a id="gmail-user-content-future-opportunities" class="gmail-anchor" href="https://github.com/FarheenB/pygeoapi/wiki/Final-Report-GSoC-2020#future-opportunities" style="box-sizing:border-box;background-color:initial;color:rgb(3,102,214);text-decoration-line:none;float:left;padding-right:4px;line-height:1"></a>Future Opportunities:</h3><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px">There are endless possibilities that can be done with CQL query filters. The CQL expressions can further be written in JSON language to specify the filters. CQL is implemented for CSV , GeoJSON , SQLite and PostGreSQL in this scope of GSoC 2020. But it can be expanded to other data providers that pygeoapi supports such as OGR, ElasticSearch and MongoDB.</p><h3 style="box-sizing:border-box;margin-top:24px;margin-bottom:16px;font-size:1.25em;line-height:1.25"><a id="gmail-user-content-challenges" class="gmail-anchor" href="https://github.com/FarheenB/pygeoapi/wiki/Final-Report-GSoC-2020#challenges" style="box-sizing:border-box;background-color:initial;color:rgb(3,102,214);text-decoration-line:none;float:left;padding-right:4px;line-height:1"></a>Challenges:</h3><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px">Deciding on what Object Oriented Programming strategy we will be using for CQL implementation was a major challenge and to conclude on a proper CQL filtering approach was difficult in the beginning. As this was a major change in the architecture of pygeoapi, thorough analysis of various approaches was needed. After rigorous discussion with the mentors we decided on implementing CQL at the provider level and not at collection level. As pygeoapi supports multiple data providers and its not necessary that every provider would support CQL filter functionality. Also every provider is needed its separate approach on filtering feature list. The next challenge was faced when there was a requirement to write a generic class as CQLHandler that will act as a plugin for all the data providers. But I am glad that am able to create a proper architecture for CQL implementation on CSV, GeoJSON, SQLite and PostGreSQL.</p><h4 style="box-sizing:border-box;margin-top:24px;margin-bottom:16px;font-size:1em;line-height:1.25"><a id="gmail-user-content-working-steps" class="gmail-anchor" href="https://github.com/FarheenB/pygeoapi/wiki/Final-Report-GSoC-2020#working-steps" style="box-sizing:border-box;background-color:initial;color:rgb(3,102,214);text-decoration-line:none;float:left;padding-right:4px;line-height:1"></a>Working Steps:</h4><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px">A tutorial on how to use the added functionalities and detailed stepwise generation and evaluation of CQL endpoint can be seen in the following link. <a href="https://github.com/FarheenB/pygeoapi/wiki/Steps-to-generate-and-execute-CQL-endpoints" style="box-sizing:border-box;background-color:initial;color:rgb(3,102,214);text-decoration-line:none"><span style="box-sizing:border-box;font-weight:600">Steps</span></a></p><h4 style="box-sizing:border-box;margin-top:24px;margin-bottom:16px;font-size:1em;line-height:1.25"><a id="gmail-user-content-working-example" class="gmail-anchor" href="https://github.com/FarheenB/pygeoapi/wiki/Final-Report-GSoC-2020#working-example" style="box-sizing:border-box;background-color:initial;color:rgb(3,102,214);text-decoration-line:none;float:left;padding-right:4px;line-height:1"></a>Working example:</h4><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px">The operations implemented for CQL extension on pygeoapi can be seen here. <a href="https://github.com/FarheenB/pygeoapi/wiki/Example-of-CQL-query-filters-on-pygeoapi" style="box-sizing:border-box;background-color:initial;color:rgb(3,102,214);text-decoration-line:none"><span style="box-sizing:border-box;font-weight:600">Example</span></a></p><h4 style="box-sizing:border-box;margin-top:24px;margin-bottom:16px;font-size:1em;line-height:1.25"><a id="gmail-user-content-link-to-repository-pygeoapi-openapi-cql-extension-branch" class="gmail-anchor" href="https://github.com/FarheenB/pygeoapi/wiki/Final-Report-GSoC-2020#link-to-repository-pygeoapi-openapi-cql-extension-branch" style="box-sizing:border-box;background-color:initial;color:rgb(3,102,214);text-decoration-line:none;float:left;padding-right:4px;line-height:1"></a>Link to Repository: <a href="https://github.com/FarheenB/pygeoapi/tree/openapi-cql-extension" style="box-sizing:border-box;background-color:initial;color:rgb(3,102,214);text-decoration-line:none">pygeoapi openapi-cql-extension branch</a></h4><p style="box-sizing:border-box;margin-top:0px;margin-bottom:16px"><em style="box-sizing:border-box">(Pull request waiting to be merged)</em></p><h4 style="box-sizing:border-box;margin-top:24px;margin-bottom:16px;font-size:1em;line-height:1.25"><a id="gmail-user-content-link-to-projects-osgeo-wiki-page-wiki-page-link" class="gmail-anchor" href="https://github.com/FarheenB/pygeoapi/wiki/Final-Report-GSoC-2020#link-to-projects-osgeo-wiki-page-wiki-page-link" style="box-sizing:border-box;background-color:initial;color:rgb(3,102,214);text-decoration-line:none;float:left;padding-right:4px;line-height:1"></a>Link to Project's OSGeo Wiki-page: <a href="https://wiki.osgeo.org/wiki/GSoC_2020_CQL_filter_implementation_on_pygeoapi" rel="nofollow" style="box-sizing:border-box;background-color:initial;color:rgb(3,102,214);text-decoration-line:none">Wiki-Page Link</a></h4><h4 style="box-sizing:border-box;margin-top:24px;margin-bottom:16px;font-size:1em;line-height:1.25"><a id="gmail-user-content-rtd-documentation-of-cql-extension-rtd" class="gmail-anchor" href="https://github.com/FarheenB/pygeoapi/wiki/Final-Report-GSoC-2020#rtd-documentation-of-cql-extension-rtd" style="box-sizing:border-box;background-color:initial;color:rgb(3,102,214);text-decoration-line:none;float:left;padding-right:4px;line-height:1"></a>RTD documentation of CQL extension: <a href="https://pygeoapi-cql-filters.readthedocs.io/en/latest/configuration.html" rel="nofollow" style="box-sizing:border-box;background-color:initial;color:rgb(3,102,214);text-decoration-line:none">RTD</a></h4><h4 style="box-sizing:border-box;margin-top:24px;font-size:1em;line-height:1.25;margin-bottom:0px"><a id="gmail-user-content-all-links-related-to-the-project-git-wiki" class="gmail-anchor" href="https://github.com/FarheenB/pygeoapi/wiki/Final-Report-GSoC-2020#all-links-related-to-the-project-git-wiki" style="box-sizing:border-box;background-color:initial;color:rgb(3,102,214);text-decoration-line:none;float:left;padding-right:4px;line-height:1"></a>All links related to the project <a href="https://github.com/FarheenB/pygeoapi/wiki/GSoC-2020-CQL-implementation-on-pygeoapi" style="box-sizing:border-box;background-color:initial;color:rgb(3,102,214);text-decoration-line:none">Git Wiki</a></h4><div><br></div><div><b style="color:rgb(34,34,34);font-family:sans-serif;font-size:14px">Here is a link to the Final Report of GSoC 2020.</b><span style="color:rgb(34,34,34);font-family:sans-serif;font-size:14px"> </span><a rel="nofollow" class="external gmail-text" href="https://github.com/FarheenB/pygeoapi/wiki/Final-Report-GSoC-2020" style="text-decoration-line:none;color:rgb(102,51,102);padding-right:13px;font-family:sans-serif;font-size:14px">Final Report</a> </div><div> <br></div></div></div></div></div><div class="gmail-gutter-condensed gmail-gutter-lg gmail-flex-column gmail-flex-md-row gmail-d-flex" style="box-sizing:border-box;display:flex"><div class="gmail-flex-shrink-0 gmail-col-12 gmail-col-md-9 gmail-mb-4 gmail-mb-md-0" style="box-sizing:border-box;width:935.976px;margin-bottom:0px;padding-right:16px;padding-left:16px"><div id="gmail-wiki-body" class="gmail-gollum-markdown-content" style="box-sizing:border-box"><div class="gmail-markdown-body" style="box-sizing:border-box;font-size:16px;line-height:1.5"><div>Thanks and Regards,</div></div></div></div></div><div class="gmail-gutter-condensed gmail-gutter-lg gmail-flex-column gmail-flex-md-row gmail-d-flex" style="box-sizing:border-box;display:flex"><div class="gmail-flex-shrink-0 gmail-col-12 gmail-col-md-9 gmail-mb-4 gmail-mb-md-0" style="box-sizing:border-box;width:935.976px;margin-bottom:0px;padding-right:16px;padding-left:16px"><div id="gmail-wiki-body" class="gmail-gollum-markdown-content" style="box-sizing:border-box"><div class="gmail-markdown-body" style="box-sizing:border-box;font-size:16px;line-height:1.5"><div>Farheen Bano</div></div></div></div></div></div></div>