001package com.streamconverter.controller;
002
003import com.streamconverter.command.CommandConfig;
004import com.streamconverter.command.impl.SampleStreamCommand;
005import com.streamconverter.command.impl.csv.CsvNavigateCommand;
006
007/**
008 * Controller for CSV data processing operations.
009 *
010 * <p>This controller demonstrates how to configure command pipelines for CSV processing. It
011 * provides several processing modes:
012 *
013 * <ul>
014 *   <li>Column extraction - Extract specific columns by name or index
015 *   <li>Row filtering - Filter rows based on criteria
016 *   <li>Data transformation - Transform CSV data with additional processing
017 *   <li>Validation - Validate CSV structure and content
018 * </ul>
019 *
020 * <p>Usage examples:
021 *
022 * <pre>
023 * // Extract specific column
024 * CsvProcessingController controller = CsvProcessingController.forColumnExtraction("name");
025 * controller.process(inputStream, outputStream);
026 *
027 * // Complex processing pipeline
028 * CsvProcessingController controller = CsvProcessingController.forComplexProcessing("data", "processor-id");
029 * controller.process(inputStream, outputStream);
030 * </pre>
031 *
032 * @author StreamConverter Team
033 * @version 1.0
034 * @since 1.0
035 */
036public class CsvProcessingController extends AbstractStreamController {
037
038  /** Processing mode enumeration */
039  public enum ProcessingMode {
040    /** Extract specific column data from CSV */
041    COLUMN_EXTRACTION,
042    /** Perform complex multi-step processing */
043    COMPLEX_PROCESSING,
044    /** Validate CSV format only */
045    VALIDATION_ONLY,
046    /** Pass through CSV data unchanged */
047    PASS_THROUGH
048  }
049
050  /** The processing mode for this controller */
051  private final ProcessingMode mode;
052
053  /** Column name or index for extraction */
054  private final String columnSelector;
055
056  /** Additional processor ID for complex processing */
057  private final String processorId;
058
059  /**
060   * Creates a controller for column extraction.
061   *
062   * @param columnSelector the column name or index to extract
063   */
064  private CsvProcessingController(String columnSelector) {
065    this.mode = ProcessingMode.COLUMN_EXTRACTION;
066    this.columnSelector = columnSelector;
067    this.processorId = null;
068  }
069
070  /**
071   * Creates a controller for complex processing.
072   *
073   * @param columnSelector the column name or index to extract
074   * @param processorId the processor ID for additional processing
075   */
076  private CsvProcessingController(String columnSelector, String processorId) {
077    this.mode = ProcessingMode.COMPLEX_PROCESSING;
078    this.columnSelector = columnSelector;
079    this.processorId = processorId;
080  }
081
082  /** Creates a controller for pass-through processing. */
083  private CsvProcessingController() {
084    this.mode = ProcessingMode.PASS_THROUGH;
085    this.columnSelector = null;
086    this.processorId = null;
087  }
088
089  /**
090   * Factory method for creating a column extraction controller.
091   *
092   * @param columnSelector column name or index to extract
093   * @return configured controller
094   */
095  public static CsvProcessingController forColumnExtraction(String columnSelector) {
096    if (columnSelector == null || columnSelector.trim().isEmpty()) {
097      throw new IllegalArgumentException("Column selector cannot be null or empty");
098    }
099    return new CsvProcessingController(columnSelector.trim());
100  }
101
102  /**
103   * Factory method for creating a complex processing controller.
104   *
105   * @param columnSelector column name or index to extract
106   * @param processorId processor ID for additional processing
107   * @return configured controller
108   */
109  public static CsvProcessingController forComplexProcessing(
110      String columnSelector, String processorId) {
111    if (columnSelector == null || columnSelector.trim().isEmpty()) {
112      throw new IllegalArgumentException("Column selector cannot be null or empty");
113    }
114    if (processorId == null || processorId.trim().isEmpty()) {
115      throw new IllegalArgumentException("Processor ID cannot be null or empty");
116    }
117    return new CsvProcessingController(columnSelector.trim(), processorId.trim());
118  }
119
120  /**
121   * Factory method for creating a pass-through controller.
122   *
123   * @return configured controller that processes CSV without extraction
124   */
125  public static CsvProcessingController forPassThrough() {
126    return new CsvProcessingController();
127  }
128
129  /**
130   * Configures the command pipeline based on the processing mode.
131   *
132   * @return array of command configurations
133   */
134  @Override
135  protected CommandConfig[] configureCommands() {
136    switch (mode) {
137      case COLUMN_EXTRACTION:
138        return new CommandConfig[] {
139          new CommandConfig(
140              CsvNavigateCommand.class, "Extract column: " + columnSelector, columnSelector)
141        };
142
143      case COMPLEX_PROCESSING:
144        return new CommandConfig[] {
145          new CommandConfig(
146              CsvNavigateCommand.class, "Extract column: " + columnSelector, columnSelector),
147          new CommandConfig(SampleStreamCommand.class, "Process with: " + processorId, processorId)
148        };
149
150      case VALIDATION_ONLY:
151        return new CommandConfig[] {
152          new CommandConfig(CsvNavigateCommand.class, "Validate CSV structure")
153        };
154
155      case PASS_THROUGH:
156        return new CommandConfig[] {
157          new CommandConfig(CsvNavigateCommand.class, "Process entire CSV")
158        };
159
160      default:
161        throw new IllegalStateException("Unknown processing mode: " + mode);
162    }
163  }
164
165  @Override
166  public String getInputDataType() {
167    return "CSV";
168  }
169
170  @Override
171  public String getOutputDataType() {
172    switch (mode) {
173      case COLUMN_EXTRACTION:
174        return "CSV_COLUMN";
175      case COMPLEX_PROCESSING:
176        return "PROCESSED_DATA";
177      case VALIDATION_ONLY:
178        return "VALIDATION_RESULT";
179      case PASS_THROUGH:
180        return "CSV";
181      default:
182        return "UNKNOWN";
183    }
184  }
185
186  /**
187   * Gets the processing mode of this controller.
188   *
189   * @return the processing mode
190   */
191  public ProcessingMode getProcessingMode() {
192    return mode;
193  }
194
195  /**
196   * Gets the column selector if applicable.
197   *
198   * @return the column selector, or null if not applicable
199   */
200  public String getColumnSelector() {
201    return columnSelector;
202  }
203
204  /**
205   * Gets the processor ID if applicable.
206   *
207   * @return the processor ID, or null if not applicable
208   */
209  public String getProcessorId() {
210    return processorId;
211  }
212
213  @Override
214  public String getConfigurationDescription() {
215    StringBuilder desc = new StringBuilder(super.getConfigurationDescription());
216    desc.append(" - Mode: ").append(mode);
217
218    if (columnSelector != null) {
219      desc.append(", Column: ").append(columnSelector);
220    }
221
222    if (processorId != null) {
223      desc.append(", Processor: ").append(processorId);
224    }
225
226    return desc.toString();
227  }
228}