public AnalyticOutPut doAnalysis(AnalyticSource source) throws AnalysisException {
    AnalyticOutPut result = null;
    HadoopPredictorConfig config = (HadoopPredictorConfig) source.getAnalyticConfig();
    try {
      if (config instanceof TimeSeriesHadoopPredictorConfig) {
        ((TimeSeriesHadoopPredictorConfig) config)
            .setHadoopInfo(((HadoopAnalyticSource) source).getHadoopInfo());
        result = doPredict(config);
      } else {
        result = doPredict((HadoopAnalyticSource) source, config);
        super.reportBadDataCount(
            hadoopRunner.getBadCounter(),
            HadoopConstants.Flow_Call_Back_URL,
            getName(),
            getFlowRunUUID());
        if (hadoopRunner.isLocalMode() == true) {
          result.setExtraLogMessage(
              SDKLanguagePack.getMessage(SDKLanguagePack.LOCAL_MODE, config.getLocale()));
        }
      }
      result.setAnalyticNodeMetaInfo(createNodeMetaInfo(config.getLocale()));

    } catch (Exception e) {
      throw new AnalysisException(e);
    }
    return result;
  }
  /* (non-Javadoc)
   * @see com.alpine.datamining.api.impl.visual.ImageVisualizationType#generateOutPut(com.alpine.datamining.api.AnalyticOutPut)
   */
  @Override
  public VisualizationOutPut generateOutPut(AnalyticOutPut analyzerOutPut) {
    AnalyzerOutPutBoxWhisker obj = null;
    if (analyzerOutPut instanceof AnalyzerOutPutBoxWhisker) {
      obj = (AnalyzerOutPutBoxWhisker) analyzerOutPut;
    }
    List<BoxAndWhiskerItem> list = obj.getItemList();
    BoxAndWhiskerDataset dataset = new BoxAndWhiskerDataset();
    String variableName = null;
    String seriesName = null;
    String typeName = null;

    double[] maxArray = new double[list.size()];
    double[] minArray = new double[list.size()];
    // find max and min
    for (int i = 0; i < list.size(); i++) {
      maxArray[i] = list.get(i).getMax().doubleValue();
      minArray[i] = list.get(i).getMin().doubleValue();
    }

    Arrays.sort(maxArray);
    Arrays.sort(minArray);

    double max = maxArray[maxArray.length - 1];
    double min = minArray[0];

    long n = AlpineMath.adjustUnits(min, max);

    for (BoxAndWhiskerItem item : list) {
      dataset.add(
          item.getMean().doubleValue() / n,
          item.getMedian().doubleValue() / n,
          item.getQ1().doubleValue() / n,
          item.getQ3().doubleValue() / n,
          item.getMin().doubleValue() / n,
          item.getMax().doubleValue() / n,
          0,
          0,
          null,
          item.getSeries(),
          item.getType());
    }
    if (list != null && list.size() > 0) {
      variableName = list.get(0).getVariableName();
      if (variableName == null) variableName = "";
      seriesName = list.get(0).getSeriesName();
      if (seriesName == null) seriesName = "";
      typeName = list.get(0).getTypeName();
      if (typeName == null) typeName = "";
    }

    String yLabel =
        n == 1
            ? variableName
            : variableName
                + " "
                + VisualLanguagePack.getMessage(VisualLanguagePack.UNITS, locale)
                + " ("
                + com.alpine.datamining.api.utility.AlpineMath.powExpression(n)
                + ")";

    final CategoryAxis xAxis = new CategoryAxis(typeName);
    xAxis.setLabelFont(VisualResource.getChartFont());
    final NumberAxis yAxis = new NumberAxis(yLabel);
    yAxis.setLabelFont(VisualResource.getChartFont());
    yAxis.setAutoRangeIncludesZero(false);

    final BoxAndWhiskerRenderer renderer = new BoxAndWhiskerRenderer();
    if (list != null && list.size() < 5) {
      renderer.setMaximumBarWidth(0.2);
      renderer.setItemMargin(0.7);
    }

    renderer.setToolTipGenerator(new BoxAndWhiskerToolTipGenerator());
    CategoryPlot plot = new CategoryPlot(dataset, xAxis, yAxis, renderer);

    DrawingSupplier supplier =
        new DefaultDrawingSupplier(
            createPaintArray(),
            DefaultDrawingSupplier.DEFAULT_OUTLINE_PAINT_SEQUENCE,
            DefaultDrawingSupplier.DEFAULT_STROKE_SEQUENCE,
            DefaultDrawingSupplier.DEFAULT_OUTLINE_STROKE_SEQUENCE,
            DefaultDrawingSupplier.DEFAULT_SHAPE_SEQUENCE);
    plot.setDrawingSupplier(supplier);
    plot.setBackgroundPaint(Color.lightGray);
    plot.setRangeGridlinesVisible(true);
    plot.setRangeGridlinePaint(Color.white);

    final JFreeChart chart = new JFreeChart(" ", VisualResource.getChartFont(), plot, true);
    chart.removeLegend();
    if (!seriesName.trim().equals("")) {
      final TextTitle subtitle = new TextTitle(seriesName, VisualResource.getChartFont());
      chart.addSubtitle(subtitle);
      chart.addLegend(new LegendTitle(plot));
      chart.getLegend().setItemFont(VisualResource.getChartFont());
    }
    JFreeChartImageVisualizationOutPut output = new JFreeChartImageVisualizationOutPut(chart);
    output.setName(analyzerOutPut.getAnalyticNode().getName());
    return output;
  }
  @Override
  public VisualizationOutPut generateOutPut(AnalyticOutPut analyzerOutPut) {
    EngineModel emodel = null;
    ARIMAModel model = null;
    if (!(analyzerOutPut instanceof AnalyzerOutPutTrainModel)) return null;

    emodel = (EngineModel) ((AnalyzerOutPutTrainModel) analyzerOutPut).getEngineModel();
    if (emodel == null || !(emodel.getModel() instanceof ARIMAModel)) return null;

    model = (ARIMAModel) emodel.getModel();

    List<TextAndTableListEntity> textAndTableListEntityList =
        new ArrayList<TextAndTableListEntity>();
    List<DataTextAndTableListVisualizationOutPut> textAndTableListOutput =
        new ArrayList<DataTextAndTableListVisualizationOutPut>();

    Map<String, TextAndTableListEntity> nameEntityMap =
        new HashMap<String, TextAndTableListEntity>();

    VisualizationOutPut outputTable = null;

    List<SingleARIMAModel> modelList = model.getModels();
    if (StringUtil.isEmpty(model.getGroupColumnName())) { // no groupBY
      TextTable table = getVTextTable(modelList.get(0));
      TableEntity te = new TableEntity();

      generateTableEntity(table, te);

      TextAndTableListEntity textAndTableListEntity = new TextAndTableListEntity();
      textAndTableListEntity.addTableEntity(te);
      textAndTableListEntity.setText(getVTextText(modelList.get(0)));

      outputTable = new DataTextAndTableListVisualizationOutPut(textAndTableListEntity);
      outputTable.setName(analyzerOutPut.getAnalyticNode().getName());

    } else {
      String[] availableValue = new String[modelList.size()];
      int k = 0;

      for (SingleARIMAModel singleModel : modelList) {
        TextTable table = getVTextTable(singleModel); // default value is the first
        TableEntity te = new TableEntity();

        generateTableEntity(table, te);

        TextAndTableListEntity textAndTableListEntity = new TextAndTableListEntity();
        textAndTableListEntity.addTableEntity(te);
        textAndTableListEntity.setText(getVTextText(singleModel));

        textAndTableListEntityList.add(textAndTableListEntity);
        DataTextAndTableListVisualizationOutPut output =
            new DataTextAndTableListVisualizationOutPut(textAndTableListEntity);
        textAndTableListOutput.add(output);

        availableValue[k] = singleModel.getGroupColumnValue();

        nameEntityMap.put(availableValue[k], textAndTableListEntity);
        k++;
      }

      MultiTextAndTableListEntity tableList = new MultiTextAndTableListEntity();
      tableList.setTextAndTableListEntityList(textAndTableListEntityList);
      tableList.setAvaiableValue(availableValue);
      tableList.setNameEntityMap(nameEntityMap);

      outputTable = new MultiDataTextAndTableListVisualizationOutPut(tableList);
      outputTable.setName(analyzerOutPut.getAnalyticNode().getName());
      ((MultiDataTextAndTableListVisualizationOutPut) outputTable)
          .setTextAndTableListOutput(textAndTableListOutput);
    }
    return outputTable;
  }