/** * Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.financial.expression.deprecated; import java.math.BigDecimal; import com.opengamma.core.position.Position; import com.opengamma.core.position.Trade; import com.opengamma.core.security.Security; import com.opengamma.financial.expression.NavigablePortfolioNode; import com.opengamma.financial.expression.UserExpression; /** * AST representation of a user expression. */ /* package */abstract class Expression extends UserExpression { /* package */Expression() { } @SuppressWarnings("unchecked") protected <T> T evaluate(final Class<T> expected, final Expression expr, final Evaluator evaluator) { Object value = expr.evaluate(evaluator); if ((value == NA) || (value == null)) { return null; } if (!expected.isAssignableFrom(value.getClass())) { value = coerceByClass(expected, value); if (!expected.isAssignableFrom(value.getClass())) { throw new ClassCastException("Expected value of type " + expected + " from " + expr + "; got " + value); } } return (T) value; } /** * Coerce a source value to a matching type for the target value. * * @param targetValue value of the type to coerce to * @param sourceValue original value * @return the coerced value or the original value if no coercion is possible */ protected Object coerce(final Object targetValue, final Object sourceValue) { return coerceByClass(targetValue.getClass(), sourceValue); } /** * Coerce a source value to a specific class. * * @param targetClass class to coerce to * @param sourceValue original value * @return the coerced value or the original value if no coercion is possible */ protected Object coerceByClass(final Class<?> targetClass, final Object sourceValue) { if (targetClass == String.class) { return sourceValue.toString(); } else if (targetClass == Integer.class) { if (sourceValue instanceof String) { try { return Integer.parseInt((String) sourceValue); } catch (NumberFormatException e) { // Ignore } } else if (sourceValue instanceof Number) { return ((Number) sourceValue).intValue(); } } else if (targetClass == Double.class) { if (sourceValue instanceof String) { try { return Double.parseDouble((String) sourceValue); } catch (NumberFormatException e) { // Ignore } } else if (sourceValue instanceof Number) { return ((Number) sourceValue).doubleValue(); } } else if (targetClass == BigDecimal.class) { if (sourceValue instanceof String) { return BigDecimal.valueOf(Double.parseDouble((String) sourceValue)); //TODO parse properly } else if (sourceValue instanceof Integer || sourceValue instanceof Long) { return BigDecimal.valueOf(((Number) sourceValue).longValue()); } else if (sourceValue instanceof Double || sourceValue instanceof Float) { return BigDecimal.valueOf(((Number) sourceValue).doubleValue()); } } return sourceValue; } private abstract static class Binary extends Expression { private final Expression _left; private final Expression _right; private Binary(final Expression left, final Expression right) { _left = left; _right = right; } protected Expression getLeft() { return _left; } protected Expression getRight() { return _right; } protected String toString(final String op) { return "`" + op + " (" + getLeft() + ") (" + getRight() + ")"; } } private abstract static class Unary extends Expression { private final Expression _expr; private Unary(final Expression expr) { _expr = expr; } protected Expression getExpr() { return _expr; } protected String toString(final String op) { return "`" + op + " (" + getExpr() + ")"; } } /** * */ public static final class And extends Binary { /* package */And(final Expression left, final Expression right) { super(left, right); } @Override protected Object evaluate(final Evaluator evaluator) { final Boolean leftValue = evaluate(Boolean.class, getLeft(), evaluator); if ((leftValue == null) || !leftValue.booleanValue()) { return false; } final Boolean rightValue = evaluate(Boolean.class, getRight(), evaluator); if (rightValue == null) { return false; } return rightValue; } @Override public String toString() { return toString("AND"); } } /** * */ public static final class Eq extends Binary { /* package */Eq(final Expression left, final Expression right) { super(left, right); } @Override protected Object evaluate(final Evaluator evaluator) { final Object leftValue = getLeft().evaluate(evaluator); if (leftValue == null) { return false; } final Object rightValue = coerce(leftValue, getRight().evaluate(evaluator)); if (rightValue == null) { return false; } return leftValue.equals(rightValue); } @Override public String toString() { return toString("EQ"); } } /** * */ public static final class Gt extends Binary { /* package */Gt(final Expression left, final Expression right) { super(left, right); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override protected Object evaluate(final Evaluator evaluator) { final Comparable leftValue = evaluate(Comparable.class, getLeft(), evaluator); if (leftValue == null) { return false; } final Object rightValue = coerce(leftValue, getRight().evaluate(evaluator)); if (rightValue == null) { return false; } return leftValue.compareTo(rightValue) > 0; } @Override public String toString() { return toString("GT"); } } /** * */ public static final class Gte extends Binary { /* package */Gte(final Expression left, final Expression right) { super(left, right); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override protected Object evaluate(final Evaluator evaluator) { final Comparable leftValue = evaluate(Comparable.class, getLeft(), evaluator); if (leftValue == null) { return false; } final Object rightValue = coerce(leftValue, getRight().evaluate(evaluator)); if (rightValue == null) { return false; } return leftValue.compareTo(rightValue) >= 0; } @Override public String toString() { return toString("GTE"); } } /** * */ public static final class Identifier extends Expression { private final String _text; /* package */Identifier(final String text) { _text = text; } private static Object evaluateSecurityIdentifier(final String identifier, final Security security) { if (security == null) { return null; } if ("Name".equals(identifier)) { return security.getName(); } else if ("Type".equals(identifier)) { return security.getSecurityType(); } return null; } private static Object evaluatePositionAttribute(final String attribute, final Position position) { return position.getAttributes().get(attribute); } private static Object evaluatePositionIdentifier(final String identifier, final Position position) { if (identifier.startsWith("Attribute.")) { return evaluatePositionAttribute(identifier.substring(10), position); } else if ("Quantity".equals(identifier)) { return position.getQuantity(); } return evaluatePositionAttribute(identifier, position); } private static Object evaluateTradeAttribute(final String attribute, final Position position) { for (Trade trade : position.getTrades()) { final String value = trade.getAttributes().get(attribute); if (value != null) { return value; } } return null; } private static Object evaluateTradeIdentifier(final String identifier, final Position position) { if (identifier.startsWith("Attribute.")) { return evaluateTradeAttribute(identifier.substring(10), position); } else if ("Counterparty".equals(identifier)) { for (Trade trade : position.getTrades()) { if (trade.getCounterparty() != null) { return trade.getCounterparty(); } } return null; } else if ("Premium".equals(identifier)) { for (Trade trade : position.getTrades()) { if (trade.getPremium() != null) { return trade.getPremium(); } } return null; } else if ("PremiumCurrency".equals(identifier)) { for (Trade trade : position.getTrades()) { if (trade.getPremiumCurrency() != null) { return trade.getPremiumCurrency(); } } return null; } else if ("PremiumDate".equals(identifier)) { for (Trade trade : position.getTrades()) { if (trade.getPremiumDate() != null) { return trade.getPremiumDate(); } } return null; } else if ("PremiumTime".equals(identifier)) { for (Trade trade : position.getTrades()) { if (trade.getPremiumTime() != null) { return trade.getPremiumTime(); } } return null; } return evaluateTradeAttribute(identifier, position); } private static Object evaluateNodeIdentifier(final String identifier, final NavigablePortfolioNode node) { if ("Depth".equals(identifier)) { return node.getDepth(); } else if ("Name".equals(identifier)) { return node.getName(); } else if (identifier.startsWith("Parent.")) { final NavigablePortfolioNode parent = node.getNavigableParentNode(); if (parent != null) { return evaluateNodeIdentifier(identifier.substring(7), parent); } else { return null; } } else if ("Positions".equals(identifier)) { return node.getPositions().size(); } else if ("Nodes".equals(identifier)) { return node.getChildNodes().size(); } else { return null; } } private static Object evaluatePositionOrTradeIdentifier(final String identifier, final Position position) { Object value; if (identifier.startsWith("Position.")) { return evaluatePositionIdentifier(identifier.substring(9), position); } else if (identifier.startsWith("Security.")) { return evaluateSecurityIdentifier(identifier.substring(9), position.getSecurity()); } else if (identifier.startsWith("Trade.")) { return evaluateTradeIdentifier(identifier.substring(6), position); } value = evaluatePositionIdentifier(identifier, position); if (value != null) { return value; } value = evaluateSecurityIdentifier(identifier, position.getSecurity()); if (value != null) { return value; } return evaluateTradeIdentifier(identifier, position); } private static Object nullForNA(final Object v) { if (v == NA) { return null; } else { return v; } } @Override protected Object evaluate(final Evaluator evaluator) { Position position = (Position) nullForNA(evaluator.getVariable("position")); NavigablePortfolioNode node = (NavigablePortfolioNode) nullForNA(evaluator.getVariable("node")); if ("isNode".equals(_text)) { return (position == null); } else if ("isPosition".equals(_text)) { return (position != null); } else if ((node != null) && _text.startsWith("Node.")) { return evaluateNodeIdentifier(_text.substring(5), node); } else if (position != null) { return evaluatePositionOrTradeIdentifier(_text, position); } else { return evaluateNodeIdentifier(_text, node); } } @Override public String toString() { return "`IDENTIFIER " + _text; } } /** * */ public static final class Literal extends Expression { private final Object _value; /* package */Literal(final Object value) { _value = value; } @Override protected Object evaluate(final Evaluator evaluator) { return _value; } @Override public String toString() { return "`LITERAL " + _value; } } /** * */ public static final class Lt extends Binary { /* package */Lt(final Expression left, final Expression right) { super(left, right); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override protected Object evaluate(final Evaluator evaluator) { final Comparable leftValue = evaluate(Comparable.class, getLeft(), evaluator); if (leftValue == null) { return false; } final Object rightValue = coerce(leftValue, getRight().evaluate(evaluator)); if (rightValue == null) { return false; } return leftValue.compareTo(rightValue) < 0; } @Override public String toString() { return toString("LT"); } } /** * */ public static final class Lte extends Binary { /* package */Lte(final Expression left, final Expression right) { super(left, right); } @SuppressWarnings({"unchecked", "rawtypes" }) @Override protected Object evaluate(final Evaluator evaluator) { final Comparable leftValue = evaluate(Comparable.class, getLeft(), evaluator); if (leftValue == null) { return false; } final Object rightValue = coerce(leftValue, getRight().evaluate(evaluator)); if (rightValue == null) { return false; } return leftValue.compareTo(rightValue) <= 0; } @Override public String toString() { return toString("LTE"); } } /** * */ public static final class Neq extends Binary { /* package */Neq(final Expression left, final Expression right) { super(left, right); } @Override protected Object evaluate(final Evaluator evaluator) { final Object leftValue = getLeft().evaluate(evaluator); if (leftValue == null) { return true; } final Object rightValue = coerce(leftValue, getRight().evaluate(evaluator)); if (rightValue == null) { return true; } return !leftValue.equals(rightValue); } @Override public String toString() { return toString("NEQ"); } } /** * */ public static final class Not extends Unary { /* package */Not(final Expression expr) { super(expr); } @Override protected Object evaluate(final Evaluator evaluator) { final Boolean exprValue = evaluate(Boolean.class, getExpr(), evaluator); if (exprValue == null) { return null; } return !exprValue; } @Override public String toString() { return toString("NOT"); } } /** * */ public static final class Or extends Binary { /* package */Or(final Expression left, final Expression right) { super(left, right); } @Override protected Object evaluate(Evaluator evaluator) { final Boolean leftValue = evaluate(Boolean.class, getLeft(), evaluator); if ((leftValue != null) && leftValue.booleanValue()) { return true; } final Boolean rightValue = evaluate(Boolean.class, getRight(), evaluator); if (rightValue == null) { return false; } return rightValue.booleanValue(); } @Override public String toString() { return toString("OR"); } } }