1 package autotest.tko; 2 3 import autotest.common.Utils; 4 5 import com.google.gwt.json.client.JSONArray; 6 import com.google.gwt.json.client.JSONObject; 7 import com.google.gwt.json.client.JSONString; 8 9 import java.util.ArrayList; 10 import java.util.Collection; 11 import java.util.Collections; 12 import java.util.List; 13 14 public abstract class ParameterizedField extends HeaderField { 15 private static class FieldIdentifier { 16 String type; 17 String value; 18 19 public FieldIdentifier(ParameterizedField field) { 20 this.type = field.getTypeName(); 21 this.value = field.getValue(); 22 } 23 24 @Override 25 public int hashCode() { 26 return type.hashCode() + 31 * value.hashCode(); 27 } 28 29 @Override 30 public boolean equals(Object obj) { 31 if (obj == null || !(obj instanceof FieldIdentifier)) { 32 return false; 33 } 34 35 FieldIdentifier other = (FieldIdentifier) obj; 36 return type.equals(other.type) && value.equals(other.value); 37 } 38 } 39 40 private static final ParameterizedField[] prototypes = new ParameterizedField[] { 41 // add all ParameterizedField subclasses here. these instances should never escape. 42 new MachineLabelField(), 43 new IterationResultField(), 44 new TestAttributeField(), 45 new TestLabelField(), 46 new JobKeyvalField(), 47 new IterationAttributeField(), 48 }; 49 50 private static final List<String> prototypeNames = new ArrayList<String>(); 51 static { 52 for (ParameterizedField prototype : prototypes) { 53 prototypeNames.add(prototype.getTypeName()); 54 } 55 } 56 57 private String value; 58 59 protected ParameterizedField() { 60 super("", ""); 61 } 62 63 public static ParameterizedField newInstance(String typeName, String value) { 64 ParameterizedField prototype = getPrototype(typeName); 65 ParameterizedField newField = prototype.freshInstance(); 66 newField.setValue(value); 67 return newField; 68 } 69 70 public static Collection<String> getFieldTypeNames() { 71 return Collections.unmodifiableCollection(prototypeNames); 72 } 73 74 private static ParameterizedField getPrototype(String name) { 75 for (ParameterizedField prototype : prototypes) { 76 if (name.startsWith(prototype.getTypeName())) { 77 return prototype; 78 } 79 } 80 81 throw new IllegalArgumentException("No prototype found for " + name); 82 } 83 84 @Override 85 public String getSqlName() { 86 return getBaseSqlName() + getValue(); 87 } 88 89 @Override 90 public void addQueryParameters(JSONObject parameters) { 91 JSONArray fieldValueList = 92 Utils.setDefaultValue(parameters, getFieldParameterName(), new JSONArray()).isArray(); 93 fieldValueList.set(fieldValueList.size(), new JSONString(getValue())); 94 } 95 96 /** 97 * @return the prefix of the SQL name generated for each field 98 */ 99 protected abstract String getBaseSqlName(); 100 101 /** 102 * @return name of the parameter to pass with a list of field names for this field type 103 */ 104 protected abstract String getFieldParameterName(); 105 106 /** 107 * @return a string identifying this type of field 108 */ 109 public abstract String getTypeName(); 110 111 /** 112 * @return a new instance of the subclass type. 113 */ 114 protected abstract ParameterizedField freshInstance(); 115 116 @Override 117 public String getName() { 118 return getTypeName() + ": " + getValue(); 119 } 120 121 public String getValue() { 122 return value; 123 } 124 125 public void setValue(String value) { 126 this.value = value; 127 } 128 129 public Object getIdentifier() { 130 return new FieldIdentifier(this); 131 } 132 133 /** 134 * Get the exact field to use in a SQL WHERE clause to filter on this field. 135 * 136 * This is a necessary artifact of the way we directly expose SQL WHERE clauses to the user. It 137 * will hopefully be possible to get rid of this in the future if that changes. 138 */ 139 public abstract String getFilteringName(); 140 } 141