/**
   * Iterate returning all values.
   *
   * @return map of values
   */
  public Map<String, Object> iterate(int agentInstanceId) {
    Map<String, Object> values = new HashMap<String, Object>();

    int count = 0;
    for (VariableTriggerSetDesc assignment : assignments) {
      Object value;
      if (readersForGlobalVars[count] == null) {
        VariableReader reader = variableService.getReader(assignment.variableName, agentInstanceId);
        if (reader == null) {
          continue;
        }
        value = reader.getValue();
      } else {
        value = readersForGlobalVars[count].getValue();
      }

      if (value == null) {
        values.put(assignment.variableName, null);
      } else if (writers[count] != null) {
        EventBean current = (EventBean) value;
        values.put(assignment.variableName, writers[count].getGetter().get(current));
      } else if (value instanceof EventBean) {
        values.put(assignment.variableName, ((EventBean) value).getUnderlying());
      } else {
        values.put(assignment.variableName, value);
      }
      count++;
    }
    return values;
  }
 //
 // Methods
 //
 private void read() {
   add(valueReader.read());
 }
  /**
   * Write new variable values and commit, evaluating assignment expressions using the given events
   * per stream.
   *
   * <p>Populates an optional map of new values if a non-null map is passed.
   *
   * @param variableService variable service
   * @param eventsPerStream events per stream
   * @param valuesWritten null or an empty map to populate with written values
   * @param exprEvaluatorContext expression evaluation context
   */
  public void writeVariables(
      VariableService variableService,
      EventBean[] eventsPerStream,
      Map<String, Object> valuesWritten,
      ExprEvaluatorContext exprEvaluatorContext) {
    Set<String> variablesBeansCopied = null;
    if (!copyMethods.isEmpty()) {
      variablesBeansCopied = new HashSet<String>();
    }

    // We obtain a write lock global to the variable space
    // Since expressions can contain variables themselves, these need to be unchangeable for the
    // duration
    // as there could be multiple statements that do "var1 = var1 + 1".
    variableService.getReadWriteLock().writeLock().lock();
    try {
      variableService.setLocalVersion();

      int count = 0;
      for (VariableTriggerSetDesc assignment : assignments) {
        VariableMetaData variableMetaData = metaData[count];
        int agentInstanceId =
            variableMetaData.getContextPartitionName() == null
                ? VariableService.NOCONTEXT_AGENTINSTANCEID
                : exprEvaluatorContext.getAgentInstanceId();
        Object value = assignment.evaluator.evaluate(eventsPerStream, true, exprEvaluatorContext);

        if (writers[count] != null) {
          VariableReader reader =
              variableService.getReader(
                  variableMetaData.getVariableName(), exprEvaluatorContext.getAgentInstanceId());
          EventBean current = (EventBean) reader.getValue();
          if (current == null) {
            value = null;
          } else {
            WriteDesc writeDesc = writers[count];
            boolean copy = variablesBeansCopied.add(writeDesc.getVariableName());
            if (copy) {
              EventBean copied = copyMethods.get(writeDesc.getType()).copy(current);
              current = copied;
            }
            variableService.write(variableMetaData.getVariableNumber(), agentInstanceId, current);
            writeDesc.getWriter().write(value, current);
          }
        } else if (variableMetaData.getEventType() != null) {
          EventBean eventBean =
              eventAdapterService.adapterForType(value, variableMetaData.getEventType());
          variableService.write(variableMetaData.getVariableNumber(), agentInstanceId, eventBean);
        } else {
          if ((value != null) && (mustCoerce[count])) {
            value = JavaClassHelper.coerceBoxed((Number) value, variableMetaData.getType());
          }
          variableService.write(variableMetaData.getVariableNumber(), agentInstanceId, value);
        }

        count++;

        if (valuesWritten != null) {
          valuesWritten.put(assignment.variableName, value);
        }
      }

      variableService.commit();
    } catch (RuntimeException ex) {
      log.error("Error evaluating on-set variable expressions: " + ex.getMessage(), ex);
      variableService.rollback();
    } finally {
      variableService.getReadWriteLock().writeLock().unlock();
    }
  }