package com.yahoo.dtf.range;
import com.yahoo.dtf.range.EnumeratedRange;
import com.yahoo.dtf.range.RandomListRange;
import com.yahoo.dtf.range.Range;
import com.yahoo.dtf.range.RangeJoin;
import com.yahoo.dtf.range.SequentialRange;
import com.yahoo.dtf.exception.DTFException;
/**
* @dtf.feature Range Expressions
* @dtf.feature.group Ranges
*
* @dtf.feature.desc
* Range expressions are used to create/define properties with values that
* iterate over a collection of values or randomly choose from a collection of
* values. These ranges are used in some of the looping mechanisms within DTF
* and can be very useful for defining special identifiers to be used during
* the looping that can make your test much easier to write. The table below
* explains each type of range expression and has an example on how to use it.
*
* <table border='1'>
* <tr><th>Name</th><th>Description</th><th>Example</th></tr>
* <tr>
* <td>Sequential</td>
* <td><p>
* Defines a list of elements using only the boundary elements and
* allows for a more condensed representation of a n interval. The
* syntax is: <b>lowerlimit..upperlimit</b> where lowerlimit is an
* integer representing the first element in the list and upperlimit
* is an integer representing the last element. All other elements
* are generated by adding 1 to the current element.
* </p>
* </td>
* <td>
* {@dtf.xml
* <for property="prop" range="1..10">
* <log>Prop: ${prop}</log>
* </for>}
* <p>
* The above example will just print out each of those values that are
* separated by a coma.
* </p>
* </td>
* </tr>
*
* <tr>
* <td>Random</td>
* <td><p>The range expression will iterate randomly over the range
* expression defined as an argument. The syntax is
* random(your_expression), where your_expression can be any of
* the already existing range expressions. Now this expression is
* a little trickier to use because since it will select elements
* in a random order it doesn't really have an end or a beginning
* so you want to use it carefully.</p>
* </td>
* <td>
* {@dtf.xml
* <sequence>
* <createrange name="range" value="random(a,b,c,d1,e)"/>
* <for property="prop" range="1..5">
* <log>Prop: ${range}</log>
* </for>
* </sequence>}
* <p>The above example will print out 5 randomly chosen elements form
* the expression defined in the random expression.</p>
* </td>
* <tr>
*
* <tr>
* <td>Aggregate</td>
* <td><p>There is a simple way of aggregating ranges with the use of
* the square brackets. By wrapping an existing range expression
* in those brackets you create a sub-expression, like so:
* [expression1][expression2]. With this new syntax you can
* create ranges with fixed parts that iterate over a value of
* possible numbers. Like in the examples.</p>
* </td>
* <td>
* {@dtf.xml
* <createrange name="range" value="[client][1..10]"/>}
* <p>The above range would have the values client1,client2,client3...client10.</p>
* </td>
* </tr>
* </table>
*/
public class RangeFactory {
public static Range getRange(String regexp) throws DTFException {
RangeJoin range = new RangeJoin();
if (!regexp.startsWith("["))
regexp = "[" + regexp + "]";
int start = -1;
int startcnt = 0;
int endcnt = 0;
for (int i = 0; i < regexp.length(); i++) {
if ( regexp.charAt(i) == '[' ) {
startcnt++;
if ( start == -1 ) start = i;
} else if ( start != -1 && regexp.charAt(i) == ']' &&
(++endcnt == startcnt) ) {
Range aux = null;
String expression = regexp.substring(start+1,i);
// more restrictive range expression first
if ( XMLDataRange.matches(expression) ) {
aux = new XMLDataRange(expression);
} else if ( JSONDataRange.matches(expression) ) {
aux = new JSONDataRange(expression);
} else if ( RandomListRange.matches(expression) ) {
aux = new RandomListRange(expression);
} else if ( SequentialRange.matches(expression) ) {
aux = new SequentialRange(expression);
} else {
// everything defaults to an enumerated range
aux = new EnumeratedRange(expression);
}
range.addRange(aux);
start = -1;
startcnt = 0;
endcnt = 0;
}
}
return range;
}
}