001    package org.hackystat.telemetry.analyzer.function.impl;
002    
003    import org.hackystat.telemetry.analyzer.function.TelemetryFunction;
004    import org.hackystat.telemetry.analyzer.function.TelemetryFunctionException;
005    import org.hackystat.telemetry.analyzer.model.TelemetryStreamCollection;
006    
007    /**
008     * If passed two numbers, returns their division, and if passed two telemetry streams, returns a 
009     * new TelemetryStreamCollection containing the pairwise division of the individual elements. 
010     * 
011     * @author (Cedric) Qin ZHANG
012     */
013    public class DivFunction extends TelemetryFunction {
014    
015      /** Thread-safe div operator. */
016      private DivOperator divOperator = new DivOperator();
017      
018      /**
019       * Constructs this instance.
020       * 
021       */
022      public DivFunction() {
023        super("div");
024      }
025      
026      /**
027       * @param parameters An array of 2 objects of type either <code>Number</code> 
028       *        or <code>TelemetryStreamCollection</code>. 
029       * 
030       * @return Either an instance of <code>Number</code> or <code>TelemetryStreamCollection</code>. 
031       * @throws TelemetryFunctionException If anything is wrong.
032       */
033      @Override
034      public Object compute(Object[] parameters) throws TelemetryFunctionException {
035        //parameter validity check
036        if (parameters.length != 2 
037           || ! (parameters[0] instanceof Number || parameters[0] instanceof TelemetryStreamCollection)
038           || ! (parameters[1] instanceof Number || parameters[1] instanceof TelemetryStreamCollection)
039           ) {
040          throw new TelemetryFunctionException("Telemetry function " + this.getName()
041              + " takes 2 parameters of type 'Number' and/or 'TelemetryStreamCollection'.");
042        }
043        
044        if (parameters[0] instanceof Number && parameters[1] instanceof Number) {
045          return this.divOperator.computes((Number) parameters[0], (Number) parameters[1]);
046        }
047        else {
048          TelemetryStreamCollection tsc0 = (parameters[0] instanceof Number)
049            ? Utility.expandNumber((Number) parameters[0], (TelemetryStreamCollection) parameters[1])
050            : (TelemetryStreamCollection) parameters[0];
051          TelemetryStreamCollection tsc1 = (parameters[1] instanceof Number)
052            ? Utility.expandNumber((Number) parameters[1], (TelemetryStreamCollection) parameters[0])
053            : (TelemetryStreamCollection) parameters[1];
054          return BinaryOperationUtility.computes(this.divOperator, tsc0, tsc1);
055        }
056      }
057      
058      /**
059       * Binary operator used by the enclosing class.
060       * 
061       * @author (Cedric) Qin ZHANG
062       */
063      private static class DivOperator implements BinaryOperationUtility.BinaryOperator {
064        /**
065         * Performs binary operation. 
066         * @param a Number 1.
067         * @param b Number 2.
068         * @return The result.
069         */
070        public Number computes(Number a, Number b) {
071          return Double.valueOf(a.doubleValue() / b.doubleValue());     
072        }
073      }
074    }