public ExampleIterator(OperatorDescription description) {
    super(description, "Example Process");
    outExtender.start();

    getTransformer().addPassThroughRule(exampleSetInput, exampleSetInnerSource);
    getTransformer().addRule(new SubprocessTransformRule(getSubprocess(0)));
    getTransformer()
        .addRule(
            new PassThroughRule(exampleSetInput, exampleSetOutput, false) {

              @Override
              public MetaData modifyMetaData(MetaData unmodifiedMetaData) {
                if (exampleSetInnerSink.isConnected()) {
                  return exampleSetInnerSink.getMetaData();
                } else {
                  // due to side effects, we cannot make any guarantee about the output.
                  return new ExampleSetMetaData();
                }
              }
            });
    getTransformer().addRule(outExtender.makePassThroughRule());

    addValue(
        new ValueDouble("iteration", "The number of the current iteration / loop / example.") {

          @Override
          public double getDoubleValue() {
            return iteration;
          }
        });
  }
  /**
   * Gets the input data and macro name and iterates over the example set while updating the current
   * iteration in the given macro.
   */
  @Override
  public void doWork() throws OperatorException {
    outExtender.reset();
    ExampleSet exampleSet = exampleSetInput.getData(ExampleSet.class);
    String iterationMacroName = getParameterAsString(PARAMETER_ITERATION_MACRO);
    boolean innerSinkIsConnected = exampleSetInnerSink.isConnected();

    for (iteration = 1; iteration <= exampleSet.size(); iteration++) {

      getProcess().getMacroHandler().addMacro(iterationMacroName, String.valueOf(iteration));

      // passing in clone or if connected the result from last iteration
      exampleSetInnerSource.deliver(
          innerSinkIsConnected ? exampleSet : (ExampleSet) exampleSet.clone());
      getSubprocess(0).execute();
      inApplyLoop();

      if (innerSinkIsConnected) {
        exampleSet = exampleSetInnerSink.getData(ExampleSet.class);
      }

      outExtender.collect();
    }

    getProcess().getMacroHandler().removeMacro(iterationMacroName);
    exampleSetOutput.deliver(exampleSet);
  }
  @Override
  public void doWork() throws OperatorException {
    ExampleSet exampleSet = exampleSetInput.getData(ExampleSet.class);

    Attribute[] labels = getLabels(exampleSet);
    if (labels.length == 0) {
      throw new UserError(this, 105);
    }

    outExtender.reset();
    for (int i = 0; i < labels.length; i++) {
      ExampleSet cloneSet = (ExampleSet) exampleSet.clone();
      cloneSet.getAttributes().setLabel(labels[i]);
      exampleInnerSource.deliver(cloneSet);

      getSubprocess(0).execute();
      outExtender.collect();
      inApplyLoop();
    }
  }
 public MultipleLabelIterator(OperatorDescription description) {
   super(description, "Iteration");
   outExtender.start();
   getTransformer()
       .addRule(
           new ExampleSetPassThroughRule(exampleSetInput, exampleInnerSource, SetRelation.EQUAL) {
             @Override
             public ExampleSetMetaData modifyExampleSet(ExampleSetMetaData metaData)
                 throws UndefinedParameterError {
               AttributeMetaData myLabel = metaData.getLabelMetaData();
               if (myLabel != null) metaData.removeAttribute(myLabel);
               for (AttributeMetaData amd : metaData.getAllAttributes()) {
                 if (amd.getName().startsWith(Attributes.LABEL_NAME)) {
                   amd.setRole(Attributes.LABEL_NAME);
                   break;
                 }
               }
               return metaData;
             }
           });
   getTransformer().addRule(new SubprocessTransformRule(getSubprocess(0)));
   getTransformer().addRule(outExtender.makePassThroughRule());
 }