1 package jimm.datavision.field; 2 import jimm.datavision.*; 3 import java.util.*; 4 5 interface AggregateFunction { 6 public double aggregate(double[] values, int numValues); 7 } 8 9 19 public class AggregateField extends Field { 20 21 protected static final int START_VALUES_LENGTH = 100; 22 23 24 protected static HashMap functions; 25 26 protected static Object [] functionNames; 27 28 static { 30 functions = new HashMap(); 31 functions.put("sum", new AggregateFunction() { 32 public double aggregate(double[] values, int numValues) { 33 double total = 0; 34 for (int i = 0; i < numValues; ++i) total += values[i]; 35 return total; 36 } 37 }); 38 functions.put("subtotal", functions.get("sum")); functions.put("min", new AggregateFunction() { 40 public double aggregate(double[] values, int numValues) { 41 double min = Double.MAX_VALUE; 42 for (int i = 0; i < numValues; ++i) 43 if (values[i] < min) min = values[i]; 44 return min; 45 } 46 }); 47 functions.put("max", new AggregateFunction() { 48 public double aggregate(double[] values, int numValues) { 49 double max = Double.MIN_VALUE; 50 for (int i = 0; i < numValues; ++i) 51 if (values[i] > max) max = values[i]; 52 return max; 53 } 54 }); 55 functions.put("count", new AggregateFunction() { 56 public double aggregate(double[] values, int numValues) { 57 return numValues; 58 } 59 }); 60 functions.put("average", new AggregateFunction() { 61 public double aggregate(double[] values, int numValues) { 62 if (numValues == 0) 63 return 0; 64 double total = 0; 65 for (int i = 0; i < numValues; ++i) total += values[i]; 66 return total / numValues; 67 } 68 }); 69 functions.put("stddev", new AggregateFunction() { 70 public double aggregate(double[] values, int numValues) { 71 if (numValues < 2) 72 return 0; 73 double average = ((AggregateFunction)functions.get("average")) 74 .aggregate(values, numValues); 75 double sumOfSquares = 0; 76 for (int i = 0; i < numValues; ++i) 77 sumOfSquares += (values[i] - average) * (values[i] - average); 78 return Math.sqrt(sumOfSquares / (numValues - 1)); 79 } 80 }); 81 82 TreeSet withoutSelect = new TreeSet(functions.keySet()); 85 withoutSelect.remove("select"); 86 functionNames = withoutSelect.toArray(); 87 } 88 89 protected Group group; protected String functionName; 91 protected AggregateFunction function; 92 protected double[] values; protected int valuesIndex; 94 protected Field fieldToAggregate; 95 96 103 public static boolean isAggregateFunctionName(String functionName) { 104 return functions.keySet().contains(functionName); 105 } 106 107 112 public static Object [] functionNameArray() { 113 return functionNames; 114 } 115 116 127 public AggregateField(Long id, Report report, Section section, Object value, 128 boolean visible, String functionName) 129 { 130 super(id, report, section, value, visible); 131 values = null; 132 133 setFunction(functionName); 134 135 } 139 140 protected void finalize() throws Throwable { 141 if (fieldToAggregate != null) 142 fieldToAggregate.deleteObserver(this); 143 super.finalize(); 144 } 145 146 public String getFunction() { return functionName; } 147 public void setFunction(String newFunctionName) { 148 newFunctionName = newFunctionName.toLowerCase(); 149 if (functionName != newFunctionName && 150 (functionName == null || !functionName.equals(newFunctionName))) 151 { 152 functionName = newFunctionName; 153 function = (AggregateFunction)functions.get(functionName); 154 setChanged(); 155 notifyObservers(); 156 } 157 } 158 159 163 public void initialize() { 164 values = null; 165 } 166 167 public String dragString() { 168 return typeString() + ":" + getField().getId(); 169 } 170 171 179 public Group getGroup() { return group; } 180 181 187 public void setGroup(Group newGroup) { 188 if (group != newGroup) { 189 group = newGroup; 190 setChanged(); 191 notifyObservers(); 192 } 193 } 194 195 202 public Field getField() { 203 if (fieldToAggregate == null) { 204 fieldToAggregate = getReport().findField(value); 205 fieldToAggregate.addObserver(this); 206 } 207 return fieldToAggregate; 208 } 209 210 216 public Long getFieldId() { 217 return (value instanceof Long ) ? (Long )value : new Long (value.toString()); 218 } 219 220 225 public double getAggregateValue() { 226 if (function == null) 227 return 0; 228 return function.aggregate(values, valuesIndex); 229 } 230 231 public String typeString() { return functionName; } 232 233 public String designLabel() { 234 return functionName + "(" + getField().designLabel() + ")"; 235 } 236 237 public String formulaString() { return designLabel(); } 238 239 public boolean refersTo(Field f) { 240 return getField() == f; 241 } 242 243 public boolean refersTo(Formula f) { 244 return (getField() instanceof FormulaField) 245 && ((FormulaField)getField()).getFormula() == f; 246 } 247 248 public boolean refersTo(UserColumn uc) { 249 return (getField() instanceof UserColumnField) 250 && ((UserColumnField)getField()).getUserColumn() == uc; 251 } 252 253 public boolean refersTo(Parameter p) { 254 if ((getField() instanceof ParameterField) 255 && ((ParameterField)getField()).getParameter() == p) 256 return true; 257 258 if ((getField() instanceof FormulaField) 259 && ((FormulaField)getField()).refersTo(p)) 260 return true; 261 262 return false; 263 } 264 265 public boolean canBeAggregated() { 266 return true; 267 } 268 269 273 public void updateAggregate() { 274 278 Object obj = getField().getValue(); 279 double value = 0; 280 if (obj != null) { 281 if (obj instanceof Number ) 282 value = ((Number )obj).doubleValue(); 283 else 284 value = Double.parseDouble(obj.toString()); 285 } 286 287 if (values == null || (group != null && group.isNewValue())) { 291 values = new double[START_VALUES_LENGTH]; 292 valuesIndex = 0; 293 } 294 else if (valuesIndex == values.length) { double[] newValues = new double[values.length * 2]; 296 System.arraycopy(values, 0, newValues, 0, values.length); 297 values = newValues; 298 } 299 values[valuesIndex++] = value; 300 } 301 302 307 public Object getValue() { return new Double (getAggregateValue()); } 308 309 } 310 | Popular Tags |