com.formkiq.core.api.FolderFilesController.java Source code

Java tutorial

Introduction

Here is the source code for com.formkiq.core.api.FolderFilesController.java

Source

/*
 * Copyright (C) 2016 FormKiQ Inc.
 *
 * 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 com.formkiq.core.api;

import static org.springframework.util.StringUtils.hasText;
import static org.springframework.web.bind.annotation.RequestMethod.DELETE;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.bind.annotation.RequestMethod.POST;

import java.io.IOException;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

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

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import com.formkiq.core.domain.type.ClientFormType;
import com.formkiq.core.domain.type.FolderFormLedgerListDTO;
import com.formkiq.core.domain.type.FolderFormStatus;
import com.formkiq.core.domain.type.FolderFormsListDTO;
import com.formkiq.core.domain.type.FolderFormsSearchCriteria;
import com.formkiq.core.domain.type.FormOrderByField;
import com.formkiq.core.domain.type.SortDirection;
import com.formkiq.core.form.JSONService;
import com.formkiq.core.form.dto.ArchiveDTO;
import com.formkiq.core.form.dto.Workflow;
import com.formkiq.core.service.ArchiveService;
import com.formkiq.core.service.FolderService;
import com.formkiq.core.service.PreconditionFailedException;
import com.formkiq.core.service.SpringSecurityService;
import com.formkiq.core.service.dto.ApiMessageResponse;
import com.formkiq.core.service.dto.FormSaveResult;
import com.formkiq.core.service.workflow.WorkflowService;
import com.formkiq.core.util.Strings;

/**
 * FoldersController rest services.
 *
 */
@RestController
public class FolderFilesController extends AbstractRestController {

    /** Root URI. */
    public static final String API_FOLDER_FILE = "/api/folders/files";

    /** GET Folder File url. */
    @Deprecated
    public static final String API_FOLDER_FILE_GET = API_FOLDER_FILE + "/get";
    /** SYNC url. */
    @Deprecated
    public static final String API_FOLDER_FILE_SAVE = API_FOLDER_FILE + "/save";
    /** LIST url. */
    public static final String API_FOLDER_FILE_LIST = API_FOLDER_FILE + "/list";
    /** LIST url. */
    public static final String API_FOLDER_FILE_LEDGER = API_FOLDER_FILE + "/ledger";
    /** DELETE Folder File url. */
    public static final String API_FOLDER_FILE_DELETE = API_FOLDER_FILE + "/delete";
    /** Email File's PDF. */
    public static final String API_FOLDER_FILE_EMAIL = API_FOLDER_FILE + "/email";

    /** {@link ArchiveService}. */
    @Autowired
    private ArchiveService archiveService;

    /** FolderService. */
    @Autowired
    private FolderService folderService;

    /** {@link JSONService}. */
    @Autowired
    private JSONService jsonService;

    /** {@link SpringSecurityService}. */
    @Autowired
    private SpringSecurityService securityService;

    /** {@link WorkflowService}. */
    @Autowired
    private WorkflowService workflowService;

    /**
     * Checks for Validation Errors.
     * @param errors {@link Map}
     */
    private void checkForValidationErrors(final Map<String, String> errors) {

        if (!errors.isEmpty()) {
            StringBuilder sb = new StringBuilder("Validation error\n");

            for (Map.Entry<String, String> e : errors.entrySet()) {
                sb.append(e.getKey() + ":" + e.getValue() + "\n");
            }

            throw new PreconditionFailedException(sb.toString().trim());
        }
    }

    /**
     * Deletes a Folder File.
     * @param request {@link HttpServletRequest}
     * @param folder {@link String}
     * @param parentuuid {@link String}
     * @param uuid {@link String}
     * @return {@link ApiMessageResponse}
     */
    @Transactional
    @RequestMapping(value = API_FOLDER_FILE_DELETE, method = DELETE)
    public ApiMessageResponse delete(final HttpServletRequest request,
            @RequestParam(value = "folder", required = true) final String folder,
            @RequestParam(value = "parent_uuid", required = false) final String parentuuid,
            @RequestParam(value = "uuid", required = false) final String uuid) {

        getApiVersion(request);

        UserDetails user = this.securityService.getUserDetails();

        if (!Strings.isEmpty(parentuuid)) {

            this.folderService.deleteFolderFile(user, folder, parentuuid, true);

        } else if (!Strings.isEmpty(uuid)) {

            this.folderService.deleteFolderFile(user, folder, uuid, false);

        } else {
            throw new PreconditionFailedException("'parent_uuid' or 'uuid' is required");
        }

        return new ApiMessageResponse("Deleted successful");
    }

    /**
     * Email File.
     * @param request {@link HttpServletRequest}
     * @return {@link ApiMessageResponse}
     * @throws IOException IOException
     */
    @Transactional
    @RequestMapping(value = API_FOLDER_FILE_EMAIL, method = POST)
    public ApiMessageResponse emailFolderFile(final HttpServletRequest request) throws IOException {

        ApiMessageResponse msg = new ApiMessageResponse("Email sent");

        Map<String, String[]> map = request.getParameterMap();

        String to = getParameter(map, "to", true);
        String subject = getParameter(map, "subject", true);
        String body = getParameter(map, "body", true);
        String folder = getParameter(map, "folder", true);
        String uuid = getParameter(map, "uuid", true);

        this.workflowService.emailForm(request, folder, uuid, to, subject, body);

        return msg;
    }

    /**
     * Folder File Ledger.
     * @param request {@link HttpServletRequest}
     * @return {@link FolderFormsListDTO}
     * @throws MissingServletRequestParameterException Exception
     */
    @Transactional
    @RequestMapping(value = API_FOLDER_FILE_LEDGER, method = GET)
    public FolderFormLedgerListDTO fileledger(final HttpServletRequest request)
            throws MissingServletRequestParameterException {

        Map<String, String[]> map = request.getParameterMap();

        String folder = getParameter(map, "folder", true);
        String uuid = getParameter(map, "uuid", true);

        return this.folderService.findFormLedger(folder, uuid);
    }

    /**
     * Folder File List.
     * @param request {@link HttpServletRequest}
     * @return {@link FolderFormsListDTO}
     * @throws MissingServletRequestParameterException Exception
     */
    @Transactional
    @RequestMapping(value = API_FOLDER_FILE_LIST, method = GET)
    public FolderFormsListDTO filelist(final HttpServletRequest request)
            throws MissingServletRequestParameterException {

        Map<String, String[]> map = request.getParameterMap();

        String folder = getParameter(map, "folder", true);
        String uuid = getParameter(map, "uuid", false);
        String token = getParameter(map, "token", false);

        List<FolderFormStatus> status = getParameters(map, "status", Arrays.asList(FolderFormStatus.ACTIVE),
                FolderFormStatus.class);

        SortDirection dir = getParameter(map, "orderdir", SortDirection.ASC, SortDirection.class);

        FormOrderByField orderby = getParameter(map, "order", FormOrderByField.NAME, FormOrderByField.class);

        FolderFormsSearchCriteria criteria = new FolderFormsSearchCriteria();
        criteria.setSearchText(getParameter(map, "text", false));

        if (map.containsKey("type")) {
            criteria.setType(getParameter(map, "type", null, ClientFormType.class));
        }

        criteria.setStatus(status);
        criteria.setSorter(dir);
        criteria.setOrderby(orderby);

        return this.folderService.findForms(folder, uuid, criteria, token);
    }

    /**
     * Gets a File.
     * @param request {@link HttpServletRequest}
     * @param response {@link HttpServletResponse}
     * @param folder {@link String}
     * @param uuid {@link String}
     * @throws IOException IOException
     */
    @Transactional
    @RequestMapping(value = API_FOLDER_FILE_GET, method = GET)
    public void getDep(final HttpServletRequest request, final HttpServletResponse response,
            @RequestParam(value = "folder", required = true) final String folder,
            @RequestParam(value = "uuid", required = true) final String uuid) throws IOException {
        get(request, response, folder, uuid, false);
    }

    /**
     * Gets a File.
     * @param request {@link HttpServletRequest}
     * @param response {@link HttpServletResponse}
     * @param folder {@link String}
     * @param uuid {@link String}
     * @param resetuuid {@link String}
     * @throws IOException IOException
     */
    @Transactional
    @RequestMapping(value = API_FOLDER_FILE + "/{folder}/{uuid}", method = GET)
    public void get(final HttpServletRequest request, final HttpServletResponse response,
            @PathVariable(name = "folder", required = true) final String folder,
            @PathVariable(name = "uuid", required = true) final String uuid,
            @RequestParam(value = "resetuuid", required = false) final boolean resetuuid) throws IOException {

        ArchiveDTO archiveDTO = null;
        String contentType = "application/zip";
        String accept = request.getHeader("Accept");
        String uri = request.getRequestURI();

        Pair<byte[], String> p = this.folderService.findFormData(folder, uuid);
        String sha1hash = p.getRight();
        byte[] data = p.getLeft();

        if (resetuuid) {
            archiveDTO = this.archiveService.extractJSONFromZipFile(data);
            this.archiveService.resetUUID(archiveDTO);
            data = this.archiveService.createZipFile(archiveDTO);
            sha1hash = "";
        }

        if (hasText(accept) && accept.contains("+json")) {

            archiveDTO = archiveDTO != null ? archiveDTO : this.archiveService.extractJSONFromZipFile(data);

            data = this.jsonService.writeValueAsBytes(archiveDTO);
            contentType = "application/json";
        }

        if (hasText(accept) && (accept.contains("+pdf") || uri.endsWith(".pdf"))) {

            contentType = "application/pdf";

            archiveDTO = archiveDTO != null ? archiveDTO : this.archiveService.extractJSONFromZipFile(data);

            if (archiveDTO.getPDF().isEmpty()) {
                this.folderService.createWorkflowOutput(archiveDTO);
            }

            if (archiveDTO.getPDF().isEmpty()) {
                throw new PreconditionFailedException("No PDF Found");
            }

            data = archiveDTO.getPDF().values().iterator().next();
        }

        response.addHeader("sha1hash", sha1hash);
        response.setContentType(contentType);
        response.setContentLengthLong(data.length);
        IOUtils.write(data, response.getOutputStream());
    }

    /**
     * Gets a File Outputs.
     *
     * @param request {@link HttpServletRequest}
     * @param response {@link HttpServletResponse}
     * @param folder {@link String}
     * @param uuid {@link String}
     * @return {@link Workflow}
     *
     * @throws IOException IOException
     */
    @Transactional
    @RequestMapping(value = API_FOLDER_FILE + "/{folder}/{uuid}/outputs", method = GET)
    public Workflow getOutputs(final HttpServletRequest request, final HttpServletResponse response,
            @PathVariable(name = "folder", required = true) final String folder,
            @PathVariable(name = "uuid", required = true) final String uuid) throws IOException {

        getApiVersion(request);

        Workflow workflow = new Workflow();
        workflow.setSteps(null);
        workflow.setPrintsteps(null);
        workflow.setVariables(null);
        workflow.setOutputs(this.folderService.findFormOutputs(folder, uuid));
        return workflow;
    }

    /**
     * Save File to Folder.
     * @param request {@link HttpServletRequest}
     * @param response {@link HttpServletResponse}
     * @param folder {@link String}
     * @param entity HttpEntity&lt;byte[]&gt;
     * @param lastSha1hash {@link String}
     * @return {@link ApiMessageResponse}
     * @throws IOException IOException
     */
    @Transactional
    @RequestMapping(value = API_FOLDER_FILE + "/{folder}", method = POST)
    public ApiMessageResponse saveFolderFile(final HttpServletRequest request, final HttpServletResponse response,
            @PathVariable(name = "folder", required = true) final String folder,
            @RequestParam(value = "sha1hash", required = false) final String lastSha1hash,
            final HttpEntity<byte[]> entity) throws IOException {

        getApiVersion(request);

        FormSaveResult result = null;
        ApiMessageResponse msg = new ApiMessageResponse("Save successful");

        Enumeration<String> e = request.getHeaders("accept");
        boolean isAdmin = this.securityService.isAdmin()
                && this.securityService.hasAcceptHeader(e, ACCEPT_HEADER_ADMIN);

        if (request instanceof MultipartHttpServletRequest) {

            MultipartHttpServletRequest rr = (MultipartHttpServletRequest) request;

            Iterator<String> itr = rr.getFileNames();
            MultipartFile mpf = rr.getFile(itr.next());
            result = this.folderService.saveForm(folder, mpf.getBytes(), lastSha1hash, isAdmin);
            checkForValidationErrors(result.getErrors());
            response.addHeader("sha1hash", result.getSha1hash());

        } else {

            result = this.folderService.saveForm(folder, entity.getBody(), lastSha1hash, isAdmin);
            checkForValidationErrors(result.getErrors());
            response.addHeader("sha1hash", result.getSha1hash());
        }

        if (FolderFormStatus.IN_PROCESS.equals(result.getStatus())) {
            msg = new ApiMessageResponse("Saved as 'In Process'");
        }

        return msg;
    }

    /**
     * Save File to Folder.
     * @param request {@link HttpServletRequest}
     * @param response {@link HttpServletResponse}
     * @param folder {@link String}
     * @param entity HttpEntity&lt;byte[]&gt;
     * @param lastSha1hash {@link String}
     * @return {@link ApiMessageResponse}
     * @throws IOException IOException
     */
    @Transactional
    @RequestMapping(value = API_FOLDER_FILE_SAVE, method = POST)
    public ApiMessageResponse saveFolderFileOld(final HttpServletRequest request,
            final HttpServletResponse response,
            @RequestParam(value = "folder", required = true) final String folder,
            @RequestParam(value = "sha1hash", required = false) final String lastSha1hash,
            final HttpEntity<byte[]> entity) throws IOException {
        return saveFolderFile(request, response, folder, lastSha1hash, entity);
    }
}