Uso de BasicExpression y nuevos métodos

Introducción

Es este ejercicio modificaremos el servicio de ofertas. En la primera parte, filtraremos las peticiones mediante el uso de BasicExpression en la propia petición REST. En la siguiente parte, haremos nuevos métodos para que filtren los datos con BasicExpression.

¿Qué es una BasicExpression?

Una BasicExpression sirve para filtrar las peticiones de una manera compleja que delimite la respuesta dentro de unas condiciones. Las BasicExpression se componen de dos operandos (derecho e izquierdo) y un operador. El operando izquierdo puede contener el nombre de una columna u otra BasicExpression, el operando derecho puede contener un valor u otra BasicExpression y un operador que indicará la relación entre ellos. De tal manera que se puede crear una BasicExpression, que de manera resumida, filtre la petición mediante esta condición:

  • START_DATE >= 2020-01-01: En este caso, el operando izquierdo es el valor de la columna, START_DATE, el operando derecho es el valor de dicha columna y el operador es el símbolo >= . De esta manera, obligaremos a que la condición de la consulta sea que devuelva todos los registros cuya fecha de inicio sea superior o igual al 1 de Enero del 2020.
  • (START_DATE >= 2020-01-01) AND (END_DATE <= 2020-06-30): En este caso existe una BasicExpression cuyo operando izquierdo es BasicExpression, el operando derecho es otra BasicExpression y el operador es el símbolo AND.

BasicExpression en el cuerpo de una petición REST

Una BasicExpression en la petición REST se escribe en el filter de esta misma petición, indicando que es una BasicExpression a través de la anotación @basic_expression, y dentro de ella, lop para el operando izquierdo, op para el operador, y rop para el operando derecho. Si queremos usar múltiples BasicExpression, basta con anidar dentro de cada operando una BasicExpression nueva. Crearemos algunas peticiones en Postman para usar las BasicExpression.

Tipo de petición Petición Cuerpo petición
POST localhost:33333/offers/offer/search
{
    "filter": {
        "@basic_expression": {
            "lop": "START_DATE",
            "op": ">=",
            "rop": "2020-01-15"
        }
    },
    "columns": [
        "ID",
        "DESCRIPTION",
        "OFFER_STATUS",
        "END_DATE",
        "APPLICANT",
        "ACRONYM",
        "CREATION_DATE",
        "START_DATE"
    ]
}
POST localhost:33333/offers/offer/search
{
    "filter": {
        "@basic_expression": {
            "lop": {
                "lop": "START_DATE",
                "op": ">=",
                "rop": "2019-06-01"
            },
            "op": "AND",
            "rop": {
                "lop": "START_DATE",
                "op": "<",
                "rop": "2020-01-01"
            }
        }
    },
    "columns": [
        "ID",
        "DESCRIPTION",
        "OFFER_STATUS",
        "END_DATE",
        "APPLICANT",
        "ACRONYM",
        "CREATION_DATE",
        "START_DATE"
    ]
}

BasicExpression en el método de una petición REST

En caso de que queramos crear un método nuevo que podamos invocar desde una URL específica, sin tener que añadir nosotros una BasicExpression en el cuerpo de una petición REST. En este caso, crearemos dos nuevos métodos dentro del controlador REST de las ofertas. Uno que envíe todas las ofertas del presente año y otro que, pasado en la URL un parámetro, nos devuelva las ofertas de ese año en concreto.

La anotacion @RequestMapping permite indicar la ruta para la que responderá este método, junto con el tipo de petición que se haga e indicar el tipo de respuesta a devolver.

En las condiciones de la consulta, para indicar que el valor es una BasicExpression, tenemos que añadir, como clave EXPRESSION_KEY_UNIQUE_IDENTIFIER, o lo que es lo mismo, SQLStatementBuilder.ExtendedSQLConditionValuesProcessor.EXPRESSION_KEY, una constante que contiene la cadena anterior.

OfferRestController.java

OfferRestController.java
package com.ontimize.hr.ws.core.rest;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.ontimize.hr.api.core.service.IOfferService;
import com.ontimize.hr.model.core.dao.OfferDao;
import com.ontimize.jee.common.db.SQLStatementBuilder;
import com.ontimize.jee.common.db.SQLStatementBuilder.BasicExpression;
import com.ontimize.jee.common.db.SQLStatementBuilder.BasicField;
import com.ontimize.jee.common.db.SQLStatementBuilder.BasicOperator;
import com.ontimize.jee.common.dto.EntityResult;
import com.ontimize.jee.common.dto.EntityResultMapImpl;
import com.ontimize.jee.server.rest.ORestController;

@RestController
@RequestMapping("/offers")
public class OfferRestController extends ORestController<IOfferService> {

    @Autowired
    private IOfferService offerService;

    @Override
    public IOfferService getService() {
        return this.offerService;
    }

    @RequestMapping(value = "currentOffers/search", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
    public EntityResult currentOffersSearch(@RequestBody Map<String, Object> req) {
        try {
            List<String> columns = (List<String>) req.get("columns");
            Map<String, Object> key = new HashMap<String, Object>();
            key.put(SQLStatementBuilder.ExtendedSQLConditionValuesProcessor.EXPRESSION_KEY,
                    searchBetween(OfferDao.ATTR_START_DATE));
            return offerService.offerQuery(key, columns);
        } catch (Exception e) {
            e.printStackTrace();
            EntityResult res = new EntityResultMapImpl();
            res.setCode(EntityResult.OPERATION_WRONG);
            return res;
        }
    }

    @RequestMapping(value = "yearOffers/search", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
    public EntityResult yearOffersSearch(@RequestBody Map<String, Object> req) {
        try {
            List<String> columns = (List<String>) req.get("columns");
            Map<String, Object> filter = (Map<String, Object>) req.get("filter");
            int year = (int) filter.get("YEAR");
            Map<String, Object> key = new HashMap<String, Object>();
            key.put(SQLStatementBuilder.ExtendedSQLConditionValuesProcessor.EXPRESSION_KEY,
                    searchBetweenWithYear(OfferDao.ATTR_START_DATE, year));
            return offerService.offerQuery(key, columns);
        } catch (Exception e) {
            e.printStackTrace();
            EntityResult res = new EntityResultMapImpl();
            res.setCode(EntityResult.OPERATION_WRONG);
            return res;
        }
    }

    private BasicExpression searchBetween(String param) {

        Calendar cal = Calendar.getInstance();
        int currentYear = cal.get(Calendar.YEAR);

        return this.searchBetweenWithYear(param, currentYear);
    }

    private BasicExpression searchBetweenWithYear(String param, int year) {

        Calendar cal = Calendar.getInstance();
        cal.set(year, 0, 1);
        Date startDate = cal.getTime();
        cal.set(year + 1, 0, 1);
        Date endDate = cal.getTime();

        BasicField field = new BasicField(param);
        BasicExpression bexp1 = new BasicExpression(field, BasicOperator.MORE_EQUAL_OP, startDate);
        BasicExpression bexp2 = new BasicExpression(field, BasicOperator.LESS_OP, endDate);
        return new BasicExpression(bexp1, BasicOperator.AND_OP, bexp2);
    }

}

arrow_back Tutorial anterior Próximo tutorial arrow_forward