com.pkrete.locationservice.admin.service.illustrations.MapsServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.pkrete.locationservice.admin.service.illustrations.MapsServiceImpl.java

Source

/**
 * This file is part of Location Service :: Admin. Copyright (C) 2014 Petteri
 * Kivimki
 *
 * Location Service :: Admin 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 (at your
 * option) any later version.
 *
 * Location Service :: Admin 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
 * Location Service :: Admin. If not, see <http://www.gnu.org/licenses/>.
 */
package com.pkrete.locationservice.admin.service.illustrations;

import com.pkrete.locationservice.admin.service.MapsService;
import com.pkrete.locationservice.admin.dao.MapsDao;
import com.pkrete.locationservice.admin.model.illustration.Map;
import com.pkrete.locationservice.admin.model.language.Language;
import com.pkrete.locationservice.admin.model.owner.Owner;
import com.pkrete.locationservice.admin.io.DirectoryService;
import com.pkrete.locationservice.admin.io.FileService;
import com.pkrete.locationservice.admin.converter.JSONizerService;
import com.pkrete.locationservice.admin.service.LanguagesService;
import com.pkrete.locationservice.admin.util.DateTimeUtil;
import com.pkrete.locationservice.admin.util.IllustrationsUtil;
import com.pkrete.locationservice.admin.util.Settings;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map.Entry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

/**
 * This class implements {@link MapsService MapsService} interface, which
 * defines service layer for Map objects.
 *
 * @author Petteri Kivimki
 */
public class MapsServiceImpl implements MapsService {

    private final static Logger logger = LoggerFactory.getLogger(MapsServiceImpl.class.getName());
    private MapsDao dao;
    private FileService fileService;
    private DirectoryService dirService;
    private LanguagesService languagesService;
    private JSONizerService jsonizer;

    /**
     * Sets the data access object.
     *
     * @param dao new value
     */
    public void setDao(MapsDao dao) {
        this.dao = dao;
    }

    /**
     * Sets the file service object.
     *
     * @param fileService new value
     */
    public void setFileService(FileService fileService) {
        this.fileService = fileService;
    }

    /**
     * Sets the directory service object.
     *
     * @param dirService new value
     */
    public void setDirService(DirectoryService dirService) {
        this.dirService = dirService;
    }

    /**
     * Sets the language service object.
     *
     * @param languageService new value
     */
    public void setLanguagesService(LanguagesService languagesService) {
        this.languagesService = languagesService;
    }

    /**
     * Sets the JSON converter object.
     *
     * @param dao new value
     */
    public void setJsonizer(JSONizerService jsonizer) {
        this.jsonizer = jsonizer;
    }

    /**
     * Returns the map with given id. This method is only for editor classes.
     * All the other classes must give also the owner parameter.
     *
     * @param id the id that is used for searching
     * @return the map with the given id
     */
    @Override
    public Map get(int id) {
        return dao.get(id);
    }

    /**
     * Returns the map with given id.
     *
     * @param id the id that is used for searching
     * @param owner the owner of the object
     * @return the map with the given id
     */
    @Override
    public Map get(int id, Owner owner) {
        return dao.get(id, owner);
    }

    /**
     * Deletes the map with the given id and owner.
     *
     * @param id id of the map
     * @param owner owner of the map
     * @return true if and only if the map was successfully deleted; otherwise
     * false
     */
    @Override
    public boolean delete(int id, Owner owner) {
        Map map = dao.get(id, owner);
        return delete(map);
    }

    /**
     * Deletes the given map object from the database.
     *
     * @param map the map to be deleted
     */
    @Override
    public boolean delete(Map map) {
        // Check for null
        if (map == null) {
            logger.warn("Deleting map failed! Map can not be null.");
            return false;
        }
        // JSON presentation of the Language object
        String json = this.jsonizer.jsonize(map, true);

        // Make sure that the map can be deleted
        if (!dao.canBeDeleted(map.getId())) {
            logger.warn("Deleting map failed! Map has dependencies in the database. Map : {}", json);
            return false;
        }
        boolean success = true;
        // If the map is not external, map files need to be deleted
        if (!map.getIsExternal()) {
            // Map file must be deleted from each language directory
            success = this.deleteFiles(map);
        }
        // Delete the map from DB, if success == true
        if (success) {
            if (dao.delete(map)) {
                logger.info("Map deleted : {}", json);
                return true;
            }
        }
        logger.warn("Failed to delete map : {}", json);
        return false;
    }

    /**
     * Returns a list of all the maps in the database that are related to the
     * given owner object.
     *
     * @param owner the owner of the objects
     * @return all the maps in the database
     */
    @Override
    public List<Map> get(Owner owner) {
        return dao.get(owner);
    }

    /**
     * Adds the given map object to the database and to the file system.
     *
     * @param map the map to be added
     * @return true if and only if the map was successfully added; otherwise
     * false
     */
    @Override
    public boolean create(Map map) {
        // Set created date
        map.setCreated(new Date());
        // Get path of the maps dir
        final String path = Settings.getInstance().getMapsPath(map.getOwner().getCode());
        // Get path of the maps admin dir
        final String adminPath = Settings.getInstance().getMapsPathAdmin(map.getOwner().getCode());

        if (map.getFilePath() != null && map.getFilePath().length() > 0) {
            logger.debug("Move uploaded maps files from admin dir to service dir.");
            // Map files are moved from admin dir to service dir.
            // FilePath variable contains the name of the map files
            String name = map.getFilePath();
            // Check that the file really exists in all the languages
            if (!this.adminMapExists(map.getFilePath(), map.getOwner())) {
                logger.warn(
                        "Creating map failed, because the given file doesn't exist in all the language directories! File : {}",
                        map.getFilePath());
                return false;
            }
            // Get all the languages related to the Map owner
            List<Language> languages = this.languagesService.getLanguages(map.getOwner());
            // Name must be unique
            name = this.getUniqueName(path, name, languages);
            // Path variable must be updated
            map.setPath(name);
            // The map is not external
            map.setIsExternal(false);
            // Map for files that were succesfully renamed
            java.util.Map<String, String> renamedFiles = new HashMap<String, String>();
            boolean success = true;
            // Move all the language versions
            for (Language lang : languages) {
                // Absolute source path
                String sourcePath = adminPath + lang.getCode() + "/" + map.getFilePath();
                // Absolute target path
                String targetPath = path + lang.getCode() + "/" + map.getPath();
                logger.info("Move map file : \"{}\" -> \"{}\"", sourcePath, targetPath);

                // Try to rename (=move) the file
                if (!fileService.rename(sourcePath, targetPath)) {
                    logger.warn("Moving map file failed!");
                    success = false;
                    break;
                }
                renamedFiles.put(targetPath, sourcePath);
            }
            // Rollback if moving the files failed
            if (!success) {
                logger.warn("Moving map files failed -> ROLLBACK.");
                logger.warn("Undo all the changes.");

                // Do rollback if all the fiels were not renamed.
                // Go through all the files and try to rename them with the
                // original name.
                boolean renamed = true;
                for (String key : renamedFiles.keySet()) {
                    if (!this.fileService.rename(key, renamedFiles.get(key))) {
                        renamed = false;
                    }
                }
                if (!renamed) {
                    logger.warn("Failed to restore all the previously moved map files.");
                } else {
                    logger.info("Succesfully restored all the previously moved map files.");
                }
                logger.warn("Creating new map failed.");
                return false;
            }
        } else if (map.getUrl().length() > 0) {
            // Set path
            map.setPath(map.getUrl());
            // Map is external
            map.setIsExternal(true);
        } else if (map.hasFiles()) {
            logger.debug("Add uploaded map files.");
            // User has uploaded files, one file for each language
            java.util.Map<Integer, MultipartFile> files = map.getFiles();
            // Get the name of the first file
            String name = files.entrySet().iterator().next().getValue().getOriginalFilename();
            // Get all the languages related to the Map owner
            List<Language> languages = this.languagesService.getLanguages(map.getOwner());
            // Get list of language id - language pairs
            java.util.Map<Integer, Language> languagesMap = Language.toMap(languages);
            // Name must be unique
            name = this.getUniqueName(path, name, languages);
            // Update path variable
            map.setPath(name);
            // Map is not external
            map.setIsExternal(false);
            // List for files that were succesfully written to disk
            List<String> writtenFiles = new ArrayList<String>();
            boolean success = true;
            // Write uploaded files to disk
            for (Entry<Integer, MultipartFile> entry : files.entrySet()) {
                // New file object for the target file
                File mapFile = new File(path + languagesMap.get(entry.getKey()).getCode() + "/" + name);
                logger.info("Write uploaded map file to disk. Path : \"{}\"", mapFile.getAbsolutePath());
                try {
                    // Write the uploaded file to disk
                    entry.getValue().transferTo(mapFile);
                } catch (IOException ex) {
                    logger.warn("Writing map file to disk failed!");
                    logger.error(ex.getMessage(), ex);
                    success = false;
                    break;
                }
                // Check that the file really exists
                if (!fileService.exists(mapFile.getAbsolutePath())) {
                    logger.warn("Writing map file to disk failed! File doesn't exist. Path : \"{}\"",
                            mapFile.getAbsolutePath());
                    success = false;
                    break;
                }
                writtenFiles.add(mapFile.getAbsolutePath());
            }
            // Rollback if writing the files failed
            if (!success) {
                logger.warn("Writing map files failed -> ROLLBACK.");
                logger.warn("Undo all the changes.");

                // Do rollback if all the files were not written.
                // Go through all the files and try to delete them
                boolean deleted = true;
                for (String file : writtenFiles) {
                    if (!this.fileService.delete(file)) {
                        deleted = false;
                    }
                }
                if (!deleted) {
                    logger.warn("Failed to remove all the previously written map files.");
                } else {
                    logger.info("Succesfully removed all the previously written map files.");
                }
                logger.warn("Creating new map failed.");
                return false;
            }
        }
        // Try to save the map to DB
        if (dao.create(map)) {
            logger.info("Map created : {}", this.jsonizer.jsonize(map, true));
            return true;
        }
        logger.warn("Failed to create map : {}", this.jsonizer.jsonize(map, true));
        return false;
    }

    /**
     * Updates the given map object to the database.
     *
     * @param map the map to be updated
     * @return true if and only if the map was successfully added; otherwise
     * false
     */
    @Override
    public boolean update(Map map) {
        // Get JSON presentation
        String json = this.jsonizer.jsonize(map, true);
        // Set updated date
        map.setUpdated(new Date());
        // Get path of the maps dir
        final String path = Settings.getInstance().getMapsPath(map.getOwner().getCode());
        // Get path of the maps admin dir
        final String adminPath = Settings.getInstance().getMapsPathAdmin(map.getOwner().getCode());

        if (map.getFilePath() != null && map.getFilePath().length() > 0) {
            logger.debug("Move uploaded maps files from admin dir to service dir.");
            // Get name of the map file
            String name = map.getPath();
            // Get all the languages related to the Map owner
            List<Language> languages = this.languagesService.getLanguages(map.getOwner());
            // Check that the file really exists in one language at least
            if (!this.adminMapExists(map.getFilePath(), languages, map.getOwner())) {
                logger.warn("Updating map failed, because the given file doesn't exist in any language! File : {}",
                        map.getFilePath());
                return false;
            }
            // If the current map is external, name must be checked
            if (map.getIsExternal()) {
                // Old map was external, name of the map file must set
                name = map.getFilePath();
                // Name must be unique
                name = this.getUniqueName(path, name, languages);
                // Update path
                map.setPath(name);
            }
            // The map is not external
            map.setIsExternal(false);
            // Move all the language versions that exist
            for (Language lang : languages) {
                // Absolute source path
                String sourcePath = adminPath + lang.getCode() + "/" + map.getFilePath();
                // If the source file doesn't exist, jump to next
                if (!this.fileService.exists(sourcePath)) {
                    continue;
                }
                // Absolute target path
                String targetPath = path + lang.getCode() + "/" + map.getPath();
                if (!this.fileService.replace(sourcePath, targetPath)) {
                    logger.warn("Moving map file failed!");
                    return false;
                }
            }
        } else if (map.getUrl() != null && map.getUrl().length() > 0) {
            // If map is not external, the files must me deleted
            if (!map.getIsExternal()) {
                if (!this.deleteFiles(map)) {
                    logger.warn("Updating map failed! Unable to delete all the related files!");
                    return false;
                }
            }
            // Update path
            map.setPath(map.getUrl());
            // The map is external
            map.setIsExternal(true);
        } else if (map.hasFile()) {
            logger.debug("Update map file(s).");
            boolean success = true;
            // Get uploaded files
            java.util.Map<Integer, MultipartFile> files = map.getFiles();
            // Get all the languages related to the Map owner
            List<Language> languages = this.languagesService.getLanguages(map.getOwner());
            // Get list of language id - language pairs
            java.util.Map<Integer, Language> languagesMap = Language.toMap(languages);
            // Loop through the files
            for (Entry<Integer, MultipartFile> entry : files.entrySet()) {
                // If file is empty, jump to next
                if (entry.getValue() == null || entry.getValue().getSize() == 0) {
                    continue;
                }
                // Create File object for the target file
                File mapFile = new File(path + languagesMap.get(entry.getKey()).getCode() + "/" + map.getPath());
                // Create File object for the temp file
                File tempFile = new File(
                        path + languagesMap.get(entry.getKey()).getCode() + "/temp." + map.getPath());
                // Try to rename the old file
                if (this.fileService.exists(mapFile.getAbsolutePath())
                        && !fileService.rename(mapFile.getAbsolutePath(), tempFile.getAbsolutePath())) {
                    logger.warn("Renaming the old map file failed! Path : {}", mapFile.getAbsolutePath());
                    continue;
                }
                logger.info("Write uploaded map file to disk. Path : \"{}\"", mapFile.getAbsolutePath());
                try {
                    // Write the uploaded file to disk
                    entry.getValue().transferTo(mapFile);
                } catch (IOException ex) {
                    logger.warn("Writing map file to disk failed!");
                    logger.error(ex.getMessage(), ex);
                    success = false;
                }
                // Check that the file really exists
                if (!fileService.exists(mapFile.getAbsolutePath())) {
                    logger.warn("Writing map file to disk failed! File doesn't exist. Path : \"{}\"",
                            mapFile.getAbsolutePath());
                    // If temp file exists, try to recover it
                    if (this.fileService.exists(tempFile.getAbsolutePath())
                            && !fileService.rename(tempFile.getAbsolutePath(), mapFile.getAbsolutePath())) {
                        logger.warn("Recovering the old map file failed! Path : {}", mapFile.getAbsolutePath());
                    } else if (logger.isDebugEnabled()) {
                        logger.debug("Old map file succesfully recovered from the temp file.");
                    }
                    success = false;
                } else {
                    // If temp file exists, delete it
                    if (fileService.exists(tempFile.getAbsolutePath())
                            && !fileService.delete(tempFile.getAbsolutePath())) {
                        logger.warn("Updating map failed! Unable to delete the temp file. Path : \"{}\"",
                                tempFile.getAbsolutePath());
                    } else if (logger.isDebugEnabled()) {
                        logger.debug("Temp file succesfully deleted.");
                    }
                }
            }
            if (!success) {
                logger.warn("Only part of the map files was updated.");
            }
        }
        // Try to update the DB
        if (dao.update(map)) {
            logger.info("Map updated : {}", this.jsonizer.jsonize(map, true));
            return true;
        }
        logger.warn("Failed to update Map : {}", json);
        return false;
    }

    /**
     * Returns a list of map files that exist in all the language admin
     * directories related to the given owner. If file is missing from one or
     * more language directory, it's not included in the results.
     *
     * @param owner owner of the map files
     * @return list of files that are present in all the language admin
     * directories
     */
    @Override
    public List<String> getAdminMaps(Owner owner) {
        // List for the results
        List<String> list = new ArrayList<String>();
        // Get languages related to the given owner
        List<Language> languages = languagesService.getLanguages(owner);
        // Get path of the maps admin dir
        String path = Settings.getInstance().getMapsPathAdmin(owner.getCode());
        // Create File object that represents the first language directory
        File source = new File(path + languages.get(0).getCode() + "/");
        // Get all the files in the directory
        String[] files = source.list();
        // Go through all the files
        for (int i = 0; i < files.length; i++) {
            boolean hit = true;
            // Check that the current file is present in all the language
            // directories
            for (Language lang : languages) {
                if (!fileService.exists(path + lang.getCode() + "/" + files[i])) {
                    // Skip other languages, if file doesn't exist.
                    hit = false;
                    break;
                }
            }
            // If file exists in all the language directories,
            // add it to the results
            if (hit) {
                list.add(files[i]);
            }
        }
        // Return results
        return list;
    }

    /**
     * Checks if the map object corresponding the give id can be removed from
     * the database.
     *
     * @param mapId the id number of the map to be removed
     * @return true if the map object can be removed, otherwise returns false
     */
    @Override
    public boolean canBeDeleted(int mapId) {
        return dao.canBeDeleted(mapId);
    }

    /**
     * Checks if a file denoted by the given dir and filename exists, and adds a
     * timestamp in the beginning of the filename if another file with the same
     * name already exists.
     *
     * @param dir absolute directory
     * @param filename name of the file
     * @return unique filename
     */
    private String getUniqueName(String dir, String filename) {
        String path = dir + filename;
        while (fileService.exists(path)) {
            filename = DateTimeUtil.getTimestamp() + "." + filename;
            path = dir + filename;
        }
        return filename;
    }

    /**
     * Checks if a file denoted by the given dir and filename exists in the
     * language directories, and adds a timestamp in the beginning of the
     * filename if another file with the same name already exists. The
     *
     * @param dir absolute directory
     * @param filename name of the file
     * @param languages list of languages to be checked
     * @return unique filename
     */
    private String getUniqueName(String dir, String filename, List<Language> languages) {
        boolean unique = true;
        for (Language lang : languages) {
            String path = dir + lang.getCode() + "/" + filename;
            if (fileService.exists(path)) {
                unique = false;
                break;
            }
        }
        if (unique) {
            return filename;
        }
        do {
            unique = true;
            filename = DateTimeUtil.getTimestamp() + "." + filename;
            for (Language lang : languages) {
                String path = dir + lang.getCode() + "/" + filename;
                if (fileService.exists(path)) {
                    unique = false;
                    break;
                }
            }
        } while (!unique);
        return filename;
    }

    /**
     * Returns a Map containing all the uploaded map files and a list of
     * languages in which they're available.
     *
     * @param owner owner of the map files
     * @return Map containing all the uploaded map files and a list of languages
     * in which they're available
     */
    @Override
    public java.util.Map<String, List<Language>> getUploadedMaps(Owner owner) {
        // Map for the results
        java.util.Map maps = new LinkedHashMap();
        // Get languages related to the given owner
        List<Language> languages = languagesService.getLanguages(owner);
        // Get path of the maps admin dir
        String path = Settings.getInstance().getMapsPathAdmin(owner.getCode());
        // Loop through all the languages
        for (Language lang : languages) {
            // Get list of file names in the current language directory
            List<String> files = this.dirService.getFilesStr(path + lang.getCode() + "/");
            // Go through all the files
            for (String file : files) {
                // If the file exists, add the language
                if (maps.containsKey(file)) {
                    ((List) maps.get(file)).add(lang);
                } else {
                    // If the file doesn't exist yet,
                    // Create a list for the languages
                    List temp = new ArrayList();
                    // Add the current language to the list
                    temp.add(lang);
                    // Add the file and the language list to the results
                    maps.put(file, temp);
                }
            }
        }
        // Return results
        return maps;
    }

    /**
     * Deletes the uploaded map file with given name, language and owner.
     *
     * @param fileName name of the map file
     * @param language language of the map file
     * @param owner owner of the map file
     * @return true if and only if the file was deleted; otherwise false
     */
    @Override
    public boolean delete(String fileName, Language language, Owner owner) {
        // Check for null values
        if (fileName == null || owner == null) {
            logger.error("Deleting uploaded image file failed! File name or owner can not be null.");
            return false;
        }
        // Get path of the maps admin dir
        String path = Settings.getInstance().getMapsPathAdmin(owner.getCode());
        // Append language code
        path += language.getCode() + "/";
        // Absolute target path
        path += fileName;
        // The file doesn't exist -> exit
        if (!this.adminMapExists(fileName, language, owner)) {
            logger.warn("Unable to delete the uploaded map file \"{}\", because the file doesn't exist.", path);
            return false;
        }
        // Try to delete the file
        if (!this.fileService.delete(path)) {
            logger.warn("Failed to delete the uploaded map file \"{}\".", path);
            return false;
        }
        logger.info("Uploaded map file \"{}\" was succesfully deleted.", path);
        return true;
    }

    /**
     * Returns a list of maps files that are located in the maps admin directory
     * under the given language related to the given owner.
     *
     * @param language language of the map
     * @param owner owner of the map files
     * @return list of map files
     */
    public List<String> getAdminMaps(Language language, Owner owner) {
        // Get path of the maps admin dir
        String path = Settings.getInstance().getMapsPathAdmin(owner.getCode());
        // Return results
        return dirService.getFilesStr(path + language.getCode());
    }

    /**
     * Checks that a map file with the given name exists in all the maps admin
     * directories. Returns true if and only if the given file is present in all
     * the admin language directories. Otherwise returns false.
     *
     * @param fileName name of the file
     * @param owner owner of the file
     * @return true if and only if the given file is present in all the admin
     * language directories; otherwise false
     */
    @Override
    public boolean adminMapExists(String fileName, Owner owner) {
        // Get list of files that exist in all the admin language dirs
        List<String> files = this.getAdminMaps(owner);
        // Go through the list
        for (String file : files) {
            if (file.equals(fileName)) {
                // The file exists, return true
                return true;
            }
        }
        // No match was found, return false
        return false;
    }

    /**
     * Checks that a map file with the given name exists in maps admin directory
     * in the given language related to the given owner.
     *
     * @param fileName name of the map file
     * @param language language of the map file
     * @param owner owner of the file
     * @return true if and only if the map exists; otherwise false
     */
    @Override
    public boolean adminMapExists(String fileName, Language language, Owner owner) {
        // Get list of uploaded maps related to the given owner
        List<String> maps = this.getAdminMaps(language, owner);
        // Go through the list and check that the given file exists
        for (String map : maps) {
            if (map.equals(fileName)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Checks that a map file with the given name exists in maps admin directory
     * at least in one of the languages related to the given owner.
     *
     * @param fileName name of the map file
     * @param languages languages related to the given owner
     * @param owner owner of the file
     * @return true if and only if the map exists; otherwise false
     */
    @Override
    public boolean adminMapExists(String fileName, List<Language> languages, Owner owner) {
        if (languages == null) {
            languages = this.languagesService.getLanguages(owner);
        }
        for (Language lang : languages) {
            if (this.adminMapExists(fileName, lang, owner)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Saves the given file in the maps directory of the Admin app under the
     * given language.
     *
     * @param file file to be saved
     * @param language language of the file
     * @param owner owner of the file
     * @return name of the file if and only if the file was saved; otherwise
     * null
     */
    @Override
    public String upload(MultipartFile file, Language language, Owner owner) {
        // Check for null values
        if (file == null || owner == null || language == null) {
            logger.warn("Writing map file to disk failed! File or owner can not be null.");
            return null;
        }

        // Get path of the maps admin dir
        String path = Settings.getInstance().getMapsPathAdmin(owner.getCode());
        // Add language code to the path
        path += language.getCode() + "/";
        // Get the name of the file
        String name = file.getOriginalFilename();
        // Name must be unique inside the target directory, NOT between
        // all the language directories
        name = this.getUniqueName(path, name);
        // Absolute target path
        path += name;

        // Create a new File object for the uploaded file
        File mapFile = new File(path);
        logger.info("Write uploaded map file to disk. Path : \"{}\"", path);

        try {
            // Write the uploaded file to disk
            file.transferTo(mapFile);
        } catch (IOException ex) {
            logger.warn("Writing map file to disk failed!");
            logger.error(ex.getMessage(), ex);
            return null;
        }
        // Check that the file really exists
        if (!fileService.exists(path)) {
            logger.warn("Writing map file to disk failed! File doesn't exist. Path : \"{}\"", path);
            return null;
        }
        logger.info("Writing uploaded map file to disk done. Path : \"{}\"", path);
        return name;
    }

    /**
     * Removes all the files related to the given Map object.
     *
     * @param map Map object which files are deleted
     * @return true if and only if all the existing files were successfully
     * deleted; otherwise false
     */
    private boolean deleteFiles(Map map) {
        boolean success = true;
        // Map file must be deleted from each language directory
        for (Language lang : languagesService.getLanguages(map.getOwner())) {
            // Build absolute path of the map file
            String path = IllustrationsUtil.buildFilePath(map, lang.getCode());
            if (path == null) {
                logger.warn(
                        "Deleting map file failed! Unable to build path for the map file. {\"id\":{},\"lang\":\"{}\"}",
                        map.getId(), lang.getCode());
                // Jump to next language
                continue;
            }
            // Try to delete the file only if it exists.
            if (!fileService.exists(path)) {
                logger.debug("Unable to delete map file, because it doesn't exist. File : {}", path);
                // Jump to next language
                continue;
            }
            // Delete the file
            if (!fileService.delete(path)) {
                success = false;
            }
        }
        return success;
    }
}