All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.univocity.parsers.common.processor.RowProcessorSwitch Maven / Gradle / Ivy

/*
 * Copyright (c) 2015 uniVocity Software Pty Ltd. All rights reserved.
 * This file is subject to the terms and conditions defined in file
 * 'LICENSE.txt', which is part of this source code package.
 *
 */
package com.univocity.parsers.common.processor;

import com.univocity.parsers.common.*;

import java.util.*;
import java.util.Map.*;

/**
 * A special {@link RowProcessor} implementation that combines and allows switching among different
 * RowProcessors. Each RowProcessor will have its own {@link ParsingContext}. Concrete implementations of this class
 * are expected to implement the {@link #switchRowProcessor(String[], ParsingContext)} method and analyze the input row
 * to determine whether or not the current {@link RowProcessor} implementation must be changed to handle a special
 * circumstance (determined by the concrete implementation) such as a different row format.
 *
 * When the row processor is switched, the {@link #rowProcessorSwitched(RowProcessor, RowProcessor)} will be called, and
 * must be overridden, to notify the change to the user.
 */
public abstract class RowProcessorSwitch implements RowProcessor, ColumnOrderDependent {

	private Map rowProcessors;
	private RowProcessor selectedRowProcessor;
	private ParsingContextWrapper contextForProcessor;

	/**
	 * Analyzes the input to determine whether or not the row processor implementation must be changed
	 *
	 * @param row     a row parsed from the input
	 * @param context the current parsing context (not associated with the current row processor used by this class)
	 *
	 * @return the row processor implementation to use. If it is not the same as the one used by the previous row,
	 * the returned row processor will be used, and the {@link #rowProcessorSwitched(RowProcessor, RowProcessor)} method
	 * will be called.
	 */
	protected abstract RowProcessor switchRowProcessor(String[] row, ParsingContext context);

	/**
	 * Returns the headers in use by the current row processor implementation, which can vary among row processors.
	 * If {@code null}, the headers parsed by the input, or defined in {@link CommonParserSettings#getHeaders()} will be returned.
	 *
	 * @return the current sequence of headers to use.
	 */
	public String[] getHeaders() {
		return null;
	}

	/**
	 * Returns the indexes in use by the current row processor implementation, which can vary among row processors.
	 * If {@code null} all columns of a given record will be considered.
	 *
	 * @return the current sequence of indexes to use.
	 */
	public int[] getIndexes() {
		return null;
	}

	/**
	 * Notifies a change of row processor implementation. Users are expected to override this method to receive the notification.
	 *
	 * @param from the row processor previously in use
	 * @param to   the new row processor to use to continue processing the input.
	 */
	public void rowProcessorSwitched(RowProcessor from, RowProcessor to) {
	}

	@Override
	public void processStarted(ParsingContext context) {
		rowProcessors = new HashMap();
		selectedRowProcessor = NoopRowProcessor.instance;
	}

	@Override
	public final void rowProcessed(String[] row, final ParsingContext context) {
		RowProcessor processor = switchRowProcessor(row, context);
		if (processor == null) {
			processor = NoopRowProcessor.instance;
		}
		if (processor != selectedRowProcessor) {
			contextForProcessor = rowProcessors.get(processor);

			if (contextForProcessor == null) {
				contextForProcessor = new ParsingContextWrapper(context) {

					private final String[] fieldNames = getHeaders();
					private final int[] indexes = getIndexes();

					@Override
					public String[] headers() {
						return fieldNames == null || fieldNames.length == 0 ? context.headers() : fieldNames;
					}

					@Override
					public int[] extractedFieldIndexes() {
						return indexes == null || indexes.length == 0 ? context.extractedFieldIndexes() : indexes;
					}
				};

				processor.processStarted(contextForProcessor);
				rowProcessors.put(processor, contextForProcessor);
			}

			if (selectedRowProcessor != NoopRowProcessor.instance) {
				rowProcessorSwitched(selectedRowProcessor, processor);
			}
			selectedRowProcessor = processor;
			if(getIndexes() != null){
				int[] indexes = getIndexes();
				String[] tmp = new String[indexes.length];
				for(int i = 0; i < indexes.length; i++){
					int index = indexes[i];
					if(index < row.length){
						tmp[i] = row[index];
					}
				}
				row = tmp;
			}
			selectedRowProcessor.rowProcessed(row, contextForProcessor);
		} else {
			selectedRowProcessor.rowProcessed(row, contextForProcessor);
		}
	}

	@Override
	public void processEnded(ParsingContext context) {
		rowProcessorSwitched(selectedRowProcessor, null);
		selectedRowProcessor = NoopRowProcessor.instance;
		for (Entry e : rowProcessors.entrySet()) {
			e.getKey().processEnded(e.getValue());
		}
	}

	public boolean preventColumnReordering() {
		return true;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy