Create an iterator using Package SDK

In Automation 360, you can create an iterator with the SDK package. An iterator is used to loop through multiple objects of similar type and is used with the Loop package. It consists of two methods, next and hasNext, which return the actual object and a boolean value.

Required annotations

When iterator is used, the next method returns the next available value. If no more values are available, an exception is shown. The hasNext method checks for other values and returns false if no more values are available. In Automation 360, when the loop is executed, hasNext() is called first, and next() is called only if hasNext() returned a true value.

For creating an iterator, the following annotations are required.

Annotation Usage
BotCommand Use the BotCommand annotation with an iterator as the commandType. This ensures that the plain old Java object (POJO) is eligible for creating an Automation 360 iterator.
CommandPkg When creating a package, provide a name, label, and description to the annotation.
Idx Annotate all parameters and member variables that are required and help with the validation check, or they can be displayed in the interface for the input. Provide the Idx and the type.
Pkg Annotate all parameters and member variables that will be displayed in the interface. This annotation will be ignored if it is not accompanied by the Idx.
HasNext The method that has to be called for testing if the iteration has more elements (returns true if next() returns an element rather than throwing an exception). It must return a Boolean value.

If the method accepts parameters, then they must be annotated with the Idx. The hasNext method verifies it and returns false if no more values are available. InAutomation 360, when Loop is executed, hasNext() is called first. next() is called only if hasNext() returns a true value.

Next The method returns the next available value in the iteration. The return type is a value. If no more value is available, an exception is shown.
Use case example

The example use case loops through number of times, for example, for (int i=0; I<n; i++) Java construct. It accepts the value of n from the Bot Creator when the bot is created.

  1. Make sure you have imported the following packages to ensure all the functionalities works as described in the sample.
    import com.automationanywhere.botcommand.data.Value;
    import com.automationanywhere.botcommand.data.impl.NumberValue;
    import com.automationanywhere.commandsdk.annotations.BotCommand;
    import com.automationanywhere.commandsdk.annotations.CommandPkg;
    import com.automationanywhere.commandsdk.annotations.HasNext;
    import com.automationanywhere.commandsdk.annotations.Idx;
    import com.automationanywhere.commandsdk.annotations.Inject;
    import com.automationanywhere.commandsdk.annotations.Next;
    import com.automationanywhere.commandsdk.annotations.Pkg;
    import com.automationanywhere.commandsdk.annotations.BotCommand.CommandType;
    import com.automationanywhere.commandsdk.annotations.rules.GreaterThanEqualTo;
    import com.automationanywhere.commandsdk.annotations.rules.NotEmpty;
    import com.automationanywhere.commandsdk.annotations.rules.NumberInteger;
    import com.automationanywhere.commandsdk.model.AttributeType;
    import com.automationanywhere.commandsdk.model.DataType;
  2. Create the POJO class with the business logic.

    Ensure that the POJO has a method and returns a boolean value. This will act as the comparison method.

    @BotCommand(commandType=CommandType.Iterator)
    @CommandPkg(return_label = "Return the value in variable", node_label = ": {{times}} times", 
    label = "Iterator demo", description = "Iterate number of times", name = "iteratorTypeDemo", return_type = DataType.NUMBER)
    public class IteratorTypeDemo {
        @Idx(index = "1", type = AttributeType.NUMBER)
        @Pkg(label = "times", default_value = "10", default_value_type = DataType.NUMBER)
        @GreaterThanEqualTo("0")
        @NumberInteger
        @NotEmpty
        @Inject
    	private Double times = 10d;
    
    	private Double counter = 0d;
    
        @HasNext
        public boolean hasNext() {
    		return counter < times;
        }
    
        @Next
        public Value<Double> next() throws Exception{
    		if (counter >= times)
    			throw new Exception("Counter '"+ counter +"' is exceed the times limit '"+times+"'");
    
    		counter++;
            NumberValue result = new NumberValue();
            result.set(counter);
            return result;
        }
    
        public void setTimes(Double times) {
            this.times = times;
        }
    }
  3. Annotate the POJO class to enable it for the Automation 360 iterator and to create a package.
    @BotCommand(commandType = CommandType.Iterator)
    @CommandPkg(return_label = "Return the value in variable", node_label = ": {{times}} times",
    	label = "Iterator demo", description = "Iterate number of times", name = "iteratorTypeDemo", return_type = DataType.NUMBER)
    public class IteratorTypeDemo {
    
    	private Double times = 10 d;
    	private Double counter = 0 d;
    
    	public boolean hasNext() {
    		return counter < times;
    	}
  4. Annotate the hasNext() and next() method appropriately.
    @HasNext
    public boolean hasNext() {
    	return counter < times;
    }
    
    @Next
    public Value < Double > next() throws Exception {
    	if (counter >= times)
    		throw new Exception("Counter '" + counter + "' is exceed the times limit '" + times + "'");
    
    	counter++;
    	NumberValue result = new NumberValue();
    	result.set(counter);
    	return result;
    }

    The methods are named in easy-to-use way and are in parallel with the Java iterator interface. There is no restriction from the SDK side when naming methods.

    In an iterator, do not use parameter methods, but use setter injection.

  5. Annotate the variables with Idx and Pkg.

    Add @NotEmpty to ensure the value is not null, and add @GreaterThanEqualTo to ensure the value is always greater than 0.

    @Idx(index = "1", type = AttributeType.NUMBER)
    @Pkg(label = "times", default_value = "10", default_value_type = DataType.NUMBER)
    @GreaterThanEqualTo("0")
    @NotEmpty
    @Inject
    private Double times = 10 d;

    The attribute type number returns a Double.