edu.byu.mpn.rest.DeviceController.java Source code

Java tutorial

Introduction

Here is the source code for edu.byu.mpn.rest.DeviceController.java

Source

/*
 *   Copyright 2016 Brigham Young University
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package edu.byu.mpn.rest;

import com.amazonaws.services.sns.model.InvalidParameterException;
import edu.byu.mpn.da.interfaces.DeviceDao;
import edu.byu.mpn.domain.Device;
import edu.byu.mpn.helpers.ResponseMessage;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import javax.ws.rs.*;
import javax.ws.rs.core.Response;
import java.util.Date;

/**
 * Created by cwoodfie on 4/5/16.
 */

@Service
@Produces("application/json")
@Consumes("application/json")
@Path("/v1/devices")
public class DeviceController extends BaseController {
    private static final Logger LOG = LogManager.getLogger(DeviceController.class);
    public static final String EX_OUT_OF_DATE = "The resource you passed in is out of date. Please refresh your device info and try again.";
    public static final String EX_EMPTY_REQUEST = "No request body provided.";
    public static final String EX_MISSING_ID = "The id of the device must be included in the request body.";
    public static final String EX_ID_CONFLICT = "The id in the url does not match the id included in the device.";
    public static final String EX_PERSONID_MISSING = "The request body must include a personId.";
    public static final String EX_TOKEN_MISSING = "The request body must include a valid token";
    public static final String EX_NACHO_DEVICE = "The device you are trying to access is registered to somebody else.";
    public static final String EX_NACHO_PERSONID = "The personId included in the device does not match the logged in user. Please use your own personId and try again.";
    public static final String EX_MISSING_PARAMETER_FORMAT = "The device passed in was missing the %s parameter";
    public static final String EX_UNSUPPORTED_PLATFORM = "Mobile Push Notifications have not been implemented for your device platform. \"Android\" and \"Apple\" are currently the only valid platforms.";
    private DeviceDao deviceDao;
    private String applePlatformApplicationArn;
    private String androidPlatformApplicationArn;
    private String topicArn;
    private String testTopicArn;

    @Autowired
    public void setDeviceDao(DeviceDao deviceDao) {
        this.deviceDao = deviceDao;
    }

    @Autowired
    public void setApplePlatformApplicationArn(
            @Qualifier("applePlatformApplicationArn") String applePlatformApplicationArn) {
        this.applePlatformApplicationArn = applePlatformApplicationArn;
    }

    @Autowired
    public void setAndroidPlatformApplicationArn(
            @Qualifier("androidPlatformApplicationArn") String androidPlatformApplicationArn) {
        this.androidPlatformApplicationArn = androidPlatformApplicationArn;
    }

    @Autowired
    public void setTopicArn(@Qualifier("topicArn") String topicArn) {
        this.topicArn = topicArn;
    }

    @Autowired
    public void setTestTopicArn(@Qualifier("testTopicArn") String testTopicArn) {
        this.testTopicArn = testTopicArn;
    }

    @GET
    public Response getAllDevices(@QueryParam("personId") @DefaultValue("") final String personId) {
        LOG.info("/v1/devices GET");

        if (personId.isEmpty()) {
            return Response.status(Response.Status.OK).entity(deviceDao.getAllDevices()).build();
        } else {
            return Response.status(Response.Status.OK).entity(deviceDao.getAllDevicesByPersonId(personId)).build();
        }
    }

    @Path("/{id}")
    @GET
    public Response getDeviceById(@PathParam("id") Integer id,
            @DefaultValue("") @QueryParam("proxyId") String proxyId) {
        LOG.info("/v1/devices/{id} GET");

        Device device = deviceDao.getDeviceById(id);
        if (device == null) {
            return Response.status(Response.Status.NOT_FOUND).build();
        } else if (device.getPersonId() != null && !device.getPersonId().equals(getPersonId(proxyId))) {
            return Response.status(Response.Status.FORBIDDEN).entity(new ResponseMessage(EX_NACHO_DEVICE)).build();
        }

        return Response.status(Response.Status.OK).entity(device).build();
    }

    @POST
    public Response createDevice(@DefaultValue("") @QueryParam("proxyId") String proxyId,
            @DefaultValue("false") @QueryParam("testTopic") boolean testTopic, Device device) {
        LOG.info("/v1/devices POST");

        Response errorResponse = validateCreateDevice(device, proxyId);
        if (errorResponse != null) {
            return errorResponse;
        }

        //      Checks whether device already exists
        Device deviceByToken = deviceDao.getDeviceByTokenAndPlatform(device.getToken(), device.getDevicePlatform());
        if (deviceByToken != null) {
            if (device.getPersonId().equals(deviceByToken.getPersonId())) {
                return Response.status(Response.Status.OK).entity(deviceByToken).build();
            } else {
                return Response.status(Response.Status.FORBIDDEN).entity(EX_NACHO_DEVICE).build();
            }
        }

        device.setDateRegistered(new Date());
        final String platformApplicationArn = APPLE.equals(device.getDevicePlatform()) ? applePlatformApplicationArn
                : androidPlatformApplicationArn;

        try {
            device.setEndpointArn(
                    mpnClient.createPlatformEndpoint(device.getToken(), platformApplicationArn).getEndpointArn());
            device.setSubscriptionArn(mpnClient.subscribeDevice(device.getEndpointArn(), topicArn,
                    device.getPersonId(), device.getDeviceName()).getSubscriptionArn());
            if (testTopic) {
                mpnClient.subscribeDevice(device.getEndpointArn(), testTopicArn, device.getPersonId(),
                        device.getDeviceName());
            }
        } catch (InvalidParameterException e) {
            LOG.error(e.getMessage(), e);
            return Response.status(Response.Status.BAD_REQUEST).entity(new ResponseMessage(e.getMessage())).build();
        }

        deviceDao.saveOrUpdateDevice(device, getLoggedInPersonId());
        return Response.status(Response.Status.CREATED).entity(device).build();
    }

    private Response validateCreateDevice(Device device, String proxyId) {
        String missingParameter = null;
        if (device == null) {
            return Response.status(Response.Status.BAD_REQUEST).entity(new ResponseMessage(EX_EMPTY_REQUEST))
                    .build();
        } else if (device.getDeviceId() == null || device.getDeviceId().isEmpty()) {
            missingParameter = "deviceId";
        } else if (device.getPersonId() == null || device.getPersonId().isEmpty()) {
            missingParameter = "personId";
        } else if (device.getToken() == null || device.getToken().isEmpty()) {
            missingParameter = "token";
        } else if (device.getDeviceName() == null || device.getDeviceName().isEmpty()) {
            missingParameter = "deviceName";
        } else if (device.getDevicePlatform() == null || device.getDevicePlatform().isEmpty()) {
            missingParameter = "devicePlatform";
        }

        if (missingParameter != null) {
            return Response.status(Response.Status.BAD_REQUEST)
                    .entity(new ResponseMessage(String.format(EX_MISSING_PARAMETER_FORMAT, missingParameter)))
                    .build();
        } else if (!device.getPersonId().equals(getPersonId(proxyId))) {
            return Response.status(Response.Status.FORBIDDEN).entity(new ResponseMessage(EX_NACHO_PERSONID))
                    .build();
        } else if (!isValidDevicePlatform(device.getDevicePlatform())) {
            return Response.status(501).entity(new ResponseMessage(EX_UNSUPPORTED_PLATFORM)).build();
        }

        return null;
    }

    private boolean isValidDevicePlatform(String devicePlatform) {
        return ANDROID.equals(devicePlatform) || APPLE.equals(devicePlatform);
    }

    @Path("/{id}")
    @PUT
    public Response updateDevice(@PathParam("id") Integer id,
            @DefaultValue("") @QueryParam("proxyId") String proxyId, Device device) {
        LOG.info("/v1/devices/{id} PUT");

        Response errorResponse = validateUpdateDevice(id, device, proxyId);
        if (errorResponse != null) {
            return errorResponse;
        }

        Device currentDevice = deviceDao.getDeviceById(id);
        //      If deviceId or deviceName are included in the request body, update them in the database
        currentDevice
                .setDeviceId(device.getDeviceId() == null ? currentDevice.getDeviceId() : device.getDeviceId());
        currentDevice.setDeviceName(
                device.getDeviceName() == null ? currentDevice.getDeviceName() : device.getDeviceName());
        if (currentDevice.getPersonId() == null) {
            //         If device is being registered, set new dateRegistered
            currentDevice.setDateRegistered(new Date());
            currentDevice.setPersonId(device.getPersonId());
            currentDevice.setSubscriptionArn(mpnClient.subscribeDevice(currentDevice.getEndpointArn(), topicArn,
                    currentDevice.getPersonId(), currentDevice.getDeviceName()).getSubscriptionArn());
        }

        if (!currentDevice.getToken().equals(device.getToken())) {
            currentDevice.setToken(device.getToken());
            try {
                mpnClient.updatePlatformEndpoint(currentDevice.getToken(), currentDevice.getEndpointArn());
            } catch (InvalidParameterException e) {
                LOG.error(e.getMessage(), e);
                return Response.status(Response.Status.BAD_REQUEST).entity(new ResponseMessage(e.getMessage()))
                        .build();
            }
        }

        deviceDao.saveOrUpdateDevice(currentDevice, getLoggedInPersonId());
        return Response.status(Response.Status.OK).entity(currentDevice).build();
    }

    private Response validateUpdateDevice(Integer id, Device device, String proxyId) {
        String errorMessage = null;
        if (device == null) {
            errorMessage = EX_EMPTY_REQUEST;
        } else if (device.getId() == null) {
            errorMessage = EX_MISSING_ID;
        } else if (!id.equals(device.getId())) {
            errorMessage = EX_ID_CONFLICT;
        } else if (device.getPersonId() == null || device.getPersonId().isEmpty()) {
            errorMessage = EX_PERSONID_MISSING;
        } else if (device.getToken() == null || device.getToken().isEmpty()) {
            errorMessage = EX_TOKEN_MISSING;
        }
        if (errorMessage != null) {
            return Response.status(Response.Status.BAD_REQUEST).entity(new ResponseMessage(errorMessage)).build();
        }

        Device oldDevice = deviceDao.getDeviceById(id);
        if (oldDevice == null) {
            return Response.status(Response.Status.NOT_FOUND).build();
        } else if (!device.getPersonId().equals(getPersonId(proxyId))) {
            return Response.status(Response.Status.FORBIDDEN).entity(new ResponseMessage(EX_NACHO_PERSONID))
                    .build();
        } else if (!(device.getPersonId().equals(oldDevice.getPersonId()) || oldDevice.getPersonId() == null
                || oldDevice.getPersonId().isEmpty())) {
            return Response.status(Response.Status.FORBIDDEN).entity(new ResponseMessage(EX_NACHO_DEVICE)).build();
        }
        return null;
    }

    @Path("/{id}")
    @DELETE
    public Response unregisterDevice(@PathParam("id") Integer id,
            @DefaultValue("") @QueryParam("proxyId") String proxyId) {
        LOG.info("/v1/devices/{id} DELETE");

        Device device = deviceDao.getDeviceById(id);
        if (device == null) {
            return Response.status(Response.Status.NOT_FOUND).build();
        } else if (device.getPersonId() == null) {
            //         The device is already unregistered, so return success
            return Response.status(Response.Status.OK).entity(device).build();
        } else if (!device.getPersonId().equals(getPersonId(proxyId))) {
            //         The authenticated user does not match the devices registered owner
            return Response.status(Response.Status.FORBIDDEN).entity(new ResponseMessage(EX_NACHO_DEVICE)).build();
        }

        device.setPersonId(null);
        mpnClient.unsubscribeDevice(device.getEndpointArn(), device.getSubscriptionArn());
        device.setSubscriptionArn(null);

        deviceDao.saveOrUpdateDevice(device, getLoggedInPersonId());
        return Response.status(Response.Status.OK).entity(device).build();
    }

}