public void validateTypes(final boolean allowColumns, final boolean allowCollections) throws HBqlException {
if (this.needsTypeValidation()) {
if (!allowColumns && this.getColumnsUsedInExpr().size() > 0)
throw new InvalidTypeException("Invalid column reference"
+ (this.getColumnsUsedInExpr().size() > 1 ? "s" : "")
+ " in " + this.asString());
// Collect return types of all args
// This is run even if TypeSignature is null because it calls validateTypes()
final List<Class<? extends GenericValue>> clazzList = Lists.newArrayList();
for (final GenericValue val : this.getExpressionList()) {
final Class<? extends GenericValue> returnType = val.validateTypes(val, allowCollections);
clazzList.add(returnType);
}
// Check against signature if there is one
if (this.getTypeSignature() != null) {
if (this.getExpressionList().size() != this.getTypeSignature().getArgCount())
throw new InvalidTypeException("Incorrect number of variables in " + this.asString());
for (int i = 0; i < this.getTypeSignature().getArgCount(); i++) {
final Class<? extends GenericValue> parentClazz = this.getTypeSignature().getArg(i);
final Class<? extends GenericValue> clazz = clazzList.get(i);
// See if they are both NumberValues. If they are, then check ranks
if (TypeSupport.isParentClass(NumberValue.class, parentClazz, clazz)) {
final int parentRank = NumericType.getTypeRanking(parentClazz);
final int clazzRank = NumericType.getTypeRanking(clazz);
if (clazzRank > parentRank)
throw new InvalidTypeException("Cannot assign a " + clazz.getSimpleName()
+ " value to a " + parentClazz.getSimpleName()
+ " value in " + this.asString());
}
else if (parentClazz == ObjectValue.class) {
// Do nothing
}
else {
if (!parentClazz.isAssignableFrom(clazz))
throw new InvalidTypeException("Expecting type " + parentClazz.getSimpleName()
+ " but found type " + clazz.getSimpleName()
+ " in " + this.asString());
}
}
}