/************************************************************************************** * Copyright (C) 2008 EsperTech, Inc. All rights reserved. * * http://esper.codehaus.org * * http://www.espertech.com * * ---------------------------------------------------------------------------------- * * The software in this package is published under the terms of the GPL license * * a copy of which has been included with this distribution in the license.txt file. * **************************************************************************************/ package com.espertech.esper.epl.expression; import com.espertech.esper.client.EventBean; import com.espertech.esper.util.*; import java.math.BigDecimal; import java.math.BigInteger; import java.util.Map; /** * Represents the CAST(expression, type) function is an expression tree. */ public class ExprCastNode extends ExprNodeBase implements ExprEvaluator { private final String classIdentifier; private Class targetType; private transient CasterParserComputer casterParserComputer; private transient ExprEvaluator evaluator; private static final long serialVersionUID = 7448449031028156455L; /** * Ctor. * @param classIdentifier the the name of the type to cast to */ public ExprCastNode(String classIdentifier) { this.classIdentifier = classIdentifier; } public ExprEvaluator getExprEvaluator() { return this; } /** * Returns the name of the type of cast to. * @return type name */ public String getClassIdentifier() { return classIdentifier; } public Map<String, Object> getEventType() { return null; } public void validate(ExprValidationContext validationContext) throws ExprValidationException { if (this.getChildNodes().size() != 1) { throw new ExprValidationException("Cast function node must have exactly 1 child node"); } evaluator = this.getChildNodes().get(0).getExprEvaluator(); Class fromType = evaluator.getType(); // identify target type // try the primitive names including "string" SimpleTypeCaster caster; targetType = JavaClassHelper.getPrimitiveClassForName(classIdentifier.trim()); boolean numeric; if (targetType != null) { targetType = JavaClassHelper.getBoxedType(targetType); caster = SimpleTypeCasterFactory.getCaster(fromType, targetType); numeric = caster.isNumericCast(); } else if (classIdentifier.trim().toLowerCase().equals("BigInteger".toLowerCase())) { targetType = BigInteger.class; caster = SimpleTypeCasterFactory.getCaster(fromType, targetType); numeric = true; } else if (classIdentifier.trim().toLowerCase().equals("BigDecimal".toLowerCase())) { targetType = BigDecimal.class; caster = SimpleTypeCasterFactory.getCaster(fromType, targetType); numeric = true; } else { try { targetType = JavaClassHelper.getClassForName(classIdentifier.trim()); } catch (ClassNotFoundException e) { throw new ExprValidationException("Class as listed in cast function by name '" + classIdentifier + "' cannot be loaded", e); } numeric = JavaClassHelper.isNumeric(targetType); if (numeric) { caster = SimpleTypeCasterFactory.getCaster(fromType, targetType); } else { caster = new SimpleTypeCasterAnyType(targetType); } } // to-string if (targetType == String.class) { casterParserComputer = new StringXFormComputer(); } // parse else if (fromType == String.class) { SimpleTypeParser parser = SimpleTypeParserFactory.getParser(JavaClassHelper.getBoxedType(targetType)); casterParserComputer = new StringParserComputer(parser); } // numeric cast with check else if (numeric) { casterParserComputer = new NumberCasterComputer(caster); } // non-numeric cast else { casterParserComputer = new NonnumericCasterComputer(caster); } } public boolean isConstantResult() { return false; } public Class getType() { return targetType; } public Object evaluate(EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { Object result = evaluator.evaluate(eventsPerStream, isNewData, exprEvaluatorContext); if (result == null) { return null; } return casterParserComputer.compute(result); } public String toExpressionString() { StringBuilder buffer = new StringBuilder(); buffer.append("cast("); buffer.append(this.getChildNodes().get(0).toExpressionString()); buffer.append(", "); buffer.append(classIdentifier); buffer.append(')'); return buffer.toString(); } public boolean equalsNode(ExprNode node) { if (!(node instanceof ExprCastNode)) { return false; } ExprCastNode other = (ExprCastNode) node; if (other.classIdentifier.equals(this.classIdentifier)) { return true; } return false; } /** * Casting and parsing computer. */ public interface CasterParserComputer { /** * Compute an result performing casting and parsing. * @param input to process * @return cast or parse result */ public Object compute(Object input); } /** * Casting and parsing computer. */ public static class StringXFormComputer implements CasterParserComputer { public Object compute(Object input) { return input.toString(); } } /** * Casting and parsing computer. */ public static class NumberCasterComputer implements CasterParserComputer { private final SimpleTypeCaster numericTypeCaster; /** * Ctor. * @param numericTypeCaster caster */ public NumberCasterComputer(SimpleTypeCaster numericTypeCaster) { this.numericTypeCaster = numericTypeCaster; } public Object compute(Object input) { if (input instanceof Number) { return numericTypeCaster.cast(input); } return null; } } /** * Casting and parsing computer. */ public static class StringParserComputer implements CasterParserComputer { private final SimpleTypeParser parser; /** * Ctor. * @param parser parser */ public StringParserComputer(SimpleTypeParser parser) { this.parser = parser; } public Object compute(Object input) { return parser.parse(input.toString()); } } /** * Casting and parsing computer. */ public static class NonnumericCasterComputer implements CasterParserComputer { private final SimpleTypeCaster caster; /** * Ctor. * @param numericTypeCaster caster */ public NonnumericCasterComputer(SimpleTypeCaster numericTypeCaster) { this.caster = numericTypeCaster; } public Object compute(Object input) { return caster.cast(input); } } }