@Override public void addToBucket(Object arg, Bucket<Integer> bucket, Type type) { assert type.equals(Type.getPrimitive(Type.TypeName.INT)); if (null != arg) { Integer state = getState(bucket); int val = 0; if (null != state) { val = state.intValue(); } val++; // Non-null item in bucket increments state. bucket.setState(Integer.valueOf(val)); } }
@Override public Type getType(SymbolTable symTab) { // Get the types of the lhs and rhs, and then verify that one promotes to the other. mLhsType = mLeftExpr.getType(symTab); mRhsType = mRightExpr.getType(symTab); Type sharedType = null; if (mLhsType.promotesTo(mRhsType)) { sharedType = mRhsType; } else if (mRhsType.promotesTo(mLhsType)) { sharedType = mLhsType; } // Save this for later. mArgType = sharedType; switch (mOp) { case Times: case Div: case Mod: case Add: case Subtract: // Numeric operators return their input type. return sharedType; case Greater: case GreaterEq: case Less: case LessEq: case Eq: case NotEq: case And: case Or: return Type.getPrimitive(Type.TypeName.BOOLEAN); default: // Couldn't reconcile any type. LOG.error("Unknown operator " + mOp + " in getType()"); return null; } }
@Override public Object eval(EventWrapper e) throws IOException { Object lhs = mLeftExpr.eval(e); Object rhs = mRightExpr.eval(e); if (null == lhs || null == rhs) { // NULL op X always returns null. return null; } if (!mLhsType.equals(mArgType)) { lhs = coerce(lhs, mLhsType, mArgType); } if (!mRhsType.equals(mArgType)) { rhs = coerce(rhs, mRhsType, mArgType); } switch (mOp) { case Times: switch (mArgType.getPrimitiveTypeName()) { case INT: return Integer.valueOf(((Number) lhs).intValue() * ((Number) rhs).intValue()); case BIGINT: return Long.valueOf(((Number) lhs).longValue() * ((Number) rhs).longValue()); case FLOAT: return Float.valueOf(((Number) lhs).floatValue() * ((Number) rhs).floatValue()); case DOUBLE: return Double.valueOf(((Number) lhs).doubleValue() * ((Number) rhs).doubleValue()); case PRECISE: return ((BigDecimal) lhs).multiply((BigDecimal) rhs); default: LOG.error("Cannot multiply with non-number type " + mArgType); return null; } case Div: switch (mArgType.getPrimitiveTypeName()) { case INT: return Integer.valueOf(((Number) lhs).intValue() / ((Number) rhs).intValue()); case BIGINT: return Long.valueOf(((Number) lhs).longValue() / ((Number) rhs).longValue()); case FLOAT: return Float.valueOf(((Number) lhs).floatValue() / ((Number) rhs).floatValue()); case DOUBLE: return Double.valueOf(((Number) lhs).doubleValue() / ((Number) rhs).doubleValue()); case PRECISE: return ((BigDecimal) lhs).divide((BigDecimal) rhs); default: LOG.error("Cannot divide with non-number type " + mArgType); return null; } case Mod: switch (mArgType.getPrimitiveTypeName()) { case INT: return Integer.valueOf(((Number) lhs).intValue() % ((Number) rhs).intValue()); case BIGINT: return Long.valueOf(((Number) lhs).longValue() % ((Number) rhs).longValue()); case FLOAT: return Float.valueOf(((Number) lhs).floatValue() % ((Number) rhs).floatValue()); case DOUBLE: return Double.valueOf(((Number) lhs).doubleValue() % ((Number) rhs).doubleValue()); case PRECISE: return ((BigDecimal) lhs).remainder((BigDecimal) rhs); default: LOG.error("Cannot divide with non-number type " + mArgType); return null; } case Add: switch (mArgType.getPrimitiveTypeName()) { case INT: return Integer.valueOf(((Number) lhs).intValue() + ((Number) rhs).intValue()); case BIGINT: return Long.valueOf(((Number) lhs).longValue() + ((Number) rhs).longValue()); case FLOAT: return Float.valueOf(((Number) lhs).floatValue() + ((Number) rhs).floatValue()); case DOUBLE: return Double.valueOf(((Number) lhs).doubleValue() + ((Number) rhs).doubleValue()); case PRECISE: return ((BigDecimal) lhs).add((BigDecimal) rhs); case STRING: // String concatenation. StringBuilder sb = new StringBuilder(); sb.append(lhs); sb.append(rhs); return sb.toString(); default: LOG.error("Cannot divide with non-number type " + mArgType); return null; } case Subtract: switch (mArgType.getPrimitiveTypeName()) { case INT: return Integer.valueOf(((Number) lhs).intValue() - ((Number) rhs).intValue()); case BIGINT: return Long.valueOf(((Number) lhs).longValue() - ((Number) rhs).longValue()); case FLOAT: return Float.valueOf(((Number) lhs).floatValue() - ((Number) rhs).floatValue()); case DOUBLE: return Double.valueOf(((Number) lhs).doubleValue() - ((Number) rhs).doubleValue()); case PRECISE: return ((BigDecimal) lhs).subtract((BigDecimal) rhs); default: LOG.error("Cannot divide with non-number type " + mArgType); return null; } case Greater: return Boolean.valueOf(((Comparable) lhs).compareTo(rhs) > 0); case GreaterEq: return Boolean.valueOf(((Comparable) lhs).compareTo(rhs) >= 0); case Less: return Boolean.valueOf(((Comparable) lhs).compareTo(rhs) < 0); case LessEq: return Boolean.valueOf(((Comparable) lhs).compareTo(rhs) <= 0); case Eq: return Boolean.valueOf(lhs.equals(rhs)); case NotEq: return Boolean.valueOf(!lhs.equals(rhs)); case And: return Boolean.valueOf(((Boolean) lhs).booleanValue() && ((Boolean) rhs).booleanValue()); case Or: return Boolean.valueOf(((Boolean) lhs).booleanValue() || ((Boolean) rhs).booleanValue()); default: // Couldn't evaluate this operator. throw new RuntimeException("Unknown operator " + mOp + " in eval"); } }
@Override public Type getReturnType() { return Type.getPrimitive(Type.TypeName.INT); }
public count() { // Argument may have any input type. mArgType = new UniversalType("'a"); mArgType.addConstraint(Type.getNullable(Type.TypeName.TYPECLASS_ANY)); }