Index: modules/pvm/src/main/java/org/jbpm/pvm/internal/cal/Duration.java =================================================================== --- modules/pvm/src/main/java/org/jbpm/pvm/internal/cal/Duration.java (revision 6437) +++ modules/pvm/src/main/java/org/jbpm/pvm/internal/cal/Duration.java (working copy) @@ -30,27 +30,31 @@ import java.util.Map; import java.util.regex.Pattern; +import org.jbpm.api.Execution; import org.jbpm.api.JbpmException; +import org.jbpm.pvm.internal.el.Expression; import org.jbpm.pvm.internal.env.EnvironmentImpl; import org.jbpm.pvm.internal.script.ScriptManager; import org.jbpm.pvm.internal.util.Clock; /** * represents a time duration. - * - *

With the constructor {link {@link #Duration(String)} you can create a + * + *

With the constructor {link {@link #Duration(String)} you can create a * Duration from a text representation. The syntax is as follows *

- * + * *
  * duration = part [',' part | 'and' part]*
  * part = number ['business'] unit
  * number = (0..9)+
  * unit = (y|year|years|month|months|w|week|weeks|d|day|days|h|hour|hours|min|minute|minutes|s|sec|second|seconds|milli|millis|millisecond|milliseconds)
  * 
- * + * *

Duration is immutable. *

+ * + * @author Huisheng Xu */ public class Duration implements Serializable { @@ -65,12 +69,12 @@ protected int weeks; protected int months; protected int years; - + private final static String dateFormat = "yyyy-MM-dd HH:mm:ss"; - + private static final Pattern dateDurationPattern = Pattern.compile("\\s*(#\\{.+\\})\\s*" + "(?:(\\+|-)\\s*(\\d+\\s+(?:business\\s+)?\\w+))?\\s*"); - + private static final Pattern durationPattern = Pattern.compile("\\s*(\\d+\\s+(?:business\\s+)?" + "\\w+)\\s*"); @@ -78,13 +82,13 @@ protected Duration() { } - /** parses the duration from a text - * + /** parses the duration from a text + * * duration = part [',' part | 'and' part]* * part = number ['business'] unit * number = (0..9)+ * unit = (y|year|years|month|months|w|week|weeks|d|day|days|h|hour|hours|min|minute|minutes|s|sec|second|seconds|milli|millis|millisecond|milliseconds) - * + * * @throws JbpmException if the parsing is unsuccessful */ public Duration(String text) { @@ -93,19 +97,19 @@ for (String part: splitInParts(text)) { parsePart(part); } - + isBusinessTime = text.indexOf("business")!=-1; } - + public static boolean isValidExpression(String durationExpression) { try { - new Duration(durationExpression); + new Duration(durationExpression); } catch (JbpmException e) { return false; } return true; } - + public static Date calculateDueDate(String durationExpression) { Date duedate = null; if (durationExpression != null) { @@ -124,18 +128,27 @@ baseDate = (Date) result; } else if (result instanceof Calendar) { baseDate = ((Calendar) result).getTime(); + } else if (result instanceof String) { + baseDate = Clock.getTime(); + int endOfELIndex = durationExpression.indexOf("}"); + if (endOfELIndex < (durationExpression.length() - 1)) { + throw new JbpmException("Invalid duedate, didnot support + or - in String type EL."); + } + durationString = (String) Expression.create(durationExpression, null).evaluate((Execution) null); } else { throw new JbpmException("Invalid basedate type: " + baseDateEL + " is of type " + result.getClass().getName() + ". Only Date and Calendar are supported"); } - int endOfELIndex = durationExpression.indexOf("}"); - if (endOfELIndex < (durationExpression.length() - 1)) { - durationSeparator = durationExpression.substring(endOfELIndex + 1).trim().charAt(0); - if (durationSeparator != '+' && durationSeparator != '-') { - throw new JbpmException("Invalid duedate, + or - missing after EL"); + if (durationString == null) { + int endOfELIndex = durationExpression.indexOf("}"); + if (endOfELIndex < (durationExpression.length() - 1)) { + durationSeparator = durationExpression.substring(endOfELIndex + 1).trim().charAt(0); + if (durationSeparator != '+' && durationSeparator != '-') { + throw new JbpmException("Invalid duedate, + or - missing after EL"); + } + durationString = durationExpression.substring(endOfELIndex + 1).substring(2).trim(); } - durationString = durationExpression.substring(endOfELIndex + 1).substring(2).trim(); } } else { @@ -173,40 +186,40 @@ this.months = months; this.years = years; } - + private List splitInParts(String text) { List parts = new ArrayList(2); while (text!=null) { int commaIndex = text.indexOf(','); int andIndex = text.indexOf(" and "); - if ( ( (commaIndex==-1) + if ( ( (commaIndex==-1) && (andIndex!=-1) - ) - || - ( ( (commaIndex!=-1) + ) + || + ( ( (commaIndex!=-1) && (andIndex!=-1) - ) + ) && (andIndexcommaIndex) ) ) { String part = text.substring(0, commaIndex).trim(); parts.add(part); text = text.substring(commaIndex+1); - + } else { parts.add(text.trim()); text = null; @@ -224,7 +237,7 @@ String quantityText = part.substring(0, spaceIndex).trim(); spaceIndex = part.lastIndexOf(' '); String unitText = part.substring(spaceIndex+1).trim().toLowerCase(); - + int quantity; try { quantity = Integer.parseInt(quantityText); @@ -237,7 +250,7 @@ } fieldSetter.set(this, quantity); } - + interface FieldSetter { void set(Duration duration, int quantity); } @@ -325,7 +338,7 @@ fieldSetters.put("year", fieldSetter); fieldSetters.put("years", fieldSetter); } - + public int getDays() { return days; } @@ -353,7 +366,7 @@ public int getSeconds() { return seconds; } - + public int getWeeks() { return weeks; } Index: modules/test-db/src/test/java/org/jbpm/test/timer/TimerTest.java =================================================================== --- modules/test-db/src/test/java/org/jbpm/test/timer/TimerTest.java (revision 6437) +++ modules/test-db/src/test/java/org/jbpm/test/timer/TimerTest.java (working copy) @@ -1,451 +1,486 @@ -/* - * JBoss, Home of Professional Open Source - * Copyright 2005, JBoss Inc., and individual contributors as indicated - * by the @authors tag. See the copyright.txt in the distribution for a - * full listing of individual contributors. - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This software 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ -package org.jbpm.test.timer; - -import java.util.Calendar; -import java.util.HashMap; -import java.util.Map; - -import org.jbpm.api.Execution; -import org.jbpm.api.JbpmException; -import org.jbpm.api.ProcessInstance; -import org.jbpm.api.activity.ActivityExecution; -import org.jbpm.api.activity.ExternalActivityBehaviour; -import org.jbpm.api.job.Job; -import org.jbpm.api.listener.EventListener; -import org.jbpm.api.listener.EventListenerExecution; -import org.jbpm.test.JbpmTestCase; - -/** - * @author Tom Baeyens - * @author Ronald Van Kuijk - * @author Joram Barrez - */ -public class TimerTest extends JbpmTestCase { - - private static final String TEST_PROCESS_CUSTOM = - "" + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - ""; - - public void testTimerTimeout() { - deployJpdlXmlString( - "" + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - "" - ); - - ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL", "82436"); - - Job job = managementService.createJobQuery() - .processInstanceId(processInstance.getId()) - .uniqueResult(); - - managementService.executeJob(job.getId()); - assertProcessInstanceEnded(processInstance); - } - - /** - * Test case for https://jira.jboss.org/jira/browse/JBPM-2517 - * - * In this issue, it is stated that the calculations for the timer - * will overflow if larger than 4 weeks due to integer limitations. - */ - public void testTimerInFuture() { - deployJpdlXmlString( - "" + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - "" - ); - - ProcessInstance processInstance = executionService.startProcessInstanceByKey("theProcess"); - - Calendar now = Calendar.getInstance(); - int currentYear = now.get(Calendar.YEAR); - - Job job = managementService.createJobQuery() - .processInstanceId(processInstance.getId()) - .uniqueResult(); - - Calendar jobDate = Calendar.getInstance(); - jobDate.setTime(job.getDuedate()); - - assertEquals(currentYear + 10, jobDate.get(Calendar.YEAR)); - } - - public void testTimerELDate() { - deployJpdlXmlString( - "" + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - "" - ); - - Map proc_vars = new HashMap(); - Calendar cal = Calendar.getInstance(); - cal.add(Calendar.DAY_OF_MONTH, 6); - proc_vars.put("proc_var", cal.getTime()); - ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL", proc_vars, "82436"); - - Job job = managementService.createJobQuery() - .processInstanceId(processInstance.getId()) - .uniqueResult(); - - Calendar jobDate = Calendar.getInstance(); - jobDate.setTime(job.getDuedate()); - - assertEquals(cal.get(Calendar.DAY_OF_MONTH), jobDate.get(Calendar.DAY_OF_MONTH)); - - managementService.executeJob(job.getId()); - assertProcessInstanceEnded(processInstance); - } - - public void testTimerELCalendar() { - deployJpdlXmlString( - "" + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - "" - ); - - Map proc_vars = new HashMap(); - Calendar cal = Calendar.getInstance(); - cal.add(Calendar.DAY_OF_MONTH, 6); - proc_vars.put("proc_var", cal); - ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL", proc_vars, "82436"); - - Job job = managementService.createJobQuery() - .processInstanceId(processInstance.getId()) - .uniqueResult(); - - Calendar jobDate = Calendar.getInstance(); - jobDate.setTime(job.getDuedate()); - - assertEquals(cal.get(Calendar.DAY_OF_MONTH), jobDate.get(Calendar.DAY_OF_MONTH)); - - managementService.executeJob(job.getId()); - assertProcessInstanceEnded(processInstance); - } - - public void testTimerELCalendarAdd() { - deployJpdlXmlString( - "" + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - "" - ); - - Map proc_vars = new HashMap(); - Calendar cal = Calendar.getInstance(); - cal.add(Calendar.DAY_OF_MONTH, 6); - proc_vars.put("proc_var", cal); - ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL", proc_vars, "82436"); - - Job job = managementService.createJobQuery() - .processInstanceId(processInstance.getId()) - .uniqueResult(); - - Calendar jobDate = Calendar.getInstance(); - jobDate.setTime(job.getDuedate()); - - cal.add(Calendar.DAY_OF_MONTH, 5); - assertEquals(cal.get(Calendar.DAY_OF_MONTH), jobDate.get(Calendar.DAY_OF_MONTH)); - - managementService.executeJob(job.getId()); - assertProcessInstanceEnded(processInstance); - } - - public void testTimerELCalendarSubtract() { - deployJpdlXmlString( - "" + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - "" - ); - - Map proc_vars = new HashMap(); - Calendar cal = Calendar.getInstance(); - cal.add(Calendar.DAY_OF_MONTH, 6); - - proc_vars.put("proc_var", cal); - ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL", proc_vars, "82436"); - - Job job = managementService.createJobQuery() - .processInstanceId(processInstance.getId()) - .uniqueResult(); - - Calendar jobDate = Calendar.getInstance(); - jobDate.setTime(job.getDuedate()); - - // 6 days from now minus 5 days is tomorrow so subtract 5 from the original added 6. - cal.add(Calendar.DAY_OF_MONTH, -5); - assertEquals(cal.get(Calendar.DAY_OF_MONTH) , jobDate.get(Calendar.DAY_OF_MONTH)); - - managementService.executeJob(job.getId()); - assertProcessInstanceEnded(processInstance); - } - - public void testTimerELCalendarAddBusiness() { - deployJpdlXmlString( - "" + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - "" - ); - - Map proc_vars = new HashMap(); - Calendar cal = Calendar.getInstance(); - cal.set(2010, 01, 12, 12, 00, 00); // 12 feb 2010 noon - proc_vars.put("proc_var", cal); - ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL", proc_vars, "82436"); - - Job job = managementService.createJobQuery() - .processInstanceId(processInstance.getId()) - .uniqueResult(); - - Calendar jobDate = Calendar.getInstance(); - jobDate.setTime(job.getDuedate()); - - // 12 feb is friday, 5 businessdays further is friday 19th - assertEquals(19 , jobDate.get(Calendar.DAY_OF_MONTH)); - - managementService.executeJob(job.getId()); - assertProcessInstanceEnded(processInstance); - } - - public void testTimerELFail() { - deployJpdlXmlString( - "" + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - "" - ); - - Map proc_vars = new HashMap(); - proc_vars.put("proc_var", new Long(0)); - try { - executionService.startProcessInstanceByKey("ICL", proc_vars, "82436"); - fail("Should not happen, exception expected"); - } catch (Exception e) {} - } - - public void testTimerELSubtractBusinessFail() { - deployJpdlXmlString( - "" + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - "" - ); - - Map proc_vars = new HashMap(); - Calendar cal = Calendar.getInstance(); - cal.set(2010, 01, 12, 12, 00, 00); // 12 feb 2010 noon - proc_vars.put("proc_var", cal); - try { - executionService.startProcessInstanceByKey("ICL", proc_vars, "82436"); - fail("Should not happen, exception expected"); - } catch (Exception e) {} - } - - public void testTimerELSubtractPastFail() { - deployJpdlXmlString( - "" + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - " " + - "" - ); - - Map proc_vars = new HashMap(); - Calendar cal = Calendar.getInstance(); - cal.add(Calendar.DAY_OF_MONTH, 2); - proc_vars.put("proc_var", cal); - try { - executionService.startProcessInstanceByKey("ICL", proc_vars, "82436"); - fail("Should not happen, exception expected"); - } catch (Exception e) {} - } - - public void testTimerTimeoutCustom() { - deployJpdlXmlString(TEST_PROCESS_CUSTOM); - - ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL"); - assertEquals(Execution.STATE_INACTIVE_SCOPE, processInstance.getState()); - assertNotActivityActive(processInstance.getId(), "a"); - - // execute the async state so it becomes active - Job async = managementService.createJobQuery().messages().processInstanceId(processInstance.getId()).uniqueResult(); - managementService.executeJob(async.getId()); - assertActivityActive(processInstance.getId(), "a"); - - try { - executionService.signalExecutionById(processInstance.getId()); - fail("Should not happen, exception expected"); - } catch (JbpmException e) { - // Should happen....Signalling an inactive-scope exexcution is not - // allowed. If the timer is removed, this test should fail since the - // state of the execution is async then and signalling that is allowed. - } - - assertProcessInstanceActive(processInstance); - executionService.signalExecutionById(processInstance.getExecution("a").getId()); - assertActivityActive(processInstance.getId(), "b"); - } - - public void testTimerSignalCustom() { - deployJpdlXmlString(TEST_PROCESS_CUSTOM); - ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL"); - - Job async = managementService.createJobQuery().messages().processInstanceId(processInstance.getId()).uniqueResult(); - managementService.executeJob(async.getId()); - - int beforeTimer = MyCustomWait.nrOfTimesCalled; - Job timer = managementService.createJobQuery().timers().processInstanceId(processInstance.getId()).uniqueResult(); - managementService.executeJob(timer.getId()); - int afterTimer = MyCustomWait.nrOfTimesCalled; - assertEquals(beforeTimer + 1, afterTimer); - - assertProcessInstanceEnded(processInstance); - } - - public static class MyCustomWait implements ExternalActivityBehaviour, EventListener { - - private static final long serialVersionUID = 1L; - - static int nrOfTimesCalled; - - public void execute(ActivityExecution execution) throws Exception { - execution.waitForSignal(); - } - - public void signal(ActivityExecution execution, String signalName, Map parameters) throws Exception { - execution.take(signalName); - } - - public void notify(EventListenerExecution execution) throws Exception { - nrOfTimesCalled++; - } - } - +/* + * JBoss, Home of Professional Open Source + * Copyright 2005, JBoss Inc., and individual contributors as indicated + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jbpm.test.timer; + +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import org.jbpm.api.Execution; +import org.jbpm.api.JbpmException; +import org.jbpm.api.ProcessInstance; +import org.jbpm.api.activity.ActivityExecution; +import org.jbpm.api.activity.ExternalActivityBehaviour; +import org.jbpm.api.job.Job; +import org.jbpm.api.listener.EventListener; +import org.jbpm.api.listener.EventListenerExecution; +import org.jbpm.test.JbpmTestCase; + +/** + * @author Tom Baeyens + * @author Ronald Van Kuijk + * @author Joram Barrez + * @author Huisheng Xu + */ +public class TimerTest extends JbpmTestCase { + + private static final String TEST_PROCESS_CUSTOM = + "" + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + ""; + + public void testTimerTimeout() { + deployJpdlXmlString( + "" + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + "" + ); + + ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL", "82436"); + + Job job = managementService.createJobQuery() + .processInstanceId(processInstance.getId()) + .uniqueResult(); + + managementService.executeJob(job.getId()); + assertProcessInstanceEnded(processInstance); + } + + /** + * Test case for https://jira.jboss.org/jira/browse/JBPM-2517 + * + * In this issue, it is stated that the calculations for the timer + * will overflow if larger than 4 weeks due to integer limitations. + */ + public void testTimerInFuture() { + deployJpdlXmlString( + "" + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + "" + ); + + ProcessInstance processInstance = executionService.startProcessInstanceByKey("theProcess"); + + Calendar now = Calendar.getInstance(); + int currentYear = now.get(Calendar.YEAR); + + Job job = managementService.createJobQuery() + .processInstanceId(processInstance.getId()) + .uniqueResult(); + + Calendar jobDate = Calendar.getInstance(); + jobDate.setTime(job.getDuedate()); + + assertEquals(currentYear + 10, jobDate.get(Calendar.YEAR)); + } + + public void testTimerELDate() { + deployJpdlXmlString( + "" + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + "" + ); + + Map proc_vars = new HashMap(); + Calendar cal = Calendar.getInstance(); + cal.add(Calendar.DAY_OF_MONTH, 6); + proc_vars.put("proc_var", cal.getTime()); + ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL", proc_vars, "82436"); + + Job job = managementService.createJobQuery() + .processInstanceId(processInstance.getId()) + .uniqueResult(); + + Calendar jobDate = Calendar.getInstance(); + jobDate.setTime(job.getDuedate()); + + assertEquals(cal.get(Calendar.DAY_OF_MONTH), jobDate.get(Calendar.DAY_OF_MONTH)); + + managementService.executeJob(job.getId()); + assertProcessInstanceEnded(processInstance); + } + + public void testTimerELCalendar() { + deployJpdlXmlString( + "" + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + "" + ); + + Map proc_vars = new HashMap(); + Calendar cal = Calendar.getInstance(); + cal.add(Calendar.DAY_OF_MONTH, 6); + proc_vars.put("proc_var", cal); + ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL", proc_vars, "82436"); + + Job job = managementService.createJobQuery() + .processInstanceId(processInstance.getId()) + .uniqueResult(); + + Calendar jobDate = Calendar.getInstance(); + jobDate.setTime(job.getDuedate()); + + assertEquals(cal.get(Calendar.DAY_OF_MONTH), jobDate.get(Calendar.DAY_OF_MONTH)); + + managementService.executeJob(job.getId()); + assertProcessInstanceEnded(processInstance); + } + + public void testTimerELString() { + deployJpdlXmlString( + "" + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + "" + ); + + Map proc_vars = new HashMap(); + proc_vars.put("proc_var", "2 minutes"); + + ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL", proc_vars, "82436"); + + Job job = managementService.createJobQuery() + .processInstanceId(processInstance.getId()) + .uniqueResult(); + + Date jobDate = job.getDuedate(); + assertTrue("should less than 2 minutes", jobDate.getTime() - new Date().getTime() < 2 * 60 * 1000); + + managementService.executeJob(job.getId()); + assertProcessInstanceEnded(processInstance); + } + + public void testTimerELCalendarAdd() { + deployJpdlXmlString( + "" + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + "" + ); + + Map proc_vars = new HashMap(); + Calendar cal = Calendar.getInstance(); + cal.add(Calendar.DAY_OF_MONTH, 6); + proc_vars.put("proc_var", cal); + ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL", proc_vars, "82436"); + + Job job = managementService.createJobQuery() + .processInstanceId(processInstance.getId()) + .uniqueResult(); + + Calendar jobDate = Calendar.getInstance(); + jobDate.setTime(job.getDuedate()); + + cal.add(Calendar.DAY_OF_MONTH, 5); + assertEquals(cal.get(Calendar.DAY_OF_MONTH), jobDate.get(Calendar.DAY_OF_MONTH)); + + managementService.executeJob(job.getId()); + assertProcessInstanceEnded(processInstance); + } + + public void testTimerELCalendarSubtract() { + deployJpdlXmlString( + "" + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + "" + ); + + Map proc_vars = new HashMap(); + Calendar cal = Calendar.getInstance(); + cal.add(Calendar.DAY_OF_MONTH, 6); + + proc_vars.put("proc_var", cal); + ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL", proc_vars, "82436"); + + Job job = managementService.createJobQuery() + .processInstanceId(processInstance.getId()) + .uniqueResult(); + + Calendar jobDate = Calendar.getInstance(); + jobDate.setTime(job.getDuedate()); + + // 6 days from now minus 5 days is tomorrow so subtract 5 from the original added 6. + cal.add(Calendar.DAY_OF_MONTH, -5); + assertEquals(cal.get(Calendar.DAY_OF_MONTH) , jobDate.get(Calendar.DAY_OF_MONTH)); + + managementService.executeJob(job.getId()); + assertProcessInstanceEnded(processInstance); + } + + public void testTimerELCalendarAddBusiness() { + deployJpdlXmlString( + "" + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + "" + ); + + Map proc_vars = new HashMap(); + Calendar cal = Calendar.getInstance(); + cal.set(2010, 01, 12, 12, 00, 00); // 12 feb 2010 noon + proc_vars.put("proc_var", cal); + ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL", proc_vars, "82436"); + + Job job = managementService.createJobQuery() + .processInstanceId(processInstance.getId()) + .uniqueResult(); + + Calendar jobDate = Calendar.getInstance(); + jobDate.setTime(job.getDuedate()); + + // 12 feb is friday, 5 businessdays further is friday 19th + assertEquals(19 , jobDate.get(Calendar.DAY_OF_MONTH)); + + managementService.executeJob(job.getId()); + assertProcessInstanceEnded(processInstance); + } + + public void testTimerELFail() { + deployJpdlXmlString( + "" + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + "" + ); + + Map proc_vars = new HashMap(); + proc_vars.put("proc_var", new Long(0)); + try { + executionService.startProcessInstanceByKey("ICL", proc_vars, "82436"); + fail("Should not happen, exception expected"); + } catch (Exception e) {} + } + + public void testTimerELSubtractBusinessFail() { + deployJpdlXmlString( + "" + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + "" + ); + + Map proc_vars = new HashMap(); + Calendar cal = Calendar.getInstance(); + cal.set(2010, 01, 12, 12, 00, 00); // 12 feb 2010 noon + proc_vars.put("proc_var", cal); + try { + executionService.startProcessInstanceByKey("ICL", proc_vars, "82436"); + fail("Should not happen, exception expected"); + } catch (Exception e) {} + } + + public void testTimerELSubtractPastFail() { + deployJpdlXmlString( + "" + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + "" + ); + + Map proc_vars = new HashMap(); + Calendar cal = Calendar.getInstance(); + cal.add(Calendar.DAY_OF_MONTH, 2); + proc_vars.put("proc_var", cal); + try { + executionService.startProcessInstanceByKey("ICL", proc_vars, "82436"); + fail("Should not happen, exception expected"); + } catch (Exception e) {} + } + + public void testTimerTimeoutCustom() { + deployJpdlXmlString(TEST_PROCESS_CUSTOM); + + ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL"); + assertEquals(Execution.STATE_INACTIVE_SCOPE, processInstance.getState()); + assertNotActivityActive(processInstance.getId(), "a"); + + // execute the async state so it becomes active + Job async = managementService.createJobQuery().messages().processInstanceId(processInstance.getId()).uniqueResult(); + managementService.executeJob(async.getId()); + assertActivityActive(processInstance.getId(), "a"); + + try { + executionService.signalExecutionById(processInstance.getId()); + fail("Should not happen, exception expected"); + } catch (JbpmException e) { + // Should happen....Signalling an inactive-scope exexcution is not + // allowed. If the timer is removed, this test should fail since the + // state of the execution is async then and signalling that is allowed. + } + + assertProcessInstanceActive(processInstance); + executionService.signalExecutionById(processInstance.getExecution("a").getId()); + assertActivityActive(processInstance.getId(), "b"); + } + + public void testTimerSignalCustom() { + deployJpdlXmlString(TEST_PROCESS_CUSTOM); + ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL"); + + Job async = managementService.createJobQuery().messages().processInstanceId(processInstance.getId()).uniqueResult(); + managementService.executeJob(async.getId()); + + int beforeTimer = MyCustomWait.nrOfTimesCalled; + Job timer = managementService.createJobQuery().timers().processInstanceId(processInstance.getId()).uniqueResult(); + managementService.executeJob(timer.getId()); + int afterTimer = MyCustomWait.nrOfTimesCalled; + assertEquals(beforeTimer + 1, afterTimer); + + assertProcessInstanceEnded(processInstance); + } + + public static class MyCustomWait implements ExternalActivityBehaviour, EventListener { + + private static final long serialVersionUID = 1L; + + static int nrOfTimesCalled; + + public void execute(ActivityExecution execution) throws Exception { + execution.waitForSignal(); + } + + public void signal(ActivityExecution execution, String signalName, Map parameters) throws Exception { + execution.take(signalName); + } + + public void notify(EventListenerExecution execution) throws Exception { + nrOfTimesCalled++; + } + } + } \ No newline at end of file