How notice filters work in RED FLAGS webapp

Generating filter form initially

NoticesCtrl gathers the available document types and indicators from services and puts them into the view model:

Model attribute Value format Service Service method
docTypes List of maps having id and name keys, where id contains the last character of document type IDs NoticesSvc docTypes()
indicators List of String values which contain indicator IDs, e.g. lang.MyIndicator IndicatorsSvc getIndicators()

Then notices.ftl prints out the form and fills comboboxes with these values. It uses the following message properties to display internationalised texts:

Processing submitted filter form

NoticesCtrl can receive filters in two way:

The form parameters have higher priority than the filter parameter, so if they present, they will overwrite the value of filter inside the method.

NoticesCtrl generates a compact string from the form parameters using Filters class (described below), then redirects to an URL which has only the filter parameter in it.

Compact string format of filters

Each filter consist of a type and a parameter. Filter types are identical to the form parameters you've just read about above. Here are their descriptions and what parameters are expected:

Filter type Description Filter parameter
contr Contracting authority filter Search term or organization ID
cpv CPV code filter 8-digit CPV codes separated by ,
date Publication date filter Date in YYYY-MM-DD or from-to dates in YYYY-MM-DD:YYYY-MM-DD format
doc Document type filter Last character of document type ID-s
flags Flag count filter Number, or number range in min-max format
indicators Indicator filter Indicator IDs separated by ,
text Text filter Search term
value Total value filter Number, or number range in min-max format
winner Winner organization filter Search term or organization ID

One filter's compact represenatation is a filterType:filterParameter string.

The compact string representation of a filter list is the string represenation of each filter separated by __, e.g. contr=Some org__cpv=12345678. This is the format that filter parameter uses.

Conversion and validation of filters

Converting filters between type-parameter pairs and compact string representation can be done using Filter and Filters classes.

Filter class represents one filter: it has a type and a parameter field, and there's also an info field, for additional information. It's toString() method will produce a filterType:filterParameter string.

Filters acts as a utility class which does the conversion and also the validation on-the-fly. Basically it represents a filter list. It's constructors and add methods can accept List<Filter> and compact representation too. The add(String...) method accepts arrays like "type", "parameter", "type", "parameter", .... Even if you add a Filter object, Filters will convert it to string, then parse it again into a Filter object, because the private parse method does the validation:

Invalid filters are skipped so they won't be contained by the output of the conversion. The converter methods are:

Querying notices using filter

NoticesCtrl calls NoticesSvc to fetch notices from the database. NoticesSvc builds up the SQL query using Freemarker and the query template in src/main/resources/queries/notices-sql.ftl.

notices-sql.ftl receives the filters as List<Filter>, as well as the order mode, limit, offset, and whether only the result count or all the results are needed.

Filters intended for text search (contr, text, winner) are used in LIKE statements where non-alphanumeric characters (even with space) are replaced with a single %. contr and winner filters are also handled as they were containing organizaion IDs.

The notice filter query needs helper tables rfwl_cpvs and rfwl_winners in addition of rfwl_notices.

Generating form after filtering

NoticeCtrl puts filters into the model in all three forms: separate parameters for each form field, as list and as a single string. But before it adds the organization name to contr and winner filters if they are containing organization IDs, using FilterSvc.fillOrgNames().

The view model will also contain the notices, the counts, and information for pagination.

notices.ftl will display the results as well as pagination links, and fill out filter form fields with the previously specified values.

It will also print out the readable form of the filter using filter-readable.ftl. This is a generated sentence using the following message properties:

Some filters have additional labels to be able to create reasonable sentences: