/* * JBoss, Home of Professional Open Source. * Copyright 2009, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file 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.jboss.as.ejb3.timerservice.schedule.attribute; import org.jboss.as.ejb3.logging.EjbLogger; import org.jboss.as.ejb3.timerservice.schedule.ScheduleExpressionTypeUtil; import org.jboss.as.ejb3.timerservice.schedule.value.IncrementValue; import org.jboss.as.ejb3.timerservice.schedule.value.ListValue; import org.jboss.as.ejb3.timerservice.schedule.value.RangeValue; import org.jboss.as.ejb3.timerservice.schedule.value.ScheduleExpressionType; import org.jboss.as.ejb3.timerservice.schedule.value.ScheduleValue; import org.jboss.as.ejb3.timerservice.schedule.value.SingleValue; import java.util.HashSet; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; /** * Represents a {@link Integer} type value in a {@link javax.ejb.ScheduleExpression}. * <p/> * <p> * Examples for {@link IntegerBasedExpression} are the value of seconds, years, months etc... * which allow {@link Integer}. * </p> * * @author Jaikiran Pai * @version $Revision: $ */ public abstract class IntegerBasedExpression { protected abstract Integer getMaxValue(); protected abstract Integer getMinValue(); protected abstract boolean accepts(ScheduleExpressionType scheduleExprType); protected final SortedSet<Integer> absoluteValues = new TreeSet<Integer>(); protected final Set<ScheduleValue> relativeValues = new HashSet<ScheduleValue>(); protected final ScheduleExpressionType scheduleExpressionType; protected final String origValue; public IntegerBasedExpression(String value) { this.origValue = value; // check the type of value this.scheduleExpressionType = ScheduleExpressionTypeUtil.getType(value); if (this.accepts(scheduleExpressionType) == false) { throw EjbLogger.EJB3_TIMER_LOGGER.invalidScheduleExpressionType(value, this.getClass().getName(), this.scheduleExpressionType.toString()); } switch (this.scheduleExpressionType) { case RANGE: RangeValue range = new RangeValue(value); // process the range value this.processRangeValue(range); break; case LIST: ListValue list = new ListValue(value); // process the list value this.processListValue(list); break; case INCREMENT: IncrementValue incrValue = new IncrementValue(value); // process the increment value this.processIncrement(incrValue); break; case SINGLE_VALUE: SingleValue singleValue = new SingleValue(value); // process the single value this.processSingleValue(singleValue); break; case WILDCARD: // a wildcard is equivalent to "all possible" values, so // do nothing break; default: throw EjbLogger.EJB3_TIMER_LOGGER.invalidValueForSecondInScheduleExpression(value); } } protected void processListValue(ListValue list) { for (String listItem : list.getValues()) { this.processListItem(listItem); } } protected void processListItem(String listItem) { // check what type of a value the list item is. // Each item in the list must be an individual attribute value or a range. // List items can not themselves be lists, wild-cards, or increments. ScheduleExpressionType listItemType = ScheduleExpressionTypeUtil.getType(listItem); switch (listItemType) { case SINGLE_VALUE: SingleValue singleVal = new SingleValue(listItem); this.processSingleValue(singleVal); return; case RANGE: RangeValue range = new RangeValue(listItem); this.processRangeValue(range); return; default: throw EjbLogger.EJB3_TIMER_LOGGER.invalidListValue(listItem); } } protected void processRangeValue(RangeValue range) { String start = range.getStart(); String end = range.getEnd(); if (this.isRelativeValue(start) || this.isRelativeValue(end)) { this.relativeValues.add(range); return; } Integer rangeStart = this.parseInt(start); Integer rangeEnd = this.parseInt(end); // validations this.assertValid(rangeStart); this.assertValid(rangeEnd); // start and end are both the same. So it's just a single value if (rangeStart.equals(rangeEnd)) { this.absoluteValues.add(rangeStart); return; } if (rangeStart > rangeEnd) { // In range "x-y", if x is larger than y, the range is equivalent to // "x-max, min-y", where max is the largest value of the corresponding attribute // and min is the smallest. for (int i = rangeStart; i <= this.getMaxValue(); i++) { this.absoluteValues.add(i); } for (int i = this.getMinValue(); i <= rangeEnd; i++) { this.absoluteValues.add(i); } } else { // just keep adding from range start to range end (both inclusive). for (int i = rangeStart; i <= rangeEnd; i++) { this.absoluteValues.add(i); } } } protected void processIncrement(IncrementValue incr) { String startValue = incr.getStart(); Integer start = startValue.equals("*") ? 0 : this.parseInt(startValue); // make sure it's a valid value this.assertValid(start); Integer interval = this.parseInt(incr.getInterval()); this.absoluteValues.add(start); int next = start + interval; int maxValue = this.getMaxValue(); while (next <= maxValue) { this.absoluteValues.add(next); next = next + interval; } } protected void processSingleValue(SingleValue singleValue) { String value = singleValue.getValue(); if (this.isRelativeValue(value)) { this.relativeValues.add(singleValue); } else { Integer val = this.parseInt(value); this.assertValid(val); this.absoluteValues.add(val); } } protected Integer parseInt(String alias) { if (alias == null) { return null; } return Integer.parseInt(alias.trim()); } protected void assertValid(Integer value) throws IllegalArgumentException { if (value == null) { throw EjbLogger.EJB3_TIMER_LOGGER.couldNotParseScheduleExpression(this.origValue); } int max = this.getMaxValue(); int min = this.getMinValue(); if (value > max || value < min) { throw EjbLogger.EJB3_TIMER_LOGGER.invalidValuesRange(value, min, max); } } public abstract boolean isRelativeValue(String value); }