package org.egonet.io.wholenet; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import org.egonet.gui.wholenet.NameMapperFrame.NameMapping; import net.sf.functionalj.tuple.Pair; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Multimap; import com.google.common.collect.Sets; import au.com.bytecode.opencsv.CSVReader; public class NameMappingReader { public static class Mapping { // "ego_first","ego_last","alter_number","alter_name","group" public String egoName,alterName; public Integer alterNumber, group; public Mapping(String[] csvColumns) { this(csvColumns[0],csvColumns[1],csvColumns[2],csvColumns[3]); } public Mapping(String egoName, String alterNumber, String alterName, String group) { this.egoName = egoName; this.alterNumber = Integer.parseInt(alterNumber); this.alterName = alterName; this.group = Integer.parseInt(group); } public Mapping(NameMapping mapping) { String name = mapping.getInterview().getIntName(); this.egoName = name; this.alterNumber = mapping.getAlterNumber(); this.alterName = mapping.toString(); this.group = mapping.getGroup(); } public Key key() { return new Key(egoName,alterNumber); } } public static class Key extends Pair<String,Integer> { public Key(String name, Integer alterNumber) { super(name,alterNumber); } public String toString() { return getFirst()+" "+getSecond(); } } public static class Mappings { private List<Mapping> mappings; private Map<Key,Mapping> keyToMapping; private Multimap<Integer,Mapping> groupToMappings; public Mappings() { mappings = Lists.newArrayList(); keyToMapping = Maps.newHashMap(); groupToMappings = ArrayListMultimap.create(); } public void add(Mapping mapping) { mappings.add(mapping); keyToMapping.put(mapping.key(), mapping); groupToMappings.put(mapping.group, mapping); } private void reIndex() { keyToMapping = Maps.newHashMap(); groupToMappings = ArrayListMultimap.create(); for(Mapping mapping : mappings) { keyToMapping.put(mapping.key(), mapping); groupToMappings.put(mapping.group, mapping); } } public Set<Integer> groups() { return groupToMappings.keySet(); } public Collection<Mapping> group(Integer groupIndex) { return groupToMappings.get(groupIndex); } public void breakGroup(Integer groupIndex) { Collection<Mapping> group = group(groupIndex); List<Integer> unusedIndices = Lists.newArrayList(); for(Integer i = 1; unusedIndices.size() < group.size(); i++) { if(i.equals(groupIndex) || ! groups().contains(i)) { unusedIndices.add(i); } } for(Mapping mapping : group) { mapping.group = unusedIndices.remove(0); } reIndex(); } public void combineGroups(Integer... groupIndexes) { if(groupIndexes.length > 1) { for(Integer groupIndex : groupIndexes) { for(Mapping mapping : group(groupIndex)) { mapping.group = groupIndexes[0]; } } reIndex(); } } public Set<Key> keys() { return keyToMapping.keySet(); } public Mapping get(Key key) { return keyToMapping.get(key); } } private Mappings mappings; public NameMappingReader(File mappingFile) throws IOException { FileReader fileReader = new FileReader(mappingFile); CSVReader csv = new CSVReader(fileReader); csv.readNext(); // skip header mappings = new Mappings(); String[] nextLine; while((nextLine = csv.readNext()) != null) { mappings.add(new Mapping(nextLine)); } fileReader.close(); } public void applyTo(List<NameMapping> nameMappings) { Mappings oldMappings = new Mappings(); for(NameMapping nameMapping : nameMappings) { oldMappings.add(new Mapping(nameMapping)); } // Remove incorrect links for(Integer oldGroup : new ArrayList<Integer>(oldMappings.groups())) { Boolean groupShownToBeInvalid = false; for(Mapping oldMapping1 : oldMappings.group(oldGroup)) { Mapping mapping1 = mappings.get(oldMapping1.key()); for(Mapping oldMapping2 : oldMappings.group(oldGroup)) { Mapping mapping2 = mappings.get(oldMapping2.key()); if(mapping1 != null && mapping2 != null && ! mapping1.group.equals(mapping2.group)) { groupShownToBeInvalid = true; } } } if(groupShownToBeInvalid) { oldMappings.breakGroup(oldGroup); } } // Add new links for(Integer group : mappings.groups()) { Set<Integer> matchingOldGroups = Sets.newTreeSet(); for(Mapping mapping : mappings.group(group)) { Mapping oldMapping = oldMappings.get(mapping.key()); if(oldMapping != null) { matchingOldGroups.add(oldMapping.group); } } oldMappings.combineGroups(matchingOldGroups.toArray(new Integer[]{})); } // Apply calculated groupings to original name mappings. for(NameMapping nameMapping : nameMappings) { nameMapping.setGroup( oldMappings.get( new Mapping(nameMapping).key()) .group); } } }