/** * Validates whether the provided {@link Collection} of {@link GroupOperation} is valid. * * @param operations The non-null operations to normalize. * @return An {@link Optional} {@link List} of {@link BulletError} if any operations were invalid or null if valid. */ public static Optional<List<BulletError>> checkOperations(Collection<GroupOperation> operations) { List<BulletError> errors = new ArrayList<>(); for (GroupOperation o : operations) { if (o.getField() == null && o.getType() != GroupOperationType.COUNT) { errors.add(makeError(GROUP_OPERATION_REQUIRES_FIELD + o.getType(), OPERATION_REQUIRES_FIELD_RESOLUTION)); } } return errors.size() > 0 ? Optional.of(errors) : Optional.empty(); }
/** * Creates a {@link Map} of {@link GroupOperation} to their numeric metric values from a {@link Set} of * {@link GroupOperation}. * * @param operations A set of operations. * @return A empty map of metrics that represent these operations. */ public static Map<GroupOperation, Number> makeInitialMetrics(Set<GroupOperation> operations) { Map<GroupOperation, Number> metrics = new HashMap<>(); // Initialize with nulls. for (GroupOperation operation : operations) { metrics.put(operation, null); if (operation.getType() == AVG) { // For AVG we store an addition COUNT_FIELD operation to store the count (the sum is stored in AVG) metrics.put(new GroupOperation(COUNT_FIELD, operation.getField(), null), null); } } return metrics; }
private void consume(Map.Entry<GroupOperation, Number> metric, BulletRecord data) { GroupOperation operation = metric.getKey(); GroupOperation.GroupOperationType type = operation.getType(); Number casted = 1L; switch (type) { case COUNT: break; case MIN: case MAX: case SUM: case AVG: casted = extractFieldAsNumber(operation.getField(), data); break; case COUNT_FIELD: casted = extractFieldAsNumber(operation.getField(), data) ; casted = casted != null ? 1L : null; break; } updateMetric(casted, metric, GroupOperation.OPERATORS.get(type)); }
/** * Returns the name of the result field to use for the given {@link GroupOperation}. If the operation * does specify a newName, it will be returned. Otherwise, a composite name containing the type of the * operation as well as the field name will be used (if provided). * * @param operation The operation to get the name for. * @return a String representing a name for the result of the operation. */ public static String getResultName(GroupOperation operation) { String name = operation.getNewName(); if (name != null) { return name; } GroupOperation.GroupOperationType type = operation.getType(); String field = operation.getField(); if (field == null) { return type.getName(); } return type.getName() + NAME_SEPARATOR + operation.getField(); }
private void addToRecord(Map.Entry<GroupOperation, Number> metric, BulletRecord record) { GroupOperation operation = metric.getKey(); Number value = metric.getValue(); switch (operation.getType()) { case COUNT: record.setLong(getResultName(operation), value == null ? 0 : value.longValue()); break; case AVG: record.setDouble(getResultName(operation), calculateAvg(value, operation.getField())); break; case COUNT_FIELD: // Internal use only for AVG. Not exposed. break; case MIN: case MAX: case SUM: record.setDouble(getResultName(operation), value == null ? null : value.doubleValue()); break; } }