package prefuse.data.expression; import java.text.DecimalFormat; import java.text.NumberFormat; import prefuse.data.Edge; import prefuse.data.Node; import prefuse.data.Schema; import prefuse.data.Tuple; import prefuse.util.ColorLib; import prefuse.util.MathLib; import prefuse.util.StringLib; import prefuse.util.collections.CopyOnWriteArrayList; /** * Abstract base class for FunctionExpression implementations. Provides * parameter handling support. * * @author jeffrey heer */ public abstract class FunctionExpression extends AbstractExpression implements Function { protected CopyOnWriteArrayList m_params; protected final int m_pcount; /** * Protected constructor. * @param parameterCount the max parameter count */ protected FunctionExpression(int parameterCount) { m_pcount = parameterCount; } /** * @see prefuse.data.expression.Function#getName() */ public abstract String getName(); /** * @see prefuse.data.expression.Function#addParameter(prefuse.data.expression.Expression) */ public void addParameter(Expression e) { int pc = getParameterCount(); if ( pc!=VARARGS && paramCount()+1 > pc ) { throw new IllegalStateException( "This function takes only "+pc+" parameters."); } if ( m_params == null ) m_params = new CopyOnWriteArrayList(); m_params.add(e); } /** * An internal-only method that returns the current number of * parameters collected. */ protected int paramCount() { return m_params==null ? 0 : m_params.size(); } /** * Return the parameter expression at the given index. * @param idx the parameter index * @return the parameter value Expression at the given index */ protected final Expression param(int idx) { return (Expression)m_params.get(idx); } /** * @see prefuse.data.expression.Function#getParameterCount() */ public int getParameterCount() { return m_pcount; } /** * Throw an exception when needed parameters are missing. */ protected void missingParams() { throw new IllegalStateException( "Function is missing parameters: " + getName()); } // ------------------------------------------------------------------------ /** * @see prefuse.data.expression.Expression#visit(prefuse.data.expression.ExpressionVisitor) */ public void visit(ExpressionVisitor v) { v.visitExpression(this); if ( paramCount() > 0 ) { Object[] params = m_params.getArray(); for ( int i=0; i 0 ) { Object[] params = m_params.getArray(); for ( int i=0; i 0 ) { Object[] params = m_params.getArray(); for ( int i=0; i 0 ) sbuf.append(", "); sbuf.append(param(i).toString()); } sbuf.append(')'); return sbuf.toString(); } } // end of class FunctionExpression /** * Default Function Implementations */ // ---------------------------------------------------------------------------- // Mathematical Functions abstract class DoubleFunction extends FunctionExpression { protected DoubleFunction(int parameterCount) { super(parameterCount); } public Class getType(Schema s) { return double.class; } public Object get(Tuple t) { return new Double(getDouble(t)); } public int getInt(Tuple t) { return (int)getDouble(t); } public long getLong(Tuple t) { return (long)getDouble(t); } public float getFloat(Tuple t) { return (float)getDouble(t); } } abstract class IntFunction extends FunctionExpression { protected IntFunction(int parameterCount) { super(parameterCount); } public Class getType(Schema s) { return int.class; } public Object get(Tuple t) { return new Integer(getInt(t)); } public long getLong(Tuple t) { return (long)getInt(t); } public float getFloat(Tuple t) { return (float)getFloat(t); } public double getDouble(Tuple t) { return (double)getInt(t); } } abstract class BooleanFunction extends FunctionExpression implements Predicate { protected BooleanFunction(int parameterCount) { super(parameterCount); } public Class getType(Schema s) { return boolean.class; } public Object get(Tuple t) { return getBoolean(t) ? Boolean.TRUE : Boolean.FALSE; } } //ROW() class RowFunction extends IntFunction { public RowFunction() { super(0); } public String getName() { return "ROW"; } public int getInt(Tuple t) { return t.getRow(); } } //ISNODE() class IsNodeFunction extends BooleanFunction { public IsNodeFunction() { super(0); } public String getName() { return "ISNODE"; } public boolean getBoolean(Tuple t) { return (t instanceof Node); } } //ISEDGE() class IsEdgeFunction extends BooleanFunction { public IsEdgeFunction() { super(0); } public String getName() { return "ISEDGE"; } public boolean getBoolean(Tuple t) { return (t instanceof Edge); } } //DEGREE() class DegreeFunction extends IntFunction { public DegreeFunction() { super(0); } public String getName() { return "DEGREE"; } public int getInt(Tuple t) { return (t instanceof Node ? ((Node)t).getDegree() : 0 ); } } //INDEGREE() class InDegreeFunction extends IntFunction { public InDegreeFunction() { super(0); } public String getName() { return "INDEGREE"; } public int getInt(Tuple t) { return (t instanceof Node ? ((Node)t).getInDegree() : 0 ); } } //OUTDEGREE() class OutDegreeFunction extends IntFunction { public OutDegreeFunction() { super(0); } public String getName() { return "OUTDEGREE"; } public int getInt(Tuple t) { return (t instanceof Node ? ((Node)t).getOutDegree() : 0 ); } } //CHILDCOUNT() class ChildCountFunction extends IntFunction { public ChildCountFunction() { super(0); } public String getName() { return "CHILDCOUNT"; } public int getInt(Tuple t) { return (t instanceof Node ? ((Node)t).getChildCount() : 0 ); } } //TREEDEPTH() class TreeDepthFunction extends IntFunction { public TreeDepthFunction() { super(0); } public String getName() { return "TREEDEPTH"; } public int getInt(Tuple t) { return (t instanceof Node ? ((Node)t).getDepth() : 0 ); } } //ABS(X) class AbsFunction extends DoubleFunction { public AbsFunction() { super(1); } public String getName() { return "ABS"; } public double getDouble(Tuple t) { if ( paramCount() == 1 ) { return Math.abs(param(0).getDouble(t)); } else { missingParams(); return Double.NaN; } } } //ACOS(X) class AcosFunction extends DoubleFunction { public AcosFunction() { super(1); } public String getName() { return "ACOS"; } public double getDouble(Tuple t) { if ( paramCount() == 1 ) { return Math.acos(param(0).getDouble(t)); } else { missingParams(); return Double.NaN; } } } //ASIN(X) class AsinFunction extends DoubleFunction { public AsinFunction() { super(1); } public String getName() { return "ASIN"; } public double getDouble(Tuple t) { if ( paramCount() == 1 ) { return Math.asin(param(0).getDouble(t)); } else { missingParams(); return Double.NaN; } } } //ATAN(X) class AtanFunction extends DoubleFunction { public AtanFunction() { super(1); } public String getName() { return "ATAN"; } public double getDouble(Tuple t) { if ( paramCount() == 1 ) { return Math.atan(param(0).getDouble(t)); } else { missingParams(); return Double.NaN; } } } //ATAN2(Y,X) class Atan2Function extends DoubleFunction { public Atan2Function() { super(2); } public String getName() { return "ATAN2"; } public double getDouble(Tuple t) { if ( paramCount() == 2 ) { return Math.atan2(param(0).getDouble(t), param(1).getDouble(t)); } else { missingParams(); return Double.NaN; } } } //CEILING(X), CEIL(X) class CeilFunction extends DoubleFunction { public CeilFunction() { super(1); } public String getName() { return "CEIL"; } public double getDouble(Tuple t) { if ( paramCount() == 1 ) { return Math.ceil(param(0).getDouble(t)); } else { missingParams(); return Double.NaN; } } public int getInt(Tuple t) { return (int)getDouble(t); } } //COS(X) class CosFunction extends DoubleFunction { public CosFunction() { super(1); } public String getName() { return "COS"; } public double getDouble(Tuple t) { if ( paramCount() == 1 ) { return Math.cos(param(0).getDouble(t)); } else { missingParams(); return Double.NaN; } } } //COT(X) class CotFunction extends DoubleFunction { public CotFunction() { super(1); } public String getName() { return "COT"; } public double getDouble(Tuple t) { if ( paramCount() == 1 ) { return 1/Math.tan(param(0).getDouble(t)); } else { missingParams(); return Double.NaN; } } } //DEGREES(X) class DegreesFunction extends DoubleFunction { public DegreesFunction() { super(1); } public String getName() { return "DEGREES"; } public double getDouble(Tuple t) { if ( paramCount() == 1 ) { return Math.toDegrees(param(0).getDouble(t)); } else { missingParams(); return Double.NaN; } } } //E() class EFunction extends DoubleFunction { public EFunction() { super(0); } public String getName() { return "E"; } public double getDouble(Tuple t) { return Math.E; } } //EXP(X) class ExpFunction extends DoubleFunction { public ExpFunction() { super(1); } public String getName() { return "EXP"; } public double getDouble(Tuple t) { if ( paramCount() == 1 ) { return Math.exp(param(0).getDouble(t)); } else { missingParams(); return Double.NaN; } } } //FLOOR(X) class FloorFunction extends DoubleFunction { public FloorFunction() { super(1); } public String getName() { return "FLOOR"; } public double getDouble(Tuple t) { if ( paramCount() == 1 ) { return Math.floor(param(0).getDouble(t)); } else { missingParams(); return Double.NaN; } } public int getInt(Tuple t) { return (int)getDouble(t); } } //LOG(X), LOG(B,X) class LogFunction extends DoubleFunction { public LogFunction() { super(2); } public String getName() { return "LOG"; } public double getDouble(Tuple t) { int pc = paramCount(); if ( pc == 2 ) { double b = param(0).getDouble(t); double x = param(1).getDouble(t); return Math.log(x)/Math.log(b); } else if ( pc == 1 ) { return Math.log(param(0).getDouble(t)); } else { missingParams(); return Double.NaN; } } } //LOG2(X) class Log2Function extends DoubleFunction { public Log2Function() { super(1); } public String getName() { return "LOG2"; } public double getDouble(Tuple t) { if ( paramCount() == 1 ) { return MathLib.log2(param(0).getDouble(t)); } else { missingParams(); return Double.NaN; } } } //LOG10(X) class Log10Function extends DoubleFunction { public Log10Function() { super(1); } public String getName() { return "LOG10"; } public double getDouble(Tuple t) { if ( paramCount() == 1 ) { return MathLib.log10(param(0).getDouble(t)); } else { missingParams(); return Double.NaN; } } } //SAFELOG10(X) class SafeLog10Function extends DoubleFunction { public SafeLog10Function() { super(2); } public String getName() { return "SAFELOG10"; } public double getDouble(Tuple t) { int pc = paramCount(); if ( pc == 1 ) { double x = param(0).getDouble(t); return MathLib.safeLog10(x); } else { missingParams(); return Double.NaN; } } } //MAX(X1,X2,...) class MaxFunction extends DoubleFunction { public MaxFunction() { super(Function.VARARGS); } public String getName() { return "MAX"; } public double getDouble(Tuple t) { double x, v = param(0).getDouble(t); for ( int i=1; i v ) v = x; } return v; } } //MIN(X1,X2,...) class MinFunction extends DoubleFunction { public MinFunction() { super(Function.VARARGS); } public String getName() { return "MIN"; } public double getDouble(Tuple t) { double x, v = param(0).getDouble(t); for ( int i=1; i ROUND(X,D) TODO class RoundFunction extends DoubleFunction { public RoundFunction() { super(1); } public String getName() { return "ROUND"; } public double getDouble(Tuple t) { if ( paramCount() == 1 ) { return Math.round(param(0).getDouble(t)); } else { missingParams(); return Double.NaN; } } public int getInt(Tuple t) { return (int)getDouble(t); } } //SIGN(X) class SignFunction extends DoubleFunction { public SignFunction() { super(1); } public String getName() { return "SIGN"; } public Class getType(Schema s) { return int.class; } public double getDouble(Tuple t) { return getInt(t); } public int getInt(Tuple t) { if ( paramCount() == 1 ) { double d = param(0).getDouble(t); return d<0 ? -1 : d==0 ? 0 : 1; } else { missingParams(); return Integer.MIN_VALUE; } } } //SIN(X) class SinFunction extends DoubleFunction { public SinFunction() { super(1); } public String getName() { return "SIN"; } public double getDouble(Tuple t) { if ( paramCount() == 1 ) { return Math.sin(param(0).getDouble(t)); } else { missingParams(); return Double.NaN; } } } //SQRT(X) class SqrtFunction extends DoubleFunction { public SqrtFunction() { super(1); } public String getName() { return "SQRT"; } public double getDouble(Tuple t) { if ( paramCount() == 1 ) { return Math.sqrt(param(0).getDouble(t)); } else { missingParams(); return Double.NaN; } } } //SUM(X1,X2,...) class SumFunction extends DoubleFunction { public SumFunction() { super(Function.VARARGS); } public String getName() { return "SUM"; } public double getDouble(Tuple t) { double v = param(0).getDouble(t); for ( int i=1; i strlen ) return str; if ( len < 0 || len > strlen ) return str.substring(0,pos)+newstr; else return str.substring(0,pos)+newstr+str.substring(len); } } //INSTR(str,substr) //LEFT(str,len) class LeftFunction extends StringFunction { public LeftFunction() { super(2); } public String getName() { return "LEFT"; } public Object get(Tuple t) { String src = param(0).get(t).toString(); int len = param(1).getInt(t); return src.substring(0, len); } } //LENGTH(str) class LengthFunction extends IntFunction { public LengthFunction() { super(1); } public String getName() { return "LENGTH"; } public int getInt(Tuple t) { return param(0).get(t).toString().length(); } } //LOCATE(substr,str), LOCATE(substr,str,pos) //LOWER(str) | LCASE(str) class LowerFunction extends StringFunction { public LowerFunction() { super(1); } public String getName() { return "LOWER"; } public Object get(Tuple t) { return param(0).get(t).toString().toLowerCase(); } } //LPAD(str,len,padstr) class LPadFunction extends StringFunction { public LPadFunction() { super(3); } public String getName() { return "LPAD"; } public Object get(Tuple t) { String str = param(0).get(t).toString(); int len = param(1).getInt(t); String pad = param(2).get(t).toString(); int strlen = str.length(); if ( strlen > len ) { return str.substring(0,len); } else if ( strlen == len ) { return str; } else { StringBuffer sbuf = getBuffer(); int padlen = pad.length(); int diff = len-strlen; for ( int i=0; i diff ) sbuf.delete(diff, sbuf.length()); sbuf.append(str); return sbuf.toString(); } } } //LTRIM(str) //MID(str,pos,len) -- same as substring //POSITION(substr, str) class PositionFunction extends IntFunction { public PositionFunction() { super(2); } public String getName() { return "REPEAT"; } public int getInt(Tuple t) { String substr = param(0).get(t).toString(); String src = param(1).get(t).toString(); return src.indexOf(substr); } } //QUOTE(str) //REPEAT(str,count) class RepeatFunction extends StringFunction { public RepeatFunction() { super(2); } public String getName() { return "REPEAT"; } public Object get(Tuple t) { String src = param(0).get(t).toString(); int count = param(1).getInt(t); StringBuffer sbuf = new StringBuffer(); for ( int i=0; i=0; ) { sbuf.append(str.charAt(i)); } return sbuf.toString(); } } //RIGHT(str,len) class RightFunction extends StringFunction { public RightFunction() { super(2); } public String getName() { return "RIGHT"; } public Object get(Tuple t) { String src = param(0).get(t).toString(); int len = param(1).getInt(t); return src.substring(src.length()-len); } } //RPAD(str,len,padstr) class RPadFunction extends StringFunction { public RPadFunction() { super(3); } public String getName() { return "RPAD"; } public Object get(Tuple t) { String str = param(0).get(t).toString(); int len = param(1).getInt(t); String pad = param(2).get(t).toString(); int strlen = str.length(); if ( strlen > len ) { return str.substring(0,len); } else if ( strlen == len ) { return str; } else { StringBuffer sbuf = getBuffer(); sbuf.append(str); int padlen = pad.length(); int diff = len-strlen; for ( int i=0; i len ) sbuf.delete(len, sbuf.length()); return sbuf.toString(); } } } //RTRIM(str) //// SOUNDEX(str) //SPACE(N) class SpaceFunction extends StringFunction { public SpaceFunction() { super(1); } public String getName() { return "SPACE"; } public Object get(Tuple t) { int n = param(0).getInt(t); StringBuffer sbuf = new StringBuffer(); for ( int i=0; i