Java tutorial
/* * Copyright (C) 2017 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.apache.commons.lang3.StringUtils.isEmpty; 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.Collection; import java.util.Date; import java.util.List; import java.util.Map; import java.util.UUID; import java.util.stream.Collectors; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.transaction.Transactional; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.http.HttpEntity; import org.springframework.security.access.annotation.Secured; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.formkiq.core.form.FormErrorException; import com.formkiq.core.form.JSONService; import com.formkiq.core.form.bean.FormInterceptor; import com.formkiq.core.form.bean.FormJSONFieldFieldInterceptor; import com.formkiq.core.form.bean.ObjectBuilder; import com.formkiq.core.form.dto.ArchiveDTO; import com.formkiq.core.form.dto.FormJSON; import com.formkiq.core.form.dto.HTMLSnippet; import com.formkiq.core.form.service.FormCalculatorService; import com.formkiq.core.form.service.FormService; import com.formkiq.core.form.service.FormValidatorService; import com.formkiq.core.form.webflow.FormFlowEventProcessor; import com.formkiq.core.service.FormNotFoundException; import com.formkiq.core.service.sign.PrintRenderer; import com.formkiq.core.service.workflow.WorkflowService; import com.formkiq.core.util.DateService; import com.formkiq.core.util.Strings; import com.formkiq.core.webflow.FlowState; import com.formkiq.core.webflow.FlowStateType; import com.formkiq.core.webflow.WebFlow; /** * Flow Rest Controller that handles interacting with current Flow. * TODO change to use {@link FormFlowEventProcessor} */ @RestController public class FormRestController extends AbstractRestController implements InitializingBean { /** Root URI. */ public static final String API_ROOT = "/api/form"; /** {@link ApplicationContext}. */ @Autowired private ApplicationContext context; /** {@link DateService}. */ @Autowired private DateService dateService; /** {@link FormService}. */ @Autowired private FormService formService; /** {@link FormCalculatorService}. */ @Autowired private FormCalculatorService formCalculatorService; /** {@link JSONService}. */ @Autowired private JSONService jsonService; /** {@link PrintRenderer}. */ @Autowired private PrintRenderer printRenderer; /** {@link FormValidatorService}. */ @Autowired private FormValidatorService validatorService; /** {@link WorkflowService}. */ @Autowired private WorkflowService workflowService; /** {@link FormJSONFieldFieldInterceptor}. */ private Collection<FormJSONFieldFieldInterceptor> fieldInterceptors; /** {@link FormInterceptor}. */ private Collection<FormInterceptor> formInterceptors; @Override public void afterPropertiesSet() throws Exception { this.fieldInterceptors = this.context.getBeansOfType(FormJSONFieldFieldInterceptor.class).values(); this.formInterceptors = this.context.getBeansOfType(FormInterceptor.class).values(); } /** * Delete the Form Data object. * @param request {@link HttpServletRequest} * @param className {@link String} * @param uuid {@link String} * * @throws IOException IOException * @throws ClassNotFoundException ClassNotFoundException * @throws IllegalAccessException IllegalAccessException * @throws InstantiationException InstantiationException */ @Transactional @Secured({ "ROLE_ADMIN" }) @RequestMapping(value = API_ROOT + "/{class}/{uuid}", method = DELETE) public void delete(final HttpServletRequest request, final @PathVariable(name = "class", required = true) String className, final @PathVariable(name = "uuid", required = true) String uuid) throws ClassNotFoundException, IOException, InstantiationException, IllegalAccessException { Class<?> clazz = Class.forName(className.replaceAll(".form$", "")); this.formService.delete(clazz, uuid); } /** * Process Form Events. * @param request {@link HttpServletRequest} * @param type {@link String} * @param event {@link String} * @param entity {@link HttpEntity} * @return {@link FormJSON} * @throws IOException IOException */ @RequestMapping(value = API_ROOT + "/event/{type}/{event}", method = POST) public FormJSON events(final HttpServletRequest request, final @PathVariable(name = "type", required = true) String type, final @PathVariable(name = "event", required = true) String event, final HttpEntity<byte[]> entity) throws IOException { FormJSON form = this.jsonService.readValue(entity.getBody(), FormJSON.class); return this.workflowService.handleFormEvents(form, type); } /** * Find {@link FormJSONFieldFieldInterceptor} for {@link Class}. * @param clazz {@link Class} * @param form {@link FormJSON} * @return {@link List} of {@link FormJSONFieldFieldInterceptor} */ private List<FormJSONFieldFieldInterceptor> findFieldInterceptors(final Class<?> clazz, final FormJSON form) { return this.fieldInterceptors.stream().filter(s -> s.isSupported(clazz, form)).collect(Collectors.toList()); } /** * Find {@link FormInterceptor} for {@link Class}. * * @param form {@link FormJSON} * @return {@link List} of {@link FormJSONFieldFieldInterceptor} */ private List<FormInterceptor> findFormInterceptors(final FormJSON form) { return this.formInterceptors.stream().filter(s -> s.isSupported(form)).collect(Collectors.toList()); } /** * Get Form. * @param request {@link HttpServletRequest} * @param response {@link HttpServletResponse} * @param className {@link String} * @param uuid {@link String} * @return {@link HTMLSnippet} * @throws IOException {@link IOException} * @throws ClassNotFoundException {@link ClassNotFoundException} * @throws ReflectiveOperationException {@link ReflectiveOperationException} */ @Secured({ "ROLE_ADMIN" }) @RequestMapping(value = { API_ROOT + "/{class}", API_ROOT + "/{class}/{uuid}" }, method = GET) public HTMLSnippet get(final HttpServletRequest request, final HttpServletResponse response, final @PathVariable(name = "class", required = true) String className, final @PathVariable(name = "uuid", required = false) String uuid) throws ClassNotFoundException, IOException, ReflectiveOperationException { Class<?> clazz = Class.forName(className.replaceAll(".form$", "")); FormJSON form = this.jsonService.loadForm(clazz); Date now = this.dateService.now(); form.setUUID(UUID.randomUUID().toString()); form.setInserteddate(now); form.setUpdateddate(now); if (!isEmpty(uuid) && Strings.isUUID(uuid)) { Object obj = this.formService.get(clazz, uuid); if (obj == null) { throw new FormNotFoundException(clazz.getName() + ": " + uuid + " not found."); } ObjectBuilder.populateFromObject(form, obj); } List<FormInterceptor> intercepts = findFormInterceptors(form); for (FormInterceptor i : intercepts) { i.preGet(form); } WebFlow flow = new WebFlow(1, null, Arrays.asList(new FlowState(FlowStateType.START), new FlowState(FlowStateType.DEFAULT, form))); return renderForm(request, flow, form); } /** * Render {@link FormJSON}. * @param request {@link HttpServletRequest} * @param flow {@link WebFlow} * @param form {@link FormJSON} * @return {@link HTMLSnippet} */ public HTMLSnippet renderForm(final HttpServletRequest request, final WebFlow flow, final FormJSON form) { Map<String, String> errors = flow.getCurrentState().getFielderrors(); return this.printRenderer.generateFormHTML(request, form, errors); } /** * Saves the Form Data object. * @param request {@link HttpServletRequest} * @param className {@link String} * @return {@link Map} form errors * @throws Exception Exception */ @Transactional @Secured({ "ROLE_ADMIN" }) @RequestMapping(value = { API_ROOT + "/{class}" }, method = POST) public Object save(final HttpServletRequest request, @PathVariable(name = "class", required = true) final String className) throws Exception { Class<?> clazz = Class.forName(className); FormJSON form = this.jsonService.loadForm(clazz); ArchiveDTO archive = new ArchiveDTO(); archive.addForm(form); this.formCalculatorService.applyFieldValues(archive, form, request); List<FormJSONFieldFieldInterceptor> intercepts = findFieldInterceptors(clazz, form); for (FormJSONFieldFieldInterceptor i : intercepts) { i.setValue(form); } Map<String, String> errors = this.validatorService.validateFormJSON(archive, form); List<FormInterceptor> cpt = findFormInterceptors(form); if (errors.isEmpty() && !cpt.isEmpty()) { for (FormInterceptor i : cpt) { errors.putAll(i.validateFormJSON(form)); } } if (errors.isEmpty()) { Object obj = clazz.newInstance(); obj = ObjectBuilder.buildObject(form, obj); for (FormInterceptor i : cpt) { i.preSave(form, obj); } this.formService.save(obj); for (FormInterceptor i : cpt) { i.postSave(form, obj); } } if (!errors.isEmpty()) { throw new FormErrorException(errors); } return form; } }