Source: map/filters/builders/CQLGeoserver.js

import { cloneDeep } from "lodash";

import { AbstractBuilder } from "./AbstractBuilder.js";

/**
 * Represents a CQLGeoserver class that extends the AbstractBuilder class.
 * @memberof vef.map.filters.builders
 */
class CQLGeoserver extends AbstractBuilder {

    /**
     * Returns the filter parameters based on the harmonized filters.
     * @param {Array} harmonizedFilters - The harmonized filters.
     * @returns {Object} - The filter parameters.
     */
    static getFilterParams(harmonizedFilters) {

        harmonizedFilters = cloneDeep(harmonizedFilters);
        // add double quotes in keys for special characters in property names
        for (let key in harmonizedFilters) {
            harmonizedFilters[`"${key}"`] = harmonizedFilters[key];
            delete harmonizedFilters[key];
        }

        const filter = super.getFilterParams(harmonizedFilters);
        return (filter.length) ? { cql_filter: `(${filter})` } : {};
    }

    /**
     * Returns a CQL expression for the BETWEEN operator.
     * @param {string} property - The property name.
     * @param {string|number} begin - The beginning value.
     * @param {string|number} end - The ending value.
     * @returns {string} - The CQL expression.
     */
    static bt(property, begin, end) {
        if (typeof begin == "string") begin = `'${begin}'`;
        if (typeof end == "string") end = `'${end}'`;
        return `${property} BETWEEN ${begin} AND ${end}`;
    }

    /**
     * Returns a CQL expression for the equality operator.
     * @param {string} property - The property name.
     * @param {string|number} value - The value to compare.
     * @returns {string} - The CQL expression.
     */
    static eq(property, value) {
        if (typeof value == "string") value = `'${value}'`;
        return `${property}=${value}`;
    }

    /**
     * Returns a CQL expression for the LIKE operator.
     * @param {string} property - The property name.
     * @param {string} value - The value to match.
     * @returns {string} - The CQL expression.
     */
    static like(property, value) {
        if (typeof value == "string") value = `'${value.replaceAll("*", "%")}'`;
        return `${property} LIKE ${value}`;
    }

    /**
     * Returns a CQL expression for the greater than operator.
     * @param {string} property - The property name.
     * @param {string|number} value - The value to compare.
     * @returns {string} - The CQL expression.
     */
    static gt(property, value) {
        if (typeof value == "string") value = `'${value}'`;
        return `${property}>${value}`;
    }

    /**
     * Returns a CQL expression for the greater than or equal to operator.
     * @param {string} property - The property name.
     * @param {string|number} value - The value to compare.
     * @returns {string} - The CQL expression.
     */
    static gteq(property, value) {
        if (typeof value == "string") value = `'${value}'`;
        return `${property}>=${value}`;
    }

    /**
     * Returns a CQL expression for the less than operator.
     * @param {string} property - The property name.
     * @param {string|number} value - The value to compare.
     * @returns {string} - The CQL expression.
     */
    static lt(property, value) {
        if (typeof value == "string") value = `'${value}'`;
        return `${property}<=${value}`;
    }

    /**
     * Returns a CQL expression for the less than or equal to operator.
     * @param {string} property - The property name.
     * @param {string|number} value - The value to compare.
     * @returns {string} - The CQL expression.
     */
    static lteq(property, value) {
        if (typeof value == "string") value = `'${value}'`;
        return `${property}<=${value}`;
    }

    /**
     * Returns an bbox filter for the given boundingbox
     * @param {string} property 
     * @param {number} latMin
     * @param {number} lngMin
     * @param {number} latMax
     * @param {number} lngMax
     * @returns {string} - The "bbox"-filter.
     */
    static bbox(property, latMin, lngMin, latMax, lngMax) {
        return `BBOX(${property}, ${lngMin}, ${latMin}, ${lngMax}, ${latMax})`;
    }

    /**
     * Returns a CQL expression for the IS NULL operator.
     * @param {string} property - The property name.
     * @returns {string} - The CQL expression.
     */
    static null(property) {
        return `${property} IS NULL`;
    }

    /**
     * Returns a CQL expression for the OR operator.
     * @param {Array} filters - The filters to join.
     * @returns {string} - The CQL expression.
     */
    static or(filters) {
        return this.join_(filters, " OR ");
    }

    /**
     * Returns a CQL expression for the AND operator.
     * @param {Array} filters - The filters to join.
     * @returns {string} - The CQL expression.
     */
    static and(filters) {
        return this.join_(filters, " AND ");
    }

    /**
     * Joins the filters with the specified separator.
     * @param {Array} filters - The filters to join.
     * @param {string} sep - The separator.
     * @returns {string} - The joined filters.
     */
    static join_(filters, sep) {
        if (filters.length == 0) return "";
        if (filters.length == 1) return filters[0];
        let result = "";
        for (let i = 0; i < filters.length; ++i) {
            if (result.length > 0) result += sep;
            result += `(${filters[i]})`;
        }
        return result;
    }

}

export { CQLGeoserver };