Java tutorial
/* * 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<byte[]> * @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<byte[]> * @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); } }