/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * Copyright (c) 2013, MPL CodeInside http://codeinside.ru */ package ru.codeinside.gses.activiti; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import org.activiti.engine.ActivitiException; import org.activiti.engine.impl.ServiceImpl; import org.activiti.engine.impl.persistence.entity.ExecutionEntity; import org.activiti.engine.repository.ProcessDefinition; import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import ru.codeinside.adm.database.Bid; import ru.codeinside.adm.database.DefinitionStatus; import ru.codeinside.adm.database.Procedure; import ru.codeinside.adm.database.ProcedureProcessDefinition; import ru.codeinside.adm.database.ProcedureType; import ru.codeinside.gses.activiti.forms.FormID; import ru.codeinside.gses.activiti.forms.api.definitions.BlockNode; import ru.codeinside.gses.activiti.forms.api.definitions.PropertyCollection; import ru.codeinside.gses.activiti.forms.api.definitions.PropertyNode; import ru.codeinside.gses.activiti.forms.api.definitions.PropertyTree; import ru.codeinside.gses.service.BidID; import ru.codeinside.gses.webui.FlashSupport; import ru.codeinside.gses.webui.form.DataAccumulator; import ru.codeinside.gses.webui.form.FormDescription; import ru.codeinside.gses.webui.form.FormDescriptionBuilder; import ru.codeinside.gses.webui.form.FormField; import ru.codeinside.gses.webui.form.GridForm; import ru.codeinside.gses.webui.form.TrivialFormPage; import javax.persistence.EntityManager; import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class ComplexFormTest extends Assert { @Rule final public InMemoryEngineRule engine = new InMemoryEngineRule(); @Test public void toggleOnly() { deployForm("Form1"); ProcessDefinition def = engine.getRepositoryService().createProcessDefinitionQuery().processDefinitionKey("cform1").singleResult(); assertNotNull(def); PropertyTree map = engine.getStartFormDefinition(def.getId()); final List<String> expected = Arrays.asList("a", "b", "^a", "~a", "c", "d", "^c", "~c"); assertEquals(expected, rootIdList(map)); assertEquals(expected, ImmutableList.copyOf(map.getIndex().keySet())); } @Test public void toggleInsideBlock() { deployForm("Form2"); ProcessDefinition def = engine.getRepositoryService().createProcessDefinitionQuery().processDefinitionKey("cform2").singleResult(); assertNotNull(def); PropertyTree map = engine.getStartFormDefinition(def.getId()); assertEquals(ImmutableList.of("+1"), rootIdList(map)); final List<String> all = Arrays.asList("+1", "a", "b", "^a", "~a", "c", "d", "^c", "~c"); assertEquals(all, ImmutableList.copyOf(map.getIndex().keySet())); BlockNode block = (BlockNode) map.getNodes()[0]; assertEquals(ImmutableList.of("a", "b", "^a", "~a", "c", "d", "^c", "~c"), rootIdList(block)); } @Test public void badBlockEnd() { try { deployForm("BadForm1"); fail("Форма содержит ошибку"); } catch (ActivitiException e) { assertEquals("Заверешение блока без начала -1 | cform/BadForm1.bpmn | line 17 | column 40", e.getMessage().trim()); } } @Test public void badBlockStart() { try { deployForm("BadForm2"); fail("Форма содержит ошибку"); } catch (ActivitiException e) { assertEquals("Начало блока без завершения +1 | cform/BadForm2.bpmn | line 6 | column 40", e.getMessage().trim()); } } @Test public void emptyBlock() { try { deployForm("BadForm3"); fail("Форма содержит ошибку"); } catch (ActivitiException e) { assertEquals("Пустой блок +1 | cform/BadForm3.bpmn | line 6 | column 40", e.getMessage().trim()); } } @Test public void blockInsideBlock() { deployForm("Form3"); ProcessDefinition def = engine.getRepositoryService().createProcessDefinitionQuery().processDefinitionKey("cform3").singleResult(); assertNotNull(def); createProcessDefinition(def); PropertyTree map = engine.getStartFormDefinition(def.getId()); assertEquals(ImmutableList.of("+1"), rootIdList(map)); final List<String> all = Arrays.asList("+1", "a", "b", "^a", "~a", "c", "d", "^c", "~c", "+2", "comment"); assertEquals(all, ImmutableList.copyOf(map.getIndex().keySet())); BlockNode block1 = (BlockNode) map.getNodes()[0]; assertEquals(ImmutableList.of("a", "b", "^a", "~a", "c", "d", "^c", "~c", "+2"), rootIdList(block1)); BlockNode block2 = (BlockNode) block1.getNodes()[8]; assertEquals(ImmutableList.of("comment"), rootIdList(block2)); final FormID formID = FormID.byProcessDefinitionId(def.getId()); FlashSupport.setLogin("login"); FormDescriptionBuilder builder = new FormDescriptionBuilder(formID, null, new DataAccumulator()); FormDescription formDescription = builder.apply(engine.getProcessEngine()); assertNotNull(formDescription); TrivialFormPage page = (TrivialFormPage) formDescription.flow.get(0); List<FormField> formFields = page.getFormFields(); List<String> paths = new ArrayList<String>(); for (FormField formField : formFields) { paths.add(formField.getPropId()); } assertEquals( ImmutableSet.of( "+1", "a_1", "b_1", "c_1", "d_1", "+2_1", "comment_1_1", "comment_1_2", "comment_1_3", "a_2", "b_2", "c_2", "d_2", "+2_2", "comment_2_1", "comment_2_2", "comment_2_3"), ImmutableSet.copyOf(paths) ); GridForm gridForm = (GridForm) page.getForm(formID, null); String dump = gridForm.fieldTree.dumpTree(); assertEquals(29, dump.split("\n").length); Map<String, Object> values = ImmutableMap.<String, Object>of("1", "1", "a_1", "2"); BidID bidID = ((ServiceImpl) engine.getFormService()) .getCommandExecutor() .execute(new SubmitStartFormCommand(null, null, def.getId(), values, null, "x", null, null) { void setExecutionDates(Bid bid, ExecutionEntity processInstance) { //избегаем вызова AdminService } }); assertEquals(1L, engine.getRuntimeService().getVariable(Long.toString(bidID.processId), "1")); } @Test public void manyForms() { final boolean DUMP_PIDS = false; ProcessDefinition def = engine.getRepositoryService().createProcessDefinitionQuery().processDefinitionKey("cform3").singleResult(); if (def == null) { deployForm("Form3"); def = engine.getRepositoryService().createProcessDefinitionQuery().processDefinitionKey("cform3").singleResult(); } createProcessDefinition(def); final Map<String, Object> values = ImmutableMap.<String, Object>of("1", "1", "a_1", "2"); final String id = def.getId(); final ServiceImpl formService = (ServiceImpl) engine.getFormService(); int N = 120; final ExecutorService executor = Executors.newCachedThreadPool(); final List<Future<String>> futures = new ArrayList<Future<String>>(); for (int i = 1; i <= N; i++) { final Future<String> future = executor.submit(new Callable<String>() { @Override public String call() throws Exception { BidID bidID = formService.getCommandExecutor().execute(new SubmitStartFormCommand(null, null, id, values, null, "x", null, null) { void setExecutionDates(Bid bid, ExecutionEntity processInstance) { //избегаем вызова AdminService } }); return Long.toString(bidID.bidId); } }); futures.add(future); } int ok = 0; for (final Future<String> future : futures) { try { String pid = future.get(1, TimeUnit.MINUTES); if (DUMP_PIDS) { System.out.print(" " + pid); } ok++; } catch (InterruptedException e) { e.printStackTrace(); break; } catch (ExecutionException e) { e.printStackTrace(); break; } catch (TimeoutException e) { e.printStackTrace(); break; } } executor.shutdownNow(); assertEquals(N, ok); } private void createProcessDefinition(ProcessDefinition def) { EntityManager em = engine.emf.createEntityManager(); em.getTransaction().begin(); if (em.find(ProcedureProcessDefinition.class, def.getId()) == null) { Procedure procedure = new Procedure(); procedure.setName("test"); procedure.setVersion("1.0"); procedure.setType(ProcedureType.Administrative); em.persist(procedure); ProcedureProcessDefinition pd = new ProcedureProcessDefinition(); pd.setProcessDefinitionKey("cform3"); pd.setProcessDefinitionId(def.getId()); pd.setVersion(new Double("1.0")); pd.setStatus(DefinitionStatus.Work); pd.setProcedure(procedure); em.persist(pd); } em.getTransaction().commit(); em.close(); } private void deployForm(String form) { final String resource = "cform/" + form + ".bpmn"; final InputStream is = getClass().getClassLoader().getResourceAsStream(resource); assertNotNull(resource, is); engine.getRepositoryService().createDeployment().addInputStream(resource, is).deploy(); } private List<String> rootIdList(PropertyCollection collection) { final PropertyNode[] nodes = collection.getNodes(); final ArrayList<String> ids = new ArrayList<String>(nodes.length); for (final PropertyNode node : nodes) { ids.add(node.getId()); } return ids; } @Test public void hideBlock() { deployForm("pfr-1018-1"); ProcessDefinition def = engine.getRepositoryService().createProcessDefinitionQuery().processDefinitionKey("pfr1018").singleResult(); assertNotNull(def); PropertyTree map = engine.getStartFormDefinition(def.getId()); assertEquals(ImmutableList.of("result_LastName", "result_FirstName", "result_SecondName", "result_SNILS", "result_DateBirth", "result_ResidenceAddress", "result_DateQuery", "result_PresenceData", "+PeriodRegistrationAccount", "+InfoPeriodsSeniority", "+BasisInclusionData", "result_NameOrgSZN", "result_DateFormationData", "~trigger"), rootIdList(map)); final List<String> all = Arrays.asList("result_LastName", "result_FirstName", "result_SecondName", "result_SNILS", "result_DateBirth", "result_ResidenceAddress", "result_DateQuery", "result_PresenceData", "+PeriodRegistrationAccount", "+AsTheUnemployed", "result_AtuDateStart", "result_AtuDateEnd", "+AsSearchWork", "result_AswDateStart", "result_AswDateEnd", "+InfoPeriodsSeniority", "+PeriodReceptionUnemploymentBenefit", "result_PrubDateStart", "result_PrubDateEnd", "+PeriodParticipationPaidPublicWorks", "result_PpppwDateStart", "result_PpppwDateEnd", "+PeriodMovingEmployment", "result_PmeDateStart", "result_PmeDateEnd", "+BasisInclusionData", "result_NumberPrivateAffair", "result_DatePrivateAffair", "result_NameOrgSZN", "result_DateFormationData", "~trigger"); assertEquals(all, ImmutableList.copyOf(map.getIndex().keySet())); BlockNode block1 = (BlockNode) map.getNodes()[8]; assertEquals(ImmutableList.of("+AsTheUnemployed", "+AsSearchWork"), rootIdList(block1)); BlockNode block2 = (BlockNode) block1.getNodes()[1]; assertEquals(ImmutableList.of("result_AswDateStart", "result_AswDateEnd"), rootIdList(block2)); final FormID formID = FormID.byProcessDefinitionId(def.getId()); FlashSupport.setLogin("login"); FormDescriptionBuilder builder = new FormDescriptionBuilder(formID, null, new DataAccumulator()); FormDescription formDescription = builder.apply(engine.getProcessEngine()); assertNotNull(formDescription); TrivialFormPage page = (TrivialFormPage) formDescription.flow.get(0); List<FormField> formFields = page.getFormFields(); List<String> paths = new ArrayList<String>(); for (FormField formField : formFields) { paths.add(formField.getPropId()); } assertEquals( ImmutableSet.of("result_PresenceData", "+PeriodRegistrationAccount", "+AsTheUnemployed_1", "result_AtuDateStart_1_1", "result_AtuDateEnd_1_1", "+AsSearchWork_1", "result_AswDateStart_1_1", "result_AswDateEnd_1_1", "+InfoPeriodsSeniority", "+PeriodReceptionUnemploymentBenefit_1", "result_PrubDateStart_1_1", "result_PrubDateEnd_1_1", "+PeriodParticipationPaidPublicWorks_1", "result_PpppwDateStart_1_1", "result_PpppwDateEnd_1_1", "+PeriodMovingEmployment_1", "result_PmeDateStart_1_1", "result_PmeDateEnd_1_1", "+BasisInclusionData", "result_NumberPrivateAffair_1", "result_DatePrivateAffair_1", "result_NameOrgSZN", "result_DateFormationData"), ImmutableSet.copyOf(paths) ); GridForm gridForm = (GridForm) page.getForm(formID, null); String dump = gridForm.fieldTree.dumpTree(); assertEquals(47, dump.split("\n").length); } }