// Path: rabbit-core/src/main/java/org/ohdsi/utilities/collections/Pair.java
// public class Pair<A, B> implements Serializable {
// 	
// 	private A					object1;
// 	private B					object2;
// 	private static final long	serialVersionUID	= 1784282381416947673L;
// 	
// 	public Pair(A item1, B item2) {
// 		this.object1 = item1;
// 		this.object2 = item2;
// 	}
// 	
// 	public String toString() {
// 		return "[[" + object1.toString() + "],[" + object2.toString() + "]]";
// 	}
// 	
// 	public int hashCode() {
// 		return object1.hashCode() + object2.hashCode();
// 	}
// 	
// 	public A getItem1() {
// 		return object1;
// 	}
// 	
// 	public B getItem2() {
// 		return object2;
// 	}
// 	
// 	public void setItem1(A item1) {
// 		object1 = item1;
// 	}
// 	
// 	public void setItem2(B item2) {
// 		object2 = item2;
// 	}
// 	
// 	@SuppressWarnings("rawtypes")
// 	public boolean equals(Object other) {
// 		if (other instanceof Pair)
// 			if (((Pair) other).object1.equals(object1))
// 				if (((Pair) other).object2.equals(object2))
// 					return true;
// 		return false;
// 	}
// }


import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.JOptionPane;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVRecord;
import org.ohdsi.utilities.collections.Pair;

			Mapping<Table> mapping = etl.getTableToTableMapping();
			Map<String, Table> nameToTable = new HashMap<>();
			for (CSVRecord row : csvFormat.parse(new InputStreamReader(mappingStream))) {
				String targetTableName = row.get("TARGET_TABLE");
				Table targetTable = nameToTable.get(targetTableName);
				if (targetTable == null) {
					targetTable = targetDatabase.getTableByName(targetTableName);
					mapping.addSourceToTargetMap(sourceStemTable, targetTable);
					nameToTable.put(targetTableName, targetTable);
				}
				Mapping<Field> fieldToFieldMapping = etl.getFieldToFieldMapping(sourceStemTable, targetTable);
				Field sourceField = sourceStemTable.getFieldByName(row.get("SOURCE_FIELD"));
				Field targetField = targetTable.getFieldByName(row.get("TARGET_FIELD"));
				fieldToFieldMapping.addSourceToTargetMap(sourceField, targetField);
			}

		} catch (IOException e) {
			throw new RuntimeException(e.getMessage());
		}

	}

	public static void removeStemTable(ETL etl) {
		// Find stem source and target tables
		Mapping<Table> mapping = etl.getTableToTableMapping();
		List<Pair<Table, Table>> tablesMappingsToRemove = new ArrayList<>();
		for (ItemToItemMap sourceToTargetMap : mapping.getSourceToTargetMaps()) {
			Table sourceTable = (Table) sourceToTargetMap.getSourceItem();
			Table targetTable = (Table) sourceToTargetMap.getTargetItem();
			if (sourceTable.isStem() || targetTable.isStem()) {

// Path: rabbit-core/src/main/java/org/ohdsi/utilities/collections/Pair.java
// public class Pair<A, B> implements Serializable {
// 	
// 	private A					object1;
// 	private B					object2;
// 	private static final long	serialVersionUID	= 1784282381416947673L;
// 	
// 	public Pair(A item1, B item2) {
// 		this.object1 = item1;
// 		this.object2 = item2;
// 	}
// 	
// 	public String toString() {
// 		return "[[" + object1.toString() + "],[" + object2.toString() + "]]";
// 	}
// 	
// 	public int hashCode() {
// 		return object1.hashCode() + object2.hashCode();
// 	}
// 	
// 	public A getItem1() {
// 		return object1;
// 	}
// 	
// 	public B getItem2() {
// 		return object2;
// 	}
// 	
// 	public void setItem1(A item1) {
// 		object1 = item1;
// 	}
// 	
// 	public void setItem2(B item2) {
// 		object2 = item2;
// 	}
// 	
// 	@SuppressWarnings("rawtypes")
// 	public boolean equals(Object other) {
// 		if (other instanceof Pair)
// 			if (((Pair) other).object1.equals(object1))
// 				if (((Pair) other).object2.equals(object2))
// 					return true;
// 		return false;
// 	}
// }


// Path: rabbitinahat/src/main/java/org/ohdsi/rabbitInAHat/dataModel/StemTableFactory.java
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.JOptionPane;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVRecord;
import org.ohdsi.utilities.collections.Pair;

			Mapping<Table> mapping = etl.getTableToTableMapping();
			Map<String, Table> nameToTable = new HashMap<>();
			for (CSVRecord row : csvFormat.parse(new InputStreamReader(mappingStream))) {
				String targetTableName = row.get("TARGET_TABLE");
				Table targetTable = nameToTable.get(targetTableName);
				if (targetTable == null) {
					targetTable = targetDatabase.getTableByName(targetTableName);
					mapping.addSourceToTargetMap(sourceStemTable, targetTable);
					nameToTable.put(targetTableName, targetTable);
				}
				Mapping<Field> fieldToFieldMapping = etl.getFieldToFieldMapping(sourceStemTable, targetTable);
				Field sourceField = sourceStemTable.getFieldByName(row.get("SOURCE_FIELD"));
				Field targetField = targetTable.getFieldByName(row.get("TARGET_FIELD"));
				fieldToFieldMapping.addSourceToTargetMap(sourceField, targetField);
			}

		} catch (IOException e) {
			throw new RuntimeException(e.getMessage());
		}

	}

	public static void removeStemTable(ETL etl) {
		// Find stem source and target tables
		Mapping<Table> mapping = etl.getTableToTableMapping();
		List<Pair<Table, Table>> tablesMappingsToRemove = new ArrayList<>();
		for (ItemToItemMap sourceToTargetMap : mapping.getSourceToTargetMaps()) {
			Table sourceTable = (Table) sourceToTargetMap.getSourceItem();
			Table targetTable = (Table) sourceToTargetMap.getTargetItem();
			if (sourceTable.isStem() || targetTable.isStem()) {

				tablesMappingsToRemove.add(new Pair<>(sourceTable, targetTable));
