it.smartcommunitylab.climb.domain.controller.ChildController.java Source code

Java tutorial

Introduction

Here is the source code for it.smartcommunitylab.climb.domain.controller.ChildController.java

Source

/**
 *    Copyright 2015 Fondazione Bruno Kessler - Trento RISE
 *
 *    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 it.smartcommunitylab.climb.domain.controller;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.bson.types.Binary;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
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.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.multipart.MultipartFile;

import it.smartcommunitylab.climb.contextstore.model.Child;
import it.smartcommunitylab.climb.domain.common.Const;
import it.smartcommunitylab.climb.domain.common.GEngineUtils;
import it.smartcommunitylab.climb.domain.common.Utils;
import it.smartcommunitylab.climb.domain.exception.EntityNotFoundException;
import it.smartcommunitylab.climb.domain.exception.StorageException;
import it.smartcommunitylab.climb.domain.exception.UnauthorizedException;
import it.smartcommunitylab.climb.domain.model.Avatar;
import it.smartcommunitylab.climb.domain.model.PedibusGame;
import it.smartcommunitylab.climb.domain.model.PedibusPlayer;
import it.smartcommunitylab.climb.domain.model.PedibusTeam;
import it.smartcommunitylab.climb.domain.model.gamification.PlayerStateDTO;
import it.smartcommunitylab.climb.domain.storage.RepositoryManager;

@Controller
public class ChildController extends AuthController {
    private static final transient Logger logger = LoggerFactory.getLogger(ChildController.class);

    @Autowired
    @Value("${image.upload.dir}")
    private String imageUploadDir;

    @Autowired
    private RepositoryManager storage;

    @Autowired
    private GEngineUtils gengineUtils;

    @SuppressWarnings("unchecked")
    @RequestMapping(value = "/api/child/{ownerId}/{instituteId}/{schoolId}", method = RequestMethod.GET)
    public @ResponseBody List<Child> searchChild(@PathVariable String ownerId, @PathVariable String instituteId,
            @PathVariable String schoolId, HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        if (!validateAuthorization(ownerId, instituteId, schoolId, null, null, Const.AUTH_RES_Child,
                Const.AUTH_ACTION_READ, request)) {
            throw new UnauthorizedException("Unauthorized Exception: token not valid");
        }
        Criteria criteria = Criteria.where("instituteId").is(instituteId).and("schoolId").is(schoolId);
        List<Child> result = (List<Child>) storage.findData(Child.class, criteria, null, ownerId);
        if (logger.isInfoEnabled()) {
            logger.info(String.format("searchChild[%s]:%d", ownerId, result.size()));
        }
        return result;
    }

    @RequestMapping(value = "/api/child/{ownerId}", method = RequestMethod.POST)
    public @ResponseBody Child addChild(@RequestBody Child child, @PathVariable String ownerId,
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        String instituteId = child.getInstituteId();
        String schoolId = child.getSchoolId();
        if (!validateAuthorization(ownerId, instituteId, schoolId, null, null, Const.AUTH_RES_Child,
                Const.AUTH_ACTION_ADD, request)) {
            throw new UnauthorizedException("Unauthorized Exception: token not valid");
        }
        child.setOwnerId(ownerId);
        child.setObjectId(Utils.getUUID());
        storage.addChild(child);
        if (child.isActiveForGame()) {
            addPlayer(child, ownerId, instituteId, schoolId);
        }
        if (logger.isInfoEnabled()) {
            logger.info(String.format("addChild[%s]:%s", ownerId, child.getName()));
        }
        return child;
    }

    @SuppressWarnings("unchecked")
    @RequestMapping(value = "/api/child/{ownerId}/{instituteId}/{schoolId}/classroom", method = RequestMethod.GET)
    public @ResponseBody List<Child> searchChildByClassroom(@PathVariable String ownerId,
            @PathVariable String instituteId, @PathVariable String schoolId, @RequestParam String classRoom,
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        if (!validateAuthorization(ownerId, instituteId, schoolId, null, null, Const.AUTH_RES_Child,
                Const.AUTH_ACTION_READ, request)) {
            throw new UnauthorizedException("Unauthorized Exception: token not valid");
        }
        Criteria criteria = Criteria.where("instituteId").is(instituteId).and("schoolId").is(schoolId)
                .and("classRoom").is(classRoom);
        List<Child> result = (List<Child>) storage.findData(Child.class, criteria, null, ownerId);
        if (logger.isInfoEnabled()) {
            logger.info(String.format("searchChildByClassroom[%s]:%d", ownerId, result.size()));
        }
        return result;
    }

    @RequestMapping(value = "/api/child/{ownerId}/{objectId}", method = RequestMethod.PUT)
    public @ResponseBody Child updateChild(@RequestBody Child child, @PathVariable String ownerId,
            @PathVariable String objectId, HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        if (!validateAuthorization(ownerId, child.getInstituteId(), child.getSchoolId(), null, null,
                Const.AUTH_RES_Child, Const.AUTH_ACTION_UPDATE, request)) {
            throw new UnauthorizedException("Unauthorized Exception: token not valid");
        }
        Criteria criteria = Criteria.where("objectId").is(objectId).and("ownerId").is(ownerId);
        Child oldChild = storage.findOneData(Child.class, criteria, ownerId);
        child.setOwnerId(ownerId);
        child.setObjectId(objectId);
        storage.updateChild(child);
        if (child.isActiveForGame() && !oldChild.isActiveForGame()) {
            //add player
            String instituteId = child.getInstituteId();
            String schoolId = child.getSchoolId();
            addPlayer(child, ownerId, instituteId, schoolId);
        } else if (!child.isActiveForGame() && oldChild.isActiveForGame()) {
            //delete player
            String instituteId = child.getInstituteId();
            String schoolId = child.getSchoolId();
            deletePlayer(oldChild, ownerId, instituteId, schoolId);
        } else if (child.isActiveForGame() && !child.getClassRoom().equals(oldChild.getClassRoom())) {
            String instituteId = child.getInstituteId();
            String schoolId = child.getSchoolId();
            List<PedibusGame> gameList = storage.getPedibusGames(ownerId, instituteId, schoolId);
            for (PedibusGame game : gameList) {
                if (game.isDeployed()) {
                    deletePlayerToTeam(ownerId, game, oldChild);
                    addPlayerToTeam(ownerId, game, child);
                }
            }
        }
        if (logger.isInfoEnabled()) {
            logger.info(String.format("updateChild[%s]:%s", ownerId, child.getName()));
        }
        return child;
    }

    @RequestMapping(value = "/api/child/{ownerId}/{objectId}", method = RequestMethod.DELETE)
    public @ResponseBody String deleteChild(@PathVariable String ownerId, @PathVariable String objectId,
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        Criteria criteria = Criteria.where("objectId").is(objectId).and("ownerId").is(ownerId);
        Child child = storage.findOneData(Child.class, criteria, ownerId);
        if (child == null) {
            throw new EntityNotFoundException("child not found");
        }
        if (!validateAuthorization(ownerId, child.getInstituteId(), child.getSchoolId(), null, null,
                Const.AUTH_RES_Child, Const.AUTH_ACTION_DELETE, request)) {
            throw new UnauthorizedException("Unauthorized Exception: token not valid");
        }
        if (child.isActiveForGame()) {
            String instituteId = child.getInstituteId();
            String schoolId = child.getSchoolId();
            deletePlayer(child, ownerId, instituteId, schoolId);
        }
        storage.removeChild(ownerId, objectId);
        if (logger.isInfoEnabled()) {
            logger.info(String.format("deleteChild[%s]:%s", ownerId, objectId));
        }
        return "{\"status\":\"OK\"}";
    }

    @RequestMapping(value = "/api/child/image/upload/png/{ownerId}/{objectId}", method = RequestMethod.POST)
    public @ResponseBody String uploadImage(@RequestParam("file") MultipartFile file, @PathVariable String ownerId,
            @PathVariable String objectId, HttpServletRequest request) throws Exception {
        Criteria criteria = Criteria.where("objectId").is(objectId);
        Child child = storage.findOneData(Child.class, criteria, ownerId);
        if (child == null) {
            throw new EntityNotFoundException("child not found");
        }
        if (!validateAuthorization(ownerId, child.getInstituteId(), child.getSchoolId(), null, null,
                Const.AUTH_RES_Image, Const.AUTH_ACTION_ADD, request)) {
            throw new UnauthorizedException("Unauthorized Exception: token not valid");
        }
        String name = objectId + ".png";
        if (logger.isInfoEnabled()) {
            logger.info("uploadImage:" + name);
        }
        if (!file.isEmpty()) {
            BufferedOutputStream stream = new BufferedOutputStream(
                    new FileOutputStream(new File(imageUploadDir + "/" + name)));
            FileCopyUtils.copy(file.getInputStream(), stream);
            stream.close();
        }
        return "{\"status\":\"OK\"}";
    }

    @RequestMapping(value = "/api/child/image/download/{imageType}/{ownerId}/{objectId}", method = RequestMethod.GET)
    public @ResponseBody HttpEntity<byte[]> downloadImage(@PathVariable String imageType,
            @PathVariable String ownerId, @PathVariable String objectId, HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        Criteria criteria = Criteria.where("objectId").is(objectId);
        Child child = storage.findOneData(Child.class, criteria, ownerId);
        if (child == null) {
            throw new EntityNotFoundException("child not found");
        }
        if (!validateAuthorization(ownerId, child.getInstituteId(), child.getSchoolId(), null, null,
                Const.AUTH_RES_Image, Const.AUTH_ACTION_READ, request)) {
            throw new UnauthorizedException("Unauthorized Exception: token not valid");
        }
        String name = objectId + "." + imageType;
        String path = imageUploadDir + "/" + name;
        if (logger.isInfoEnabled()) {
            logger.info("downloadImage:" + name);
        }
        FileInputStream in = new FileInputStream(new File(path));
        byte[] image = IOUtils.toByteArray(in);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.IMAGE_PNG);
        if (imageType.toLowerCase().equals("png")) {
            headers.setContentType(MediaType.IMAGE_PNG);
        } else if (imageType.toLowerCase().equals("gif")) {
            headers.setContentType(MediaType.IMAGE_GIF);
        } else if (imageType.toLowerCase().equals("jpg")) {
            headers.setContentType(MediaType.IMAGE_JPEG);
        } else if (imageType.toLowerCase().equals("jpeg")) {
            headers.setContentType(MediaType.IMAGE_JPEG);
        }
        headers.setContentLength(image.length);
        return new HttpEntity<byte[]>(image, headers);
    }

    @RequestMapping(value = "/api/child/image/upload/{ownerId}/{objectId}", method = RequestMethod.POST)
    public @ResponseBody void uploadAvatar(@PathVariable String ownerId, @PathVariable String objectId,
            @RequestParam("data") MultipartFile data, HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        Criteria criteria = Criteria.where("objectId").is(objectId);
        Child child = storage.findOneData(Child.class, criteria, ownerId);
        if (child == null) {
            throw new EntityNotFoundException("child not found");
        }
        if (!validateAuthorization(ownerId, child.getInstituteId(), child.getSchoolId(), null, null,
                Const.AUTH_RES_Image, Const.AUTH_ACTION_ADD, request)) {
            throw new UnauthorizedException("Unauthorized Exception: token not valid");
        }
        criteria = Criteria.where("resourceId").is(objectId).and("resourceType").is(Const.AUTH_RES_Child);
        Avatar avatar = storage.findOneData(Avatar.class, criteria, ownerId);
        if (avatar == null) {
            avatar = new Avatar();
            avatar.setOwnerId(ownerId);
            avatar.setObjectId(Utils.getUUID());
            avatar.setResourceId(objectId);
            avatar.setResourceType(Const.AUTH_RES_Child);
        }
        avatar.setContentType(data.getContentType());
        avatar.setImage(new Binary(data.getBytes()));
        if (logger.isInfoEnabled()) {
            logger.info(String.format("uploadAvatar[%s]:%s", ownerId, objectId));
        }
        storage.saveAvatar(avatar);
    }

    @RequestMapping(value = "/api/child/image/info/{ownerId}/{objectId}", method = RequestMethod.GET)
    public @ResponseBody Avatar getAvatarInfo(@PathVariable String ownerId, @PathVariable String objectId,
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        Criteria criteria = Criteria.where("objectId").is(objectId);
        Child child = storage.findOneData(Child.class, criteria, ownerId);
        if (child == null) {
            throw new EntityNotFoundException("child not found");
        }
        if (!validateAuthorization(ownerId, child.getInstituteId(), child.getSchoolId(), null, null,
                Const.AUTH_RES_Image, Const.AUTH_ACTION_READ, request)) {
            throw new UnauthorizedException("Unauthorized Exception: token not valid");
        }
        criteria = Criteria.where("resourceId").is(objectId).and("resourceType").is(Const.AUTH_RES_Child);
        Avatar avatar = storage.findOneData(Avatar.class, criteria, ownerId);
        if (avatar == null) {
            throw new EntityNotFoundException("avatar not found");
        }
        avatar.setImage(null);
        return avatar;
    }

    @RequestMapping(value = "/api/child/image/download/{ownerId}/{objectId}", method = RequestMethod.GET)
    public @ResponseBody ResponseEntity<byte[]> downloadAvatar(@PathVariable String ownerId,
            @PathVariable String objectId, HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        Criteria criteria = Criteria.where("objectId").is(objectId);
        Child child = storage.findOneData(Child.class, criteria, ownerId);
        if (child == null) {
            throw new EntityNotFoundException("child not found");
        }
        if (!validateAuthorization(ownerId, child.getInstituteId(), child.getSchoolId(), null, null,
                Const.AUTH_RES_Image, Const.AUTH_ACTION_READ, request)) {
            throw new UnauthorizedException("Unauthorized Exception: token not valid");
        }
        criteria = Criteria.where("resourceId").is(objectId).and("resourceType").is(Const.AUTH_RES_Child);
        Avatar avatar = storage.findOneData(Avatar.class, criteria, ownerId);
        if (avatar == null) {
            throw new EntityNotFoundException("avatar not found");
        }
        byte[] data = avatar.getImage().getData();
        if (logger.isInfoEnabled()) {
            logger.info(String.format("downloadAvatar[%s]:%s", ownerId, objectId));
        }
        response.setHeader("Cache-Control", "public, max-age=86400");
        return ResponseEntity.ok().contentType(MediaType.parseMediaType(avatar.getContentType()))
                .contentLength(data.length).body(data);
    }

    private void addPlayer(Child child, String ownerId, String instituteId, String schoolId)
            throws StorageException {
        List<PedibusGame> gameList = storage.getPedibusGames(ownerId, instituteId, schoolId);
        for (PedibusGame game : gameList) {
            if (game.isDeployed()) {
                if (game.getClassRooms().contains(child.getClassRoom())) {
                    //create local player
                    PedibusPlayer pp = new PedibusPlayer();
                    pp.setChildId(child.getObjectId());
                    pp.setWsnId(child.getWsnId());
                    pp.setPedibusGameId(game.getObjectId());
                    pp.setName(child.getName());
                    pp.setSurname(child.getSurname());
                    pp.setClassRoom(child.getClassRoom());
                    storage.savePedibusPlayer(pp, ownerId, false);
                    //create player in GE
                    PlayerStateDTO player = new PlayerStateDTO();
                    player.setPlayerId(child.getObjectId());
                    player.setGameId(game.getGameId());
                    try {
                        gengineUtils.createPlayer(game.getGameId(), player);
                    } catch (Exception e) {
                        logger.warn("Gamification engine player creation warning: " + e.getClass() + " "
                                + e.getMessage());
                    }
                    //update team
                    addPlayerToTeam(ownerId, game, child);
                }
            }
        }
    }

    private void deletePlayer(Child child, String ownerId, String instituteId, String schoolId) {
        List<PedibusGame> gameList = storage.getPedibusGames(ownerId, instituteId, schoolId);
        for (PedibusGame game : gameList) {
            if (game.isDeployed()) {
                if (game.getClassRooms().contains(child.getClassRoom())) {
                    //delete local player
                    storage.removePedibusPlayer(ownerId, game.getObjectId(), child.getObjectId());
                    try {
                        gengineUtils.deletePlayerState(game.getGameId(), child.getObjectId());
                    } catch (Exception e) {
                        logger.warn("Gamification engine player delete warning: " + e.getClass() + " "
                                + e.getMessage());
                    }
                    //update team
                    deletePlayerToTeam(ownerId, game, child);
                }
            }
        }
    }

    private void addPlayerToTeam(String ownerId, PedibusGame game, Child child) {
        List<PedibusTeam> pedibusTeams = storage.getPedibusTeams(ownerId, game.getObjectId());
        for (PedibusTeam pedibusTeam : pedibusTeams) {
            if (pedibusTeam.getClassRoom().equals(child.getClassRoom())) {
                pedibusTeam.getChildrenId().add(child.getObjectId());
                storage.updatePedibusTeamMembers(ownerId, pedibusTeam.getObjectId(), pedibusTeam.getChildrenId());
                try {
                    gengineUtils.addTeamMember(game.getGameId(), child.getClassRoom(), child.getObjectId());
                } catch (Exception e) {
                    logger.warn("Gamification engine team update warning: " + e.getClass() + " " + e.getMessage());
                }
            }
        }
    }

    private void deletePlayerToTeam(String ownerId, PedibusGame game, Child child) {
        List<PedibusTeam> pedibusTeams = storage.getPedibusTeams(ownerId, game.getObjectId());
        for (PedibusTeam pedibusTeam : pedibusTeams) {
            if (pedibusTeam.getClassRoom().equals(child.getClassRoom())) {
                pedibusTeam.getChildrenId().remove(child.getObjectId());
                storage.updatePedibusTeamMembers(ownerId, pedibusTeam.getObjectId(), pedibusTeam.getChildrenId());
                try {
                    gengineUtils.deleteTeamMember(game.getGameId(), child.getClassRoom(), child.getObjectId());
                } catch (Exception e) {
                    logger.warn("Gamification engine team update warning: " + e.getClass() + " " + e.getMessage());
                }
            }
        }
    }

    @ExceptionHandler({ EntityNotFoundException.class, StorageException.class })
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    @ResponseBody
    public Map<String, String> handleEntityNotFoundError(HttpServletRequest request, Exception exception) {
        logger.error(exception.getMessage());
        return Utils.handleError(exception);
    }

    @ExceptionHandler(UnauthorizedException.class)
    @ResponseStatus(value = HttpStatus.FORBIDDEN)
    @ResponseBody
    public Map<String, String> handleUnauthorizedError(HttpServletRequest request, Exception exception) {
        logger.error(exception.getMessage());
        return Utils.handleError(exception);
    }

    @ExceptionHandler(Exception.class)
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    public Map<String, String> handleGenericError(HttpServletRequest request, Exception exception) {
        logger.error(exception.getMessage());
        return Utils.handleError(exception);
    }

}