public TransformerComponentBuilder(
     AnalysisJobBuilder analysisJobBuilder,
     TransformerDescriptor<T> descriptor,
     IdGenerator idGenerator) {
   super(analysisJobBuilder, descriptor, TransformerComponentBuilder.class);
   _id = "trans-" + idGenerator.nextId();
   _idGenerator = idGenerator;
   _localChangeListeners = new ArrayList<TransformerChangeListener>(0);
 }
  /**
   * Gets the output column of this transformation with it's current configuration.
   *
   * @return
   */
  public List<MutableInputColumn<?>> getOutputColumns() {
    final Component component = getComponentInstanceForQuestioning();
    if (component == null) {
      // as long as the transformer is not configured, just return an
      // empty list
      return Collections.emptyList();
    }

    final Transformer transformer = (Transformer) component;

    final OutputColumns outputColumns = transformer.getOutputColumns();
    if (outputColumns == null) {
      throw new IllegalStateException(
          "getOutputColumns() returned null on transformer: " + transformer);
    }
    boolean changed = false;

    // adjust the amount of output columns
    final int expectedCols = outputColumns.getColumnCount();
    final int existingCols = _outputColumns.size();
    if (expectedCols != existingCols) {
      changed = true;
      int colDiff = expectedCols - existingCols;
      if (colDiff > 0) {
        for (int i = 0; i < colDiff; i++) {
          final int nextIndex = _outputColumns.size();
          final String name = getColumnName(outputColumns, nextIndex);
          final String id = _id + "-" + _idGenerator.nextId();
          _outputColumns.add(new TransformedInputColumn<Object>(name, id));
          _automaticOutputColumnNames.add(name);
        }
      } else if (colDiff < 0) {
        for (int i = 0; i < Math.abs(colDiff); i++) {
          // remove from the tail
          _outputColumns.remove(_outputColumns.size() - 1);
          _automaticOutputColumnNames.remove(_automaticOutputColumnNames.size() - 1);
        }
      }

      // reset the names when the number of output columns change and the
      // initial name has changed
      for (int i = 0; i < expectedCols; i++) {
        final MutableInputColumn<?> column = _outputColumns.get(i);
        final String previousProposedName = column.getInitialName();
        final String newProposedName = outputColumns.getColumnName(i);
        if (newProposedName != null && !newProposedName.equals(previousProposedName)) {
          column.setName(newProposedName);
        }
      }
    }

    // automatically update names and types of columns if they have not been
    // manually set
    for (int i = 0; i < expectedCols; i++) {
      final String proposedName = getColumnName(outputColumns, i);
      final Class<?> dataType = outputColumns.getColumnType(i);

      final TransformedInputColumn<?> col = (TransformedInputColumn<?>) _outputColumns.get(i);
      col.setInitialName(proposedName);
      if (dataType != col.getDataType()) {
        col.setDataType(dataType);
        changed = true;
      }

      final String automaticName = _automaticOutputColumnNames.get(i);
      final String columnName = col.getName();
      if (StringUtils.isNullOrEmpty(columnName) || automaticName.equals(columnName)) {
        if (proposedName != null) {
          col.setName(proposedName);
          _automaticOutputColumnNames.set(i, proposedName);
        }
      }
    }

    if (changed) {
      // notify listeners
      onOutputChanged();
    }

    return Collections.unmodifiableList(_outputColumns);
  }