/** * Copyright (C) 2012 BonitaSoft S.A. * BonitaSoft, 32 rue Gustave Eiffel - 38000 Grenoble * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2.0 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.bonitasoft.test.toolkit.bpm; import org.bonitasoft.engine.api.ProcessAPI; import org.bonitasoft.engine.bpm.flownode.ActivityStates; import org.bonitasoft.engine.bpm.flownode.HumanTaskInstance; import org.bonitasoft.engine.bpm.flownode.HumanTaskInstanceSearchDescriptor; import org.bonitasoft.engine.bpm.process.ArchivedProcessInstance; import org.bonitasoft.engine.bpm.process.ArchivedProcessInstancesSearchDescriptor; import org.bonitasoft.engine.bpm.process.ProcessInstance; import org.bonitasoft.engine.exception.SearchException; import org.bonitasoft.engine.search.Order; import org.bonitasoft.engine.search.SearchOptionsBuilder; import org.bonitasoft.engine.search.SearchResult; import org.bonitasoft.engine.session.APISession; import org.bonitasoft.engine.session.InvalidSessionException; import org.bonitasoft.test.toolkit.exception.NextActivityIsNotAllowedStateException; import org.bonitasoft.test.toolkit.exception.NoActivityLeftException; import org.bonitasoft.test.toolkit.exception.TestToolkitException; import org.bonitasoft.test.toolkit.organization.TestToolkitCtx; import org.bonitasoft.test.toolkit.organization.TestUser; /** * @author Vincent Elcrin * */ public class TestCase { private ProcessInstance processInstance; private final static int GET_NEXT_NB_ATTEMPT = 30; private final static int SLEEP_TIME_MS = 100; public final static String READY_STATE = "started"; public TestCase(final ProcessInstance instance) { processInstance = instance; } /** * Wait until the process return the state in parameter * * @param apiSession * @param state * @throws Exception */ public void waitProcessState(final APISession apiSession, final String state) { final ProcessAPI processAPI = TestProcess.getProcessAPI(apiSession); ProcessInstance instance = null; for (int i = 0; i < GET_NEXT_NB_ATTEMPT; i++) { try { instance = processAPI.getProcessInstance(processInstance.getId()); if (instance != null && state.equals(instance.getState())) { break; } Thread.sleep(SLEEP_TIME_MS); } catch (final Exception e) { throw new TestToolkitException("Can't get process instance <" + processInstance.getId() + ">.", e); } } if (instance == null || !state.equals(instance.getState())) { throw new TestToolkitException("Instance <" + processInstance.getId() + "> has not reached the expected state <" + state + ">."); } } /** * Search and get next human task * * @param apiSession * @return * @throws Exception */ public TestHumanTask getNextHumanTask(final APISession apiSession) { final ProcessAPI processAPI = TestProcess.getProcessAPI(apiSession); final SearchOptionsBuilder searchOptBuilder = new SearchOptionsBuilder(0, 1); searchOptBuilder.filter(HumanTaskInstanceSearchDescriptor.STATE_NAME, ActivityStates.READY_STATE); /** * Get next workable human task. (e.g not in initialization state) */ HumanTaskInstance humanTask = null; SearchResult<HumanTaskInstance> result = null; for (int i = 0; i < GET_NEXT_NB_ATTEMPT; i++) { try { result = processAPI.searchHumanTaskInstances(searchOptBuilder.done()); if (!result.getResult().isEmpty()) { humanTask = result.getResult().get(0); break; } Thread.sleep(SLEEP_TIME_MS); } catch (final InvalidSessionException e) { throw new TestToolkitException("Can't search human task instances. Invalid session", e); } catch (final SearchException e) { throw new TestToolkitException("Can't search human task instances", e); } catch (final InterruptedException e) { throw new TestToolkitException("Interrupted during searching process", e); } } if (humanTask != null) { return new TestHumanTask(humanTask); } else { if (result != null && result.getResult().size() > 0) { throw new NextActivityIsNotAllowedStateException(result.getResult().get(0)); } else { throw new NoActivityLeftException(); } } } /** * Check if state is allowed to be returned * * @param humanTask * @return */ private boolean isAllowedState(final HumanTaskInstance humanTask) { if (humanTask != null && !ActivityStates.INITIALIZING_STATE.equals(humanTask.getState())) { return true; } else { return false; } } public TestHumanTask getNextHumanTask() { return getNextHumanTask(TestToolkitCtx.getInstance().getInitiator().getSession()); } /** * @return the processInstance */ private ProcessInstance fetchProcessInstance(final APISession apiSession) { final ProcessAPI processAPI = TestProcess.getProcessAPI(apiSession); try { return processAPI.getProcessInstance(getId()); } catch (final Exception e) { throw new TestToolkitException("Can't get process instance for <" + getId() + ">. Not found", e); } } public TestCase refreshProcessInstance() { processInstance = fetchProcessInstance(TestToolkitCtx.getInstance().getInitiator().getSession()); return this; } public ProcessInstance getProcessInstance() { return processInstance; } private ArchivedProcessInstance getArchive(final APISession apiSession) { final ProcessAPI processAPI = TestProcess.getProcessAPI(apiSession); final SearchOptionsBuilder searchOptionsBuilder = new SearchOptionsBuilder(0, 1); searchOptionsBuilder.filter(ArchivedProcessInstancesSearchDescriptor.SOURCE_OBJECT_ID, getId()); searchOptionsBuilder.sort(ArchivedProcessInstancesSearchDescriptor.ARCHIVE_DATE, Order.DESC); SearchResult<ArchivedProcessInstance> searchArchivedProcessInstances = null; try { searchArchivedProcessInstances = processAPI.searchArchivedProcessInstancesInAllStates(searchOptionsBuilder.done()); } catch (final SearchException se) { throw new TestToolkitException("Can't get process instance archived for <" + getId() + ">", se); } if (searchArchivedProcessInstances != null && searchArchivedProcessInstances.getCount() > 0) { return searchArchivedProcessInstances.getResult().get(0); } else { throw new TestToolkitException("Can't get process instance archived for <" + getId() + ">"); } } public ArchivedProcessInstance getArchive(final TestUser initiator) { return getArchive(initiator.getSession()); } public ArchivedProcessInstance getArchive() { return getArchive(TestToolkitCtx.getInstance().getInitiator()); } public void archive() throws InterruptedException { final TestUser user = TestToolkitCtx.getInstance().getInitiator(); final APISession session = user.getSession(); try { while (true) { final TestHumanTask nextActivityInstance = getNextHumanTask(session); if (nextActivityInstance != null) { nextActivityInstance.assignTo(user).execute(session); } Thread.sleep(SLEEP_TIME_MS); } } catch (final NoActivityLeftException e) { // no more activity, finished } } public long getId() { return processInstance.getId(); } // /////////////////////////////////////////////////////////////////// // / Execution // /////////////////////////////////////////////////////////////////// public TestCase execute(final APISession apiSession) { try { final TestHumanTask nextActivityInstance = getNextHumanTask(apiSession); if (nextActivityInstance != null) { nextActivityInstance.execute(apiSession); } } catch (final NoActivityLeftException e) { // there were no activity in the process } return this; } public TestCase execute(final TestUser user) { return execute(user.getSession()); } public TestCase execute() throws Exception { return execute(TestToolkitCtx.getInstance().getInitiator()); } // /////////////////////////////////////////////////////////////////// // / Comments // /////////////////////////////////////////////////////////////////// private void addComment(final APISession apiSession, final String content) { final ProcessAPI processAPI = TestProcess.getProcessAPI(apiSession); try { processAPI.addComment(processInstance.getId(), content); } catch (final Exception e) { throw new TestToolkitException("Can't add comment to <" + processInstance.getId() + ">", e); } } private void addComment(final TestUser initiator, final String content) { addComment(initiator.getSession(), content); } public void addComments(final TestUser initiator, final int nbOfComments, final String content) { for (int i = 0; i < nbOfComments; i++) { addComment(initiator, content + i); } } public void addComment(final String content) { addComment(TestToolkitCtx.getInstance().getInitiator(), content); } }