org.entcore.directory.controllers.TimetableController.java Source code

Java tutorial

Introduction

Here is the source code for org.entcore.directory.controllers.TimetableController.java

Source

/*
 * Copyright  "Open Digital Education", 2016
 *
 * This program is published by "Open Digital Education".
 * You must indicate the name of the software and the company in any production /contribution
 * using the software and indicate on the home page of the software industry in question,
 * "powered by Open Digital Education" with a reference to the website: https://opendigitaleducation.com/.
 *
 * This program is free software, licensed under the terms of the GNU Affero General Public License
 * as published by the Free Software Foundation, version 3 of the License.
 *
 * You can redistribute this application and/or modify it since you respect the terms of the GNU Affero General Public License.
 * If you modify the source code and then use this modified source code in your creation, you must make available the source code of your modifications.
 *
 * You should have received a copy of the GNU Affero General Public License along with the software.
 * If not, please see : <http://www.gnu.org/licenses/>. Full compliance requires reading the terms of this license and following its directives.
    
 */

package org.entcore.directory.controllers;

import fr.wseduc.bus.BusAddress;
import fr.wseduc.rs.ApiDoc;
import fr.wseduc.rs.Get;
import fr.wseduc.rs.Post;
import fr.wseduc.rs.Put;
import fr.wseduc.security.ActionType;
import fr.wseduc.security.SecuredAction;
import fr.wseduc.webutils.Either;
import fr.wseduc.webutils.I18n;
import fr.wseduc.webutils.http.BaseController;
import fr.wseduc.webutils.request.RequestUtils;
import org.entcore.common.http.filter.AdminFilter;
import org.entcore.common.http.filter.AdmlOfStructure;
import org.entcore.common.http.filter.ResourceFilter;
import org.entcore.common.http.filter.SuperAdminFilter;
import org.entcore.common.utils.StringUtils;
import org.entcore.directory.security.UserInStructure;
import org.entcore.directory.services.TimetableService;
import org.joda.time.DateTime;
import io.vertx.core.AsyncResult;
import io.vertx.core.Handler;
import io.vertx.core.eventbus.Message;
import io.vertx.core.http.HttpServerFileUpload;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;

import java.io.File;
import java.util.List;
import java.util.UUID;

import static fr.wseduc.webutils.Utils.getOrElse;
import static org.entcore.common.http.response.DefaultResponseHandler.*;
import static org.entcore.common.utils.FileUtils.deleteImportPath;

public class TimetableController extends BaseController {

    private TimetableService timetableService;

    @Get("/timetable")
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    @ResourceFilter(AdminFilter.class)
    public void timetable(HttpServerRequest request) {
        renderView(request);
    }

    @Get("/timetable/courses/:structureId")
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    @ResourceFilter(SuperAdminFilter.class)
    public void listCourses(HttpServerRequest request) {
        final String structureId = request.params().get("structureId");
        long lastDate;
        try {
            lastDate = Long.parseLong(getOrElse(request.params().get("lastDate"), "0", false));
        } catch (NumberFormatException e) {
            try {
                lastDate = DateTime.parse(request.params().get("lastDate")).getMillis();
            } catch (RuntimeException e2) {
                badRequest(request, "invalid.date");
                return;
            }
        }
        timetableService.listCourses(structureId, lastDate, arrayResponseHandler(request));
    }

    @Get("/timetable/courses/:structureId/:begin/:end")
    @ApiDoc("Get courses for a structure between two dates by optional teacher id and/or optional group name.")
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    @ResourceFilter(UserInStructure.class)
    public void listCoursesBetweenTwoDates(final HttpServerRequest request) {
        final String structureId = request.params().get("structureId");
        final String teacherId = request.params().get("teacherId");
        final List<String> groupNames = request.params().getAll("group");
        final String beginDate = request.params().get("begin");
        final String endDate = request.params().get("end");

        if (beginDate != null && endDate != null && beginDate.matches("\\d{4}-\\d{2}-\\d{2}")
                && endDate.matches("\\d{4}-\\d{2}-\\d{2}")) {
            timetableService.listCoursesBetweenTwoDates(structureId, teacherId, groupNames, beginDate, endDate,
                    arrayResponseHandler(request));
        } else {
            badRequest(request, "timetable.invalid.dates");
        }
    }

    @Get("/timetable/subjects/:structureId")
    @ApiDoc("Get subject list of the structure by optional teacher identifiers and with the ability to display associated groups and classes.")
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    @ResourceFilter(UserInStructure.class)
    public void listSubjects(HttpServerRequest request) {
        final String structureId = request.params().get("structureId");
        final List<String> teachers = request.params().getAll("teacherId");
        final boolean classes = request.params().contains("classes");
        final boolean groups = request.params().contains("groups");

        timetableService.listSubjects(structureId, teachers, classes, groups, arrayResponseHandler(request));
    }

    @Get("/timetable/subjects/:structureId/group")
    @ApiDoc("Get subject list of the structure by external group id.")
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    @ResourceFilter(UserInStructure.class)
    public void listSubjectsByGroup(HttpServerRequest request) {
        final String structureId = request.params().get("structureId");
        final String externalGroupId = request.params().get("externalGroupId");

        timetableService.listSubjectsByGroup(structureId, externalGroupId, arrayResponseHandler(request));
    }

    @Put("/timetable/init/:structureId")
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    @ResourceFilter(AdmlOfStructure.class)
    public void initStructure(final HttpServerRequest request) {
        RequestUtils.bodyToJson(request, pathPrefix + "initTimetable", new Handler<JsonObject>() {
            @Override
            public void handle(JsonObject conf) {
                timetableService.initStructure(request.params().get("structureId"), conf,
                        notEmptyResponseHandler(request));
            }
        });
    }

    @Get("/timetable/classes/:structureId")
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    @ResourceFilter(AdmlOfStructure.class)
    public void classesMapping(final HttpServerRequest request) {
        timetableService.classesMapping(request.params().get("structureId"), defaultResponseHandler(request));
    }

    @Put("/timetable/classes/:structureId")
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    @ResourceFilter(AdmlOfStructure.class)
    public void updateClassesMapping(final HttpServerRequest request) {
        RequestUtils.bodyToJson(request, new Handler<JsonObject>() {
            @Override
            public void handle(JsonObject mapping) {
                timetableService.updateClassesMapping(request.params().get("structureId"), mapping,
                        defaultResponseHandler(request));
            }
        });
    }

    @Post("/timetable/import/:structureId")
    @ResourceFilter(AdminFilter.class)
    @SecuredAction(value = "", type = ActionType.RESOURCE)
    public void importTimetable(final HttpServerRequest request) {
        request.pause();
        final String importId = UUID.randomUUID().toString();
        final String path = config.getString("timetable-path", "/tmp") + File.separator + importId;
        request.setExpectMultipart(true);
        request.exceptionHandler(new Handler<Throwable>() {
            @Override
            public void handle(Throwable event) {
                badRequest(request, event.getMessage());
                deleteImportPath(vertx, path);
            }
        });
        request.uploadHandler(new Handler<HttpServerFileUpload>() {
            @Override
            public void handle(final HttpServerFileUpload upload) {
                final String filename = path + File.separator + upload.filename();
                upload.endHandler(new Handler<Void>() {
                    @Override
                    public void handle(Void event) {
                        timetableService.importTimetable(request.params().get("structureId"), filename,
                                getHost(request), I18n.acceptLanguage(request),
                                reportResponseHandler(vertx, path, request));
                    }
                });
                upload.streamToFileSystem(filename);
            }
        });
        vertx.fileSystem().mkdir(path, new Handler<AsyncResult<Void>>() {
            @Override
            public void handle(AsyncResult<Void> event) {
                if (event.succeeded()) {
                    request.resume();
                } else {
                    badRequest(request, "mkdir.error");
                }
            }
        });
    }

    @BusAddress("timetable")
    @SuppressWarnings("unchecked")
    public void getTimetable(final Message<JsonObject> message) {
        final String action = message.body().getString("action");

        if (action == null) {
            log.warn("[@BusAddress](timetable) Invalid action.");
            message.reply(new JsonObject().put("status", "error").put("message", "Invalid action."));
            return;
        }

        final String structureId = message.body().getString("structureId");

        switch (action) {
        case "get.course":
            final String teacherId = message.body().getString("teacherId");
            final List<String> groupNames = message.body().getJsonArray("group", new JsonArray()).getList();
            final String beginDate = message.body().getString("begin");
            final String endDate = message.body().getString("end");

            if (beginDate != null && endDate != null && beginDate.matches("\\d{4}-\\d{2}-\\d{2}")
                    && endDate.matches("\\d{4}-\\d{2}-\\d{2}")) {

                timetableService.listCoursesBetweenTwoDates(structureId, teacherId, groupNames, beginDate, endDate,
                        getBusResultHandler(message));
            } else {
                message.reply(new JsonObject().put("status", "error").put("message", "timetable.invalid.dates"));
            }
            break;
        case "get.subjects":
            final List<String> teachers = message.body()
                    .getJsonArray("teacherIds", new fr.wseduc.webutils.collections.JsonArray()).getList();
            final String externalGroupId = message.body().getString("externalGroupId");
            final boolean classes = message.body().getBoolean("classes", false);
            final boolean groups = message.body().getBoolean("groups", false);

            if (StringUtils.isEmpty(externalGroupId)) {
                timetableService.listSubjects(structureId, teachers, classes, groups, getBusResultHandler(message));
            } else {
                timetableService.listSubjectsByGroup(structureId, externalGroupId, getBusResultHandler(message));
            }

            break;
        default:
            message.reply(new JsonObject().put("status", "error").put("message", "Invalid action."));
            break;
        }
    }

    private Handler<Either<String, JsonArray>> getBusResultHandler(final Message<JsonObject> message) {
        return new Handler<Either<String, JsonArray>>() {
            @Override
            public void handle(Either<String, JsonArray> result) {
                if (result.isRight()) {
                    message.reply(new JsonObject().put("status", "ok").put("results", result.right().getValue()));
                } else {
                    message.reply(new JsonObject().put("status", "error").put("message", result.left().getValue()));
                }
            }
        };
    }

    public void setTimetableService(TimetableService timetableService) {
        this.timetableService = timetableService;
    }

}