1 package autotest.tko; 2 3 import autotest.tko.TkoUtils.FieldInfo; 4 5 import java.util.AbstractCollection; 6 import java.util.ArrayList; 7 import java.util.HashMap; 8 import java.util.Iterator; 9 import java.util.List; 10 import java.util.Map; 11 12 /** 13 * A modifiable, ordered Collection of unique HeaderFields indexed by both field name and field SQL 14 * name. 15 */ 16 public class HeaderFieldCollection extends AbstractCollection<HeaderField> { 17 private Map<String, HeaderField> fieldsByName = new HashMap<String, HeaderField>(); 18 private Map<String, HeaderField> fieldsBySqlName = new HashMap<String, HeaderField>(); 19 private List<HeaderField> orderedFields = new ArrayList<HeaderField>(); 20 populateFromList(String fieldListName)21 public void populateFromList(String fieldListName) { 22 for (FieldInfo fieldInfo : TkoUtils.getFieldList(fieldListName)) { 23 HeaderField field = new SimpleHeaderField(fieldInfo.name, fieldInfo.field); 24 add(field); 25 } 26 } 27 28 @Override add(HeaderField field)29 public boolean add(HeaderField field) { 30 if (contains(field)) { 31 return false; 32 } 33 34 orderedFields.add(field); 35 fieldsByName.put(field.getName(), field); 36 fieldsBySqlName.put(field.getSqlName(), field); 37 assert checkConsistency(); 38 return true; 39 } 40 41 /** 42 * Called only within an assertion. 43 */ checkConsistency()44 public boolean checkConsistency() { 45 assert fieldsByName.size() == fieldsBySqlName.size(); 46 assert fieldsByName.size() == orderedFields.size(); 47 for (HeaderField field : fieldsByName.values()) { 48 assert fieldsByName.get(field.getName()) == field; 49 assert fieldsBySqlName.get(field.getSqlName()) == field; 50 assert orderedFields.contains(field); 51 } 52 return true; 53 } 54 55 /** 56 * We perform strict input checking here, and both add() and remove() use this. 57 */ 58 @Override contains(Object o)59 public boolean contains(Object o) { 60 if (o == null || !(o instanceof HeaderField)) { 61 return false; 62 } 63 64 HeaderField field = (HeaderField) o; 65 boolean containsName = fieldsByName.containsKey(field.getName()); 66 boolean containsSqlName = fieldsBySqlName.containsKey(field.getSqlName()); 67 68 if (containsName && containsSqlName) { 69 return true; 70 } 71 if (!containsName && containsSqlName) { 72 throw new IllegalArgumentException("Duplicate SQL name: " + field + ", " 73 + fieldsBySqlName.get(field.getSqlName())); 74 } 75 if (containsName && !containsSqlName) { 76 throw new IllegalArgumentException("Duplicate name: " + field + ", " 77 + fieldsByName.get(field.getName())); 78 } 79 return false; 80 } 81 82 @Override iterator()83 public Iterator<HeaderField> iterator() { 84 final Iterator<HeaderField> baseIterator = orderedFields.iterator(); 85 return new Iterator<HeaderField>() { 86 HeaderField lastElement; 87 88 @Override 89 public boolean hasNext() { 90 return baseIterator.hasNext(); 91 } 92 93 @Override 94 public HeaderField next() { 95 lastElement = baseIterator.next(); 96 return lastElement; 97 } 98 99 @Override 100 public void remove() { 101 baseIterator.remove(); 102 fieldsByName.remove(lastElement.getName()); 103 fieldsBySqlName.remove(lastElement.getSqlName()); 104 assert checkConsistency(); 105 } 106 }; 107 } 108 109 @Override size()110 public int size() { 111 return fieldsByName.size(); 112 } 113 getFieldByName(String name)114 public HeaderField getFieldByName(String name) { 115 assert fieldsByName.containsKey(name) : name; 116 return fieldsByName.get(name); 117 } 118 getFieldBySqlName(String sqlName)119 public HeaderField getFieldBySqlName(String sqlName) { 120 assert fieldsBySqlName.containsKey(sqlName) : sqlName; 121 return fieldsBySqlName.get(sqlName); 122 } 123 containsName(String name)124 public boolean containsName(String name) { 125 return fieldsByName.containsKey(name); 126 } 127 containsSqlName(String sqlName)128 public boolean containsSqlName(String sqlName) { 129 return fieldsBySqlName.containsKey(sqlName); 130 } 131 132 /** 133 * Note this is O(n). 134 */ 135 @Override remove(Object o)136 public boolean remove(Object o) { 137 if (!contains(o)) { 138 return false; 139 } 140 141 HeaderField field = (HeaderField) o; 142 orderedFields.remove(field); 143 fieldsByName.remove(field.getName()); 144 fieldsBySqlName.remove(field.getSqlName()); 145 return true; 146 } 147 } 148