| package autotest.tko; |
| |
| import autotest.tko.TkoUtils.FieldInfo; |
| |
| import java.util.AbstractCollection; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| /** |
| * A modifiable, ordered Collection of unique HeaderFields indexed by both field name and field SQL |
| * name. |
| */ |
| public class HeaderFieldCollection extends AbstractCollection<HeaderField> { |
| private Map<String, HeaderField> fieldsByName = new HashMap<String, HeaderField>(); |
| private Map<String, HeaderField> fieldsBySqlName = new HashMap<String, HeaderField>(); |
| private List<HeaderField> orderedFields = new ArrayList<HeaderField>(); |
| |
| public void populateFromList(String fieldListName) { |
| for (FieldInfo fieldInfo : TkoUtils.getFieldList(fieldListName)) { |
| HeaderField field = new SimpleHeaderField(fieldInfo.name, fieldInfo.field); |
| add(field); |
| } |
| } |
| |
| @Override |
| public boolean add(HeaderField field) { |
| if (contains(field)) { |
| return false; |
| } |
| |
| orderedFields.add(field); |
| fieldsByName.put(field.getName(), field); |
| fieldsBySqlName.put(field.getSqlName(), field); |
| assert checkConsistency(); |
| return true; |
| } |
| |
| /** |
| * Called only within an assertion. |
| */ |
| public boolean checkConsistency() { |
| assert fieldsByName.size() == fieldsBySqlName.size(); |
| assert fieldsByName.size() == orderedFields.size(); |
| for (HeaderField field : fieldsByName.values()) { |
| assert fieldsByName.get(field.getName()) == field; |
| assert fieldsBySqlName.get(field.getSqlName()) == field; |
| assert orderedFields.contains(field); |
| } |
| return true; |
| } |
| |
| /** |
| * We perform strict input checking here, and both add() and remove() use this. |
| */ |
| @Override |
| public boolean contains(Object o) { |
| if (o == null || !(o instanceof HeaderField)) { |
| return false; |
| } |
| |
| HeaderField field = (HeaderField) o; |
| boolean containsName = fieldsByName.containsKey(field.getName()); |
| boolean containsSqlName = fieldsBySqlName.containsKey(field.getSqlName()); |
| |
| if (containsName && containsSqlName) { |
| return true; |
| } |
| if (!containsName && containsSqlName) { |
| throw new IllegalArgumentException("Duplicate SQL name: " + field + ", " |
| + fieldsBySqlName.get(field.getSqlName())); |
| } |
| if (containsName && !containsSqlName) { |
| throw new IllegalArgumentException("Duplicate name: " + field + ", " |
| + fieldsByName.get(field.getName())); |
| } |
| return false; |
| } |
| |
| @Override |
| public Iterator<HeaderField> iterator() { |
| final Iterator<HeaderField> baseIterator = orderedFields.iterator(); |
| return new Iterator<HeaderField>() { |
| HeaderField lastElement; |
| |
| @Override |
| public boolean hasNext() { |
| return baseIterator.hasNext(); |
| } |
| |
| @Override |
| public HeaderField next() { |
| lastElement = baseIterator.next(); |
| return lastElement; |
| } |
| |
| @Override |
| public void remove() { |
| baseIterator.remove(); |
| fieldsByName.remove(lastElement.getName()); |
| fieldsBySqlName.remove(lastElement.getSqlName()); |
| assert checkConsistency(); |
| } |
| }; |
| } |
| |
| @Override |
| public int size() { |
| return fieldsByName.size(); |
| } |
| |
| public HeaderField getFieldByName(String name) { |
| assert fieldsByName.containsKey(name) : name; |
| return fieldsByName.get(name); |
| } |
| |
| public HeaderField getFieldBySqlName(String sqlName) { |
| assert fieldsBySqlName.containsKey(sqlName) : sqlName; |
| return fieldsBySqlName.get(sqlName); |
| } |
| |
| public boolean containsName(String name) { |
| return fieldsByName.containsKey(name); |
| } |
| |
| public boolean containsSqlName(String sqlName) { |
| return fieldsBySqlName.containsKey(sqlName); |
| } |
| |
| /** |
| * Note this is O(n). |
| */ |
| @Override |
| public boolean remove(Object o) { |
| if (!contains(o)) { |
| return false; |
| } |
| |
| HeaderField field = (HeaderField) o; |
| orderedFields.remove(field); |
| fieldsByName.remove(field.getName()); |
| fieldsBySqlName.remove(field.getSqlName()); |
| return true; |
| } |
| } |