org.noorganization.instalist.server.api.ListResource.java Source code

Java tutorial

Introduction

Here is the source code for org.noorganization.instalist.server.api.ListResource.java

Source

/*
 * Copyright 2016 Tino Siegmund, Michael Wodniok
 *
 * 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 org.noorganization.instalist.server.api;

import java.text.ParseException;
import java.text.ParsePosition;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import javax.ws.rs.*;
import javax.ws.rs.core.Response;

import com.fasterxml.jackson.databind.util.ISO8601Utils;
import org.noorganization.instalist.comm.message.ListInfo;
import org.noorganization.instalist.server.support.CommonEntity;
import org.noorganization.instalist.server.TokenSecured;
import org.noorganization.instalist.server.controller.IListController;
import org.noorganization.instalist.server.controller.impl.ControllerFactory;
import org.noorganization.instalist.comm.message.Error;
import org.noorganization.instalist.server.model.DeletedObject;
import org.noorganization.instalist.server.model.DeviceGroup;
import org.noorganization.instalist.server.model.ShoppingList;
import org.noorganization.instalist.server.support.DatabaseHelper;
import org.noorganization.instalist.server.support.ResponseFactory;
import org.noorganization.instalist.server.support.exceptions.ConflictException;
import org.noorganization.instalist.server.support.exceptions.GoneException;

/**
 * Collection of available lists.
 * 
 */
@Path("/groups/{groupid}/lists")
public class ListResource {

    /**
     * Get a list of shopping-lists.
     * @param _groupId The id of the group, containing the lists.
     * @param _changedSince Requests only the elements that changed since the given date. ISO 8601
     *                     time e.g. 2016-01-19T11:54:07+0100
     */
    @GET
    @TokenSecured
    @Produces({ "application/json" })
    public Response getLists(@PathParam("groupid") int _groupId, @QueryParam("changedsince") String _changedSince)
            throws Exception {

        List<ShoppingList> foundLists;
        List<DeletedObject> foundDeleted;
        EntityManager manager = DatabaseHelper.getInstance().getManager();
        DeviceGroup group = manager.find(DeviceGroup.class, _groupId);

        if (_changedSince != null) {
            Instant changedSince;
            try {
                changedSince = ISO8601Utils.parse(_changedSince, new ParsePosition(0)).toInstant();
            } catch (ParseException _e) {
                manager.close();
                return ResponseFactory.generateBadRequest(CommonEntity.INVALID_CHANGEDATE);
            }

            TypedQuery<ShoppingList> foundListsQuery = manager.createQuery(
                    "select sl from " + "ShoppingList sl where sl.group = :group and sl.updated > :updated",
                    ShoppingList.class);
            foundListsQuery.setParameter("group", group);
            foundListsQuery.setParameter("updated", changedSince);
            foundLists = foundListsQuery.getResultList();

            TypedQuery<DeletedObject> foundDeletedListsQuery = manager
                    .createQuery("select do from" + " DeletedObject do where do.group = :group and "
                            + "do.updated > :updated and do.type = :type", DeletedObject.class);
            foundDeletedListsQuery.setParameter("group", group);
            foundDeletedListsQuery.setParameter("updated", changedSince);
            foundDeletedListsQuery.setParameter("type", DeletedObject.Type.LIST);
            foundDeleted = foundDeletedListsQuery.getResultList();
        } else {
            TypedQuery<ShoppingList> foundListsQuery = manager
                    .createQuery("select sl from " + "ShoppingList sl where sl.group = :group", ShoppingList.class);
            foundListsQuery.setParameter("group", group);
            foundLists = foundListsQuery.getResultList();

            TypedQuery<DeletedObject> foundDeletedListsQuery = manager.createQuery(
                    "select do " + "from DeletedObject do where do.group = :group and do.type = :type",
                    DeletedObject.class);
            foundDeletedListsQuery.setParameter("group", group);
            foundDeletedListsQuery.setParameter("type", DeletedObject.Type.LIST);
            foundDeleted = foundDeletedListsQuery.getResultList();
        }
        manager.close();

        ArrayList<ListInfo> rtn = new ArrayList<ListInfo>(foundLists.size() + foundDeleted.size());
        for (ShoppingList current : foundLists) {
            ListInfo toAdd = new ListInfo();
            toAdd.setUUID(current.getUUID());
            toAdd.setName(current.getName());
            if (current.getCategory() != null)
                toAdd.setCategoryUUID(current.getCategory().getUUID());
            toAdd.setLastChanged(Date.from(current.getUpdated()));
            toAdd.setDeleted(false);
            rtn.add(toAdd);
        }
        for (DeletedObject current : foundDeleted) {
            ListInfo toAdd = new ListInfo();
            toAdd.setUUID(current.getUUID());
            toAdd.setLastChanged(Date.from(current.getUpdated()));
            toAdd.setDeleted(true);
            rtn.add(toAdd);
        }

        return ResponseFactory.generateOK(rtn);
    }

    /**
     * Get a single list.
     * @param _groupId The id of the group, containing the list.
     *     
     */
    @GET
    @TokenSecured
    @Path("{listuuid}")
    @Produces({ "application/json" })
    public Response getList(@PathParam("groupid") int _groupId, @PathParam("listuuid") String _listUUID)
            throws Exception {
        UUID listUUID;
        try {
            listUUID = UUID.fromString(_listUUID);
        } catch (IllegalArgumentException _e) {
            return ResponseFactory.generateBadRequest(CommonEntity.INVALID_UUID);
        }

        EntityManager manager = DatabaseHelper.getInstance().getManager();
        DeviceGroup group = manager.find(DeviceGroup.class, _groupId);
        IListController listController = ControllerFactory.getListController(manager);

        ShoppingList foundList = listController.findByGroupAndUUID(group, listUUID);
        if (foundList == null) {
            if (listController.findDeletedByGroupAndUUID(group, listUUID) == null) {
                manager.close();
                return ResponseFactory
                        .generateNotFound(new Error().withMessage("The requested " + "list was not found."));
            }
            manager.close();
            return ResponseFactory.generateGone(new Error().withMessage("The requested list was " + "deleted."));
        }

        ListInfo rtn = new ListInfo();
        rtn.setUUID(foundList.getUUID());
        rtn.setName(foundList.getName());
        if (foundList.getCategory() != null)
            rtn.setCategoryUUID(foundList.getCategory().getUUID());
        rtn.setLastChanged(Date.from(foundList.getUpdated()));
        rtn.setDeleted(false);

        return ResponseFactory.generateOK(rtn);
    }

    /**
     * Updates a existing list.
     * @param _groupId The id of the group containing the list.
     * @param _listUUID The uuid of the list to update.
     * @param _listInfo Information for changing the list. Not all information needs to be set.
     */
    @PUT
    @TokenSecured
    @Path("{listuuid}")
    @Consumes("application/json")
    @Produces({ "application/json" })
    public Response putList(@PathParam("groupid") int _groupId, @PathParam("listuuid") String _listUUID,
            ListInfo _listInfo) throws Exception {
        if ((_listInfo.getDeleted() != null && _listInfo.getDeleted())
                || (_listInfo.getName() != null && _listInfo.getName().length() == 0)
                || (_listInfo.getUUID() != null && !_listInfo.getUUID().equals(_listUUID)))
            return ResponseFactory.generateBadRequest(CommonEntity.INVALID_DATA);

        UUID listUUID;
        UUID categoryUUID = null;
        boolean removeCategory = false;
        try {
            listUUID = UUID.fromString(_listUUID);
            if (_listInfo.getCategoryUUID() != null)
                categoryUUID = UUID.fromString(_listInfo.getCategoryUUID());
            else if (_listInfo.getRemoveCategory() != null && _listInfo.getRemoveCategory())
                removeCategory = true;
        } catch (IllegalArgumentException _e) {
            return ResponseFactory.generateBadRequest(CommonEntity.INVALID_UUID);
        }
        Instant updated;
        Instant now = Instant.now();
        if (_listInfo.getLastChanged() != null) {
            updated = _listInfo.getLastChanged().toInstant();
            if (now.isBefore(updated))
                return ResponseFactory.generateBadRequest(CommonEntity.INVALID_CHANGEDATE);
        } else
            updated = now;

        EntityManager manager = DatabaseHelper.getInstance().getManager();
        IListController listController = ControllerFactory.getListController(manager);
        try {
            listController.update(_groupId, listUUID, _listInfo.getName(), categoryUUID, removeCategory, updated);
        } catch (ConflictException _e) {
            return ResponseFactory.generateConflict(
                    new Error().withMessage("The new data is in " + "conflict with a saved list."));
        } catch (NotFoundException _e) {
            return ResponseFactory.generateNotFound(new Error().withMessage("The list was not " + "found."));
        } catch (GoneException _e) {
            return ResponseFactory.generateGone(new Error().withMessage("The list was " + "deleted already."));
        } catch (BadRequestException _e) {
            return ResponseFactory.generateBadRequest(CommonEntity.INVALID_DATA);
        } finally {
            manager.close();
        }
        return ResponseFactory.generateOK(null);
    }

    /**
     * Creates a list in the group.
     * @param _groupId The id of the group containing the list.
     * @param _listInfo Information for changing the list. Not all information needs to be set.
     */
    @POST
    @TokenSecured
    @Consumes("application/json")
    @Produces({ "application/json" })
    public Response postList(@PathParam("groupid") int _groupId, ListInfo _listInfo) throws Exception {
        if ((_listInfo.getDeleted() != null && _listInfo.getDeleted()) || _listInfo.getName() == null
                || _listInfo.getName().length() == 0 || _listInfo.getUUID() == null)
            return ResponseFactory.generateBadRequest(CommonEntity.INVALID_DATA);

        UUID listUUID;
        UUID categoryUUID = null;
        try {
            listUUID = UUID.fromString(_listInfo.getUUID());
            if (_listInfo.getCategoryUUID() != null)
                categoryUUID = UUID.fromString(_listInfo.getCategoryUUID());
        } catch (IllegalArgumentException _e) {
            return ResponseFactory.generateBadRequest(CommonEntity.INVALID_UUID);
        }
        Instant created;
        if (_listInfo.getLastChanged() != null) {
            created = _listInfo.getLastChanged().toInstant();
            if (created.isAfter(Instant.now()))
                return ResponseFactory.generateBadRequest(CommonEntity.INVALID_CHANGEDATE);
        } else
            created = Instant.now();

        EntityManager manager = DatabaseHelper.getInstance().getManager();
        IListController listController = ControllerFactory.getListController(manager);
        try {
            listController.add(_groupId, listUUID, _listInfo.getName(), categoryUUID, created);
        } catch (ConflictException _e) {
            return ResponseFactory
                    .generateConflict(new Error().withMessage("A list with this " + "uuid already exists."));
        } finally {
            manager.close();
        }

        return ResponseFactory.generateCreated(null);
    }

    /**
     * Deletes the list.
     * @param _groupId The id of the group containing the list.
     * @param _listUUID The uuid of the list to update.
     */
    @DELETE
    @TokenSecured
    @Path("{listuuid}")
    @Produces({ "application/json" })
    public Response deleteList(@PathParam("groupid") int _groupId, @PathParam("listuuid") String _listUUID)
            throws Exception {
        UUID listUUID;
        try {
            listUUID = UUID.fromString(_listUUID);
        } catch (IllegalArgumentException _e) {
            return ResponseFactory.generateBadRequest(CommonEntity.INVALID_UUID);
        }

        EntityManager manager = DatabaseHelper.getInstance().getManager();
        IListController listController = ControllerFactory.getListController(manager);
        try {
            listController.delete(_groupId, listUUID);
        } catch (NotFoundException _e) {
            return ResponseFactory
                    .generateNotFound(new Error().withMessage("A list with this " + "uuid was not found."));
        } catch (GoneException _e) {
            return ResponseFactory
                    .generateGone(new Error().withMessage("A list with this " + "uuid was already deleted."));
        } finally {
            manager.close();
        }

        return ResponseFactory.generateOK(null);
    }
}