001    package org.hackystat.telemetry.analyzer.language.ast;
002    
003    import org.hackystat.telemetry.analyzer.language.TelemetryLanguageException;
004    
005    /**
006     * Y-axis information in telemetry chart definition.
007     * 
008     * @author (Cedric) Qin Zhang
009     */
010    public class TelemetryChartYAxisDefinition extends TelemetryDefinition {
011    
012      /** Chart y-axis should have integer numbers. */
013      public static final String NUMBER_TYPE_INTEGER = "integer";
014      /** Chart y-axis should have double number. */
015      public static final String NUMBER_TYPE_DOUBLE = "double";
016      /** Chart y-axis have auto-determined number type, either integer or double. */
017      public static final String NUMBER_TYPE_AUTO = "auto";
018      
019      private Variable[] variables; //List<Variable>
020      
021      private Expression labelParameter; //Variable or StringConstant
022      private String numberType;
023      private boolean autoScaled;
024      private Number lowerBound, upperBound;
025        
026      /**
027       * Constructs the y-axis definition. Y-axis can be either auto-scaled or fixed-scaled,
028       * depending on whether lower bound and upper bounds are supplied or not.
029       * 
030       * @param name The name of this y-axis definition.
031       * @param variables The variables used in the definition. Variables are essentially holding
032       *        places so that real value can be swapped in later.
033       *        Null is valid if there is no variable used in this definition.
034       * @param labelParameter Either a <code>Variable</code> or a <code>StringConstant</code> for
035       *        y-axis label.
036       * @param numberType The axis number type. Use one of the constants in this class.
037       * @param lowerBound Y-axis lower bound. Null is valid i
038       * @param upperBound Y-axis upper bound.
039       * @param textPosition The text position of the definition string in the input.
040       * 
041       * @throws TelemetryLanguageException If y-axis number type is unsupported, 
042       *         or supplied lower and upper bounds are invalid.
043       */
044      public TelemetryChartYAxisDefinition(String name, Variable[] variables, Expression labelParameter,
045          String numberType, Number lowerBound, Number upperBound, TextPosition textPosition) 
046          throws TelemetryLanguageException {
047        super(name, textPosition);
048        this.variables = variables == null ? new Variable[0] : variables;
049        
050        //check label parameter
051        if (labelParameter instanceof Variable || labelParameter instanceof StringConstant) {
052          this.labelParameter = labelParameter;
053        }
054        else {
055          throw new TelemetryLanguageException("labelParameter must be of type either Variable " +
056              "or StringConstant.");
057        }
058        
059        //check number type
060        if (NUMBER_TYPE_INTEGER.equals(numberType) || NUMBER_TYPE_DOUBLE.equals(numberType)
061            || NUMBER_TYPE_AUTO.equals(numberType)) {
062          this.numberType = numberType;
063        }
064        else {
065          throw new TelemetryLanguageException("Y-Axis number type must be one of integer|double|auto");
066        }
067    
068        //check bounds
069        if (lowerBound == null && upperBound == null) {
070          this.autoScaled = true;
071          this.lowerBound = null;
072          this.upperBound = null;
073        }
074        else if (lowerBound != null && upperBound != null) {
075          if (NUMBER_TYPE_INTEGER.equals(numberType) && 
076              ! (lowerBound instanceof Integer && upperBound instanceof Integer)) {
077            throw new TelemetryLanguageException("Upper and lower bound for integer y-axis must be" +
078                "integers.");
079          }
080          if (lowerBound.floatValue() >= upperBound.floatValue()) {
081            throw new TelemetryLanguageException(
082                "Y-Axis lower bound must be smaller than its upper bound.");
083          }
084          this.autoScaled = false;
085          this.lowerBound = lowerBound;
086          this.upperBound = upperBound;
087        }
088        else {
089          throw new TelemetryLanguageException("You must specify both lower and upper bounds, " +
090              "or none of them.");
091        }
092      }
093      
094      /**
095       * Gets an array of variables used in the definition.
096       * 
097       * @return An array of <code>Varaible</code> objects. If there is no variable used,
098       *         then an empty array is returned.
099       */
100      public Variable[] getVariables() {
101        return this.variables;
102      }
103      
104      /**
105       * Gets the y-axis label.
106       * 
107       * @return Either a <code>Variable</code> or a <code>StringConstant</code> for y-axis label.
108       */
109      public Expression getLabelParameter() {
110        return this.labelParameter;
111      }
112      
113      /**
114       * Gets the y-axis number type. The return value is one of the number type constant defined
115       * in this class.
116       * 
117       * @return Y-axis number type.
118       */
119      public String getNumberType() {
120        return this.numberType;
121      }
122      
123      /**
124       * Determines whether the y-axis is auto-scales.
125       * 
126       * @return True if y-axis is auto-scaled.
127       */
128      public boolean isAutoScale() {
129        return this.autoScaled;
130      }
131      
132      /**
133       * Gets the lower bound of the axis.
134       * 
135       * @return The lower bound of the axis, or null if the axis is auto-scaled.
136       */
137      public Number getLowerBound() {
138        return this.lowerBound;
139      }
140      
141      /**
142       * Gets the upper bound of the axis.
143       * 
144       * @return The upper bound of the axis, or null if the axis is auto-scaled.
145       */
146      public Number getUpperBound() {
147        return this.upperBound;
148      }
149    }