eu.europa.ec.fisheries.uvms.spatial.rest.resources.secured.UserAreaResource.java Source code

Java tutorial

Introduction

Here is the source code for eu.europa.ec.fisheries.uvms.spatial.rest.resources.secured.UserAreaResource.java

Source

/*
Developed by the European Commission - Directorate General for Maritime Affairs and Fisheries @ European Union, 2015-2016.
    
This file is part of the Integrated Fisheries Data Management (IFDM) Suite. The IFDM Suite is free software: you can redistribute it 
and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of 
the License, or any later version. The IFDM Suite 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 General Public License for more 
details. You should have received a copy of the GNU General Public License along with the IFDM Suite. If not, see <http://www.gnu.org/licenses/>.
    
 */
package eu.europa.ec.fisheries.uvms.spatial.rest.resources.secured;

import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.databind.JsonNode;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.io.ParseException;
import eu.europa.ec.fisheries.uvms.commons.geometry.mapper.FeatureToGeoJsonJacksonMapper;
import eu.europa.ec.fisheries.uvms.commons.rest.constants.ErrorCodes;
import eu.europa.ec.fisheries.uvms.commons.rest.resource.UnionVMSResource;
import eu.europa.ec.fisheries.uvms.commons.service.exception.ServiceException;
import eu.europa.ec.fisheries.uvms.commons.service.interceptor.ValidationInterceptor;
import eu.europa.ec.fisheries.uvms.spatial.model.schemas.AreaType;
import eu.europa.ec.fisheries.uvms.spatial.model.schemas.AreaTypeEntry;
import eu.europa.ec.fisheries.uvms.spatial.model.schemas.SpatialFeaturesEnum;
import eu.europa.ec.fisheries.uvms.spatial.rest.dto.FilterType;
import eu.europa.ec.fisheries.uvms.spatial.rest.dto.UserAreaCoordinateType;
import eu.europa.ec.fisheries.uvms.spatial.rest.mapper.AreaLocationMapper;
import eu.europa.ec.fisheries.uvms.spatial.rest.util.ExceptionInterceptor;
import eu.europa.ec.fisheries.uvms.spatial.service.bean.AreaService;
import eu.europa.ec.fisheries.uvms.spatial.service.bean.SpatialService;
import eu.europa.ec.fisheries.uvms.spatial.service.bean.UserAreaService;
import eu.europa.ec.fisheries.uvms.spatial.service.dto.area.UserAreaUpdateDto;
import eu.europa.ec.fisheries.uvms.spatial.service.dto.geojson.UserAreaGeoJsonDto;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.opengis.feature.simple.SimpleFeatureType;

/**
 * @implicitParam roleName|string|header|true||||||
 * @implicitParam scopeName|string|header|true|EC|||||
 * @implicitParam authorization|string|header|true||||||jwt token
 */
@Path("/userarea")
@Slf4j
@Stateless
public class UserAreaResource extends UnionVMSResource {

    @EJB
    private UserAreaService userAreaService;

    @EJB
    private AreaService areaService;

    @EJB
    private SpatialService spatialService;

    private AreaLocationMapper areaLocationMapper = AreaLocationMapper.mapper();

    @HeaderParam("authorization")
    private String authorization;

    @HeaderParam("scopeName")
    private String scopeName;

    @HeaderParam("roleName")
    private String roleName;

    @Context
    private HttpServletRequest servletRequest;

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    @Path("/")
    @Interceptors(value = { ExceptionInterceptor.class })
    public Response storeUserArea(UserAreaGeoJsonDto userAreaGeoJsonDto) throws ServiceException {
        if (servletRequest.isUserInRole("MANAGE_USER_DEFINED_AREAS")) {
            String userName = servletRequest.getRemoteUser();
            log.info("{} is requesting createUserArea(...)", userName);

            if (StringUtils.isNotBlank(userAreaGeoJsonDto.getDatasetName())
                    && !servletRequest.isUserInRole("CREATE_USER_AREA_DATASET")) {
                return createErrorResponse("user_area_dataset_creation_not_allowed");
            }

            if (userAreaGeoJsonDto.getScopeSelection() != null && !userAreaGeoJsonDto.getScopeSelection().isEmpty()
                    && !servletRequest.isUserInRole("SHARE_USER_DEFINED_AREAS")) {
                return createErrorResponse("user_area_sharing_not_allowed");
            }

            long gid = userAreaService.createUserArea(userAreaGeoJsonDto, userName);
            return createSuccessResponse(gid);
        } else {
            return createErrorResponse("user_areas_management_not_allowed");
        }
    }

    @PUT
    @Path("/")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    @Interceptors(value = { ExceptionInterceptor.class })
    public Response updateUserArea(UserAreaGeoJsonDto userAreaGeoJsonDto) throws ServiceException {
        if (servletRequest.isUserInRole(SpatialFeaturesEnum.MANAGE_USER_DEFINED_AREAS.toString())) {
            String userName = servletRequest.getRemoteUser();
            log.info("{} is requesting createUserArea(...)", userName);

            if (StringUtils.isNotBlank(userAreaGeoJsonDto.getDatasetName())
                    && !servletRequest.isUserInRole(SpatialFeaturesEnum.CREATE_USER_AREA_DATASET.toString())) {
                return createErrorResponse("user_area_dataset_creation_not_allowed");
            }

            if (userAreaGeoJsonDto.getScopeSelection() != null && !userAreaGeoJsonDto.getScopeSelection().isEmpty()
                    && !servletRequest.isUserInRole(SpatialFeaturesEnum.SHARE_USER_DEFINED_AREAS.toString())) {
                return createErrorResponse("user_area_sharing_not_allowed");
            }

            boolean isPowerUser = isPowerUser(servletRequest);
            log.info("{} is requesting updateUserArea(...), with a ID={}. Spatial power user: {}", userName,
                    Long.toString(userAreaGeoJsonDto.getId()), isPowerUser);

            long gid = userAreaService.updateUserArea(userAreaGeoJsonDto, servletRequest.getRemoteUser(),
                    isPowerUser, scopeName);
            return createSuccessResponse(gid);
        } else {
            return createErrorResponse("user_areas_management_not_allowed");
        }
    }

    private SimpleFeatureType build(Class geometryType, Map<String, Object> properties, String geometryFieldName) {
        SimpleFeatureTypeBuilder sb = new SimpleFeatureTypeBuilder();
        sb.setCRS(DefaultGeographicCRS.WGS84);
        sb.setName("MULTIPOLIGON");
        if (MapUtils.isNotEmpty(properties)) {
            for (String key : properties.keySet()) {
                if (key.equalsIgnoreCase(geometryFieldName)) {
                    sb.add(key, geometryType);
                } else {
                    Class propClass = String.class;
                    Object propValue = properties.get(key);
                    if (propValue != null) {
                        propClass = propValue.getClass();
                    }
                    sb.add(key, propClass);
                }
            }
        }
        return sb.buildFeatureType();
    }

    @DELETE
    @Path("/{id}")
    @Produces(MediaType.APPLICATION_JSON)
    @Interceptors(value = { ExceptionInterceptor.class })
    public Response deleteUserArea(@PathParam("id") Long userAreaId) throws ServiceException {
        String userName = servletRequest.getRemoteUser();
        log.info("{} is requesting deleteUserArea(...), with a ID={} and scopeName={}", userName, userAreaId,
                scopeName);

        boolean isPowerUser = isPowerUser(servletRequest);
        userAreaService.deleteUserArea(userAreaId, userName, isPowerUser, null); // we pass NULL for scope because deletion shouldn't happen on shared areas, unless you are a power user
        return createSuccessResponse();
    }

    @GET
    @Produces({ MediaType.APPLICATION_JSON })
    @Path("/layers")
    @Interceptors(value = { ExceptionInterceptor.class })
    public Response getUserAreaLayerMapping() {
        log.debug("UserName from security : " + servletRequest.getRemoteUser());
        return createSuccessResponse(
                userAreaService.getUserAreaLayerDefinition(servletRequest.getRemoteUser(), scopeName));
    }

    @POST
    @Produces({ MediaType.APPLICATION_JSON })
    @Path("/details")
    @Interceptors(value = { ExceptionInterceptor.class })
    public Response getUserAreaDetails(UserAreaCoordinateType userAreaTypeDto)
            throws IOException, ParseException, ServiceException {
        Response response;
        boolean isPowerUser = isPowerUser(servletRequest);
        if (userAreaTypeDto.getId() != null) {
            response = getUserAreaDetailsById(userAreaTypeDto, servletRequest.getRemoteUser(), isPowerUser,
                    scopeName);
        } else {
            response = getUserAreaDetailsByLocation(userAreaTypeDto, servletRequest.getRemoteUser());
        }
        return response;
    }

    @GET
    @Produces({ MediaType.APPLICATION_JSON })
    @Path("/types")
    @Interceptors(value = { ExceptionInterceptor.class })
    public Response getUserAreaTypes() throws ServiceException {
        log.debug("UserName from security : " + servletRequest.getRemoteUser());
        boolean isPowerUser = false;

        if (servletRequest.isUserInRole(SpatialFeaturesEnum.MANAGE_ANY_USER_AREA.value())) {
            isPowerUser = true;
        }

        return createSuccessResponse(
                userAreaService.getUserAreaTypes(servletRequest.getRemoteUser(), scopeName, isPowerUser));
    }

    @POST
    @Produces({ MediaType.APPLICATION_JSON })
    @Path("/updatedate")
    @Interceptors(value = { ExceptionInterceptor.class })
    public Response updateUserAreaDates(UserAreaUpdateDto userAreaUpdateDto) throws ServiceException {
        boolean isPowerUser = false;
        if (servletRequest.isUserInRole(SpatialFeaturesEnum.MANAGE_ANY_USER_AREA.value())) {
            isPowerUser = true;
        }
        userAreaService.updateUserAreaDates(servletRequest.getRemoteUser(), userAreaUpdateDto.getStartDate(),
                userAreaUpdateDto.getEndDate(), userAreaUpdateDto.getType(), isPowerUser);
        return createSuccessResponse();
    }

    private boolean isPowerUser(HttpServletRequest request) {
        return request.isUserInRole("MANAGE_ANY_USER_AREA");
    }

    private Response getUserAreaDetailsById(UserAreaCoordinateType userAreaTypeDto, String userName,
            boolean isPowerUser, String scopeName) throws ServiceException, IOException, ParseException {
        if (!userAreaTypeDto.getIsGeom()) {
            AreaTypeEntry areaTypeEntry = areaLocationMapper.getAreaTypeEntry(userAreaTypeDto);
            Map<String, Object> userAreaDetailsWithExtentById = userAreaService
                    .getUserAreaDetailsWithExtentById(areaTypeEntry, userName, isPowerUser, scopeName);
            return createSuccessResponse(userAreaDetailsWithExtentById);
        } else {
            AreaTypeEntry areaTypeEntry = AreaLocationMapper.mapper().getAreaTypeEntry(userAreaTypeDto);
            Map<String, Object> userAreaDetailsWithExtentById = userAreaService
                    .getUserAreaDetailsWithExtentById(areaTypeEntry, userName, isPowerUser, scopeName);

            SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(
                    build(MultiPolygon.class, userAreaDetailsWithExtentById, "geometry"));

            for (Map.Entry<String, Object> entrySet : userAreaDetailsWithExtentById.entrySet()) {
                if (!entrySet.getKey().equals("extent") && !entrySet.getKey().equals("centroid")) {
                    featureBuilder.set(entrySet.getKey(), entrySet.getValue());
                } // TODO check with HUGO if really necessary
            }

            List<JsonNode> nodeList = new ArrayList<>();

            JsonNode jsonNode = new FeatureToGeoJsonJacksonMapper().convert(featureBuilder.buildFeature(null));
            nodeList.add(jsonNode);

            return createSuccessResponse(nodeList);
        }
    }

    private Response getUserAreaDetailsByLocation(UserAreaCoordinateType userAreaTypeDto, String userName)
            throws ServiceException {

        try {
            String areaType = userAreaTypeDto.getAreaType();
            Integer crs = userAreaTypeDto.getCrs();
            Boolean isGeom = userAreaTypeDto.getIsGeom();
            Double latitude = userAreaTypeDto.getLatitude();
            Double longitude = userAreaTypeDto.getLongitude();
            List<Map<String, Object>> userAreaDetails = areaService.getAreasByPoint(latitude, longitude, crs,
                    userName, AreaType.USERAREA);

            if (!isGeom) {
                return createSuccessResponse(userAreaDetails);
            } else {
                List<List<JsonNode>> lists = new ArrayList<>();

                for (Map<String, Object> stringObjectMap : userAreaDetails) {

                    List<JsonNode> nodeList = new ArrayList<>();

                    SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(
                            build(MultiPolygon.class, stringObjectMap, "geometry"));

                    for (Map.Entry<String, Object> entrySet : stringObjectMap.entrySet()) {
                        if (!entrySet.getKey().equals("extent") && !entrySet.getKey().equals("centroid")) {
                            featureBuilder.set(entrySet.getKey(), entrySet.getValue());
                        } // TODO check with HUGO if really necessary
                    }

                    JsonNode jsonNode = new FeatureToGeoJsonJacksonMapper()
                            .convert(featureBuilder.buildFeature(null));
                    nodeList.add(jsonNode);
                    lists.add(nodeList);
                }
                return createSuccessResponse(lists);
            }
        } catch (IOException e) {
            throw new ServiceException(e.getMessage(), e);
        }
    }

    @POST
    @Produces({ MediaType.APPLICATION_JSON })
    @Path("/byfilter")
    @Interceptors(value = { ValidationInterceptor.class, ExceptionInterceptor.class })
    public Response searchUserAreas(FilterType filter) throws ServiceException {
        return createSuccessResponse(userAreaService.searchUserAreasByCriteria(servletRequest.getRemoteUser(),
                scopeName, filter.getFilter(), isPowerUser(servletRequest)));
    }

    @GET
    @Produces({ MediaType.APPLICATION_JSON })
    @Path("/list")
    public Response listUserAreas() throws ServiceException {
        Response response;

        if (servletRequest.isUserInRole(SpatialFeaturesEnum.MANAGE_USER_DEFINED_AREAS.toString())) {
            response = createSuccessResponse(userAreaService.searchUserAreasByCriteria(
                    servletRequest.getRemoteUser(), scopeName, StringUtils.EMPTY, isPowerUser(servletRequest)));
        } else {
            response = createErrorResponse(ErrorCodes.NOT_AUTHORIZED);
        }
        return response;
    }

    @GET
    @Produces({ MediaType.APPLICATION_JSON })
    @Path("/list/{type}")
    public Response listUserAreas(@PathParam("type") String userAreaType) throws ServiceException {
        Response response;
        if (servletRequest.isUserInRole(SpatialFeaturesEnum.MANAGE_USER_DEFINED_AREAS.toString())) {
            List<UserAreaGeoJsonDto> userAreas = userAreaService.searchUserAreasByType(
                    servletRequest.getRemoteUser(), scopeName, userAreaType, isPowerUser(servletRequest));
            response = createSuccessResponse(userAreas);
        } else {
            response = createErrorResponse(ErrorCodes.NOT_AUTHORIZED);
        }
        return response;
    }
}