/**
  * Constructs a Persian calendar with the default time zone and locale and sets its time to the
  * specified date.
  *
  * @param year the Persian year.
  * @param month the Persian month (zero-based).
  * @param date the Persian day of month.
  */
 public PersianCalendar(int year, int month, int date) {
   super(TimeZone.getDefault(), ULocale.getDefault());
   set(ERA, AH);
   set(YEAR, year);
   set(MONTH, month);
   set(DATE, date);
 }
 /**
  * Constructs a <code>PersianCalendar</code> with the given date set in the default time zone with
  * the default <code>FORMAT</code> locale.
  *
  * @param year the value used to set the {@link #YEAR YEAR} time field in the calendar.
  * @param month the value used to set the {@link #MONTH MONTH} time field in the calendar. Note
  *     that the month value is 0-based. e.g., 0 for Farvardin.
  * @param date the value used to set the {@link #DATE DATE} time field in the calendar.
  * @see Category#FORMAT
  * @internal
  * @deprecated This API is ICU internal only.
  */
 @Deprecated
 public PersianCalendar(int year, int month, int date) {
   super(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT));
   this.set(Calendar.YEAR, year);
   this.set(Calendar.MONTH, month);
   this.set(Calendar.DATE, date);
 }
 @LayoutlibDelegate
 /*package*/ static long createDateIntervalFormat(
     String skeleton, String localeName, String tzName) {
   TimeZone prevDefaultTz = TimeZone.getDefault();
   TimeZone.setDefault(TimeZone.getTimeZone(tzName));
   DateIntervalFormat_Delegate newDelegate = new DateIntervalFormat_Delegate();
   newDelegate.mFormat = DateIntervalFormat.getInstance(skeleton, new ULocale(localeName));
   TimeZone.setDefault(prevDefaultTz);
   return sManager.addNewDelegate(newDelegate);
 }
 /**
  * Constructs a Persian calendar with the default time zone and locale and sets its time to the
  * specified time.
  *
  * @param year the Persian year.
  * @param month the Persian month (zero-based).
  * @param date the Persian day of month.
  * @param hour the hours part of time.
  * @param minute the minutes part of time.
  * @param second the seconds part of time.
  */
 public PersianCalendar(int year, int month, int date, int hour, int minute, int second) {
   super(TimeZone.getDefault(), ULocale.getDefault());
   set(ERA, AH);
   set(YEAR, year);
   set(MONTH, month);
   set(DATE, date);
   set(HOUR_OF_DAY, hour);
   set(MINUTE, minute);
   set(SECOND, second);
 }
 /**
  * Constructs a <code>PersianCalendar</code> with the given date and time set for the default time
  * zone with the default <code>FORMAT</code> locale.
  *
  * @param year the value used to set the {@link #YEAR YEAR} time field in the calendar.
  * @param month the value used to set the {@link #MONTH MONTH} time field in the calendar. Note
  *     that the month value is 0-based. e.g., 0 for Farvardin.
  * @param date the value used to set the {@link #DATE DATE} time field in the calendar.
  * @param hour the value used to set the {@link #HOUR_OF_DAY HOUR_OF_DAY} time field in the
  *     calendar.
  * @param minute the value used to set the {@link #MINUTE MINUTE} time field in the calendar.
  * @param second the value used to set the {@link #SECOND SECOND} time field in the calendar.
  * @see Category#FORMAT
  * @internal
  * @deprecated This API is ICU internal only.
  */
 @Deprecated
 public PersianCalendar(int year, int month, int date, int hour, int minute, int second) {
   super(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT));
   this.set(Calendar.YEAR, year);
   this.set(Calendar.MONTH, month);
   this.set(Calendar.DATE, date);
   this.set(Calendar.HOUR_OF_DAY, hour);
   this.set(Calendar.MINUTE, minute);
   this.set(Calendar.SECOND, second);
 }
  private String generateDataTableJson(TimeChartData chartData) throws DataSourceException {
    DataTable data = new DataTable();
    ArrayList<ColumnDescription> cd = new ArrayList<ColumnDescription>();
    cd.add(new ColumnDescription("date", ValueType.DATETIME, "Date"));

    for (String serie : chartData.getSeries()) {
      cd.add(new ColumnDescription(serie, ValueType.NUMBER, serie));
    }
    data.addColumns(cd);
    try {

      for (TimeChartDataValue timeSerie : chartData.getValues()) {

        TableRow row = new TableRow();
        GregorianCalendar calendar = (GregorianCalendar) GregorianCalendar.getInstance();
        calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
        calendar.setTimeInMillis(
            TimeZone.getDefault().getOffset(timeSerie.getTimestamp().getTime())
                + timeSerie.getTimestamp().getTime());
        row.addCell(new TableCell(new DateTimeValue(calendar)));
        for (Double value : timeSerie.getValues()) {
          if (value != null) {
            row.addCell(value);
          } else {
            row.addCell(Value.getNullValueFromValueType(ValueType.NUMBER));
          }
        }
        data.addRow(row);
      }

    } catch (TypeMismatchException e) {
      System.out.println("Invalid type!");
    }
    Query query = new Query();
    DataSourceParameters parameters = new DataSourceParameters("");
    DataSourceRequest request = new DataSourceRequest(query, parameters, ULocale.UK);
    String generateResponse = DataSourceHelper.generateResponse(data, request);

    return generateResponse;
  }
 /**
  * Construct a <code>DangiCalendar</code> with the give date set in the default time zone with the
  * default locale.
  *
  * @param date The date to which the new calendar is set.
  * @internal
  * @deprecated This API is ICU internal only.
  */
 public DangiCalendar(Date date) {
   this(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT));
   setTime(date);
 }
 /**
  * Construct a <code>DangiCalendar</code> with the default time zone and locale.
  *
  * @internal
  * @deprecated This API is ICU internal only.
  */
 public DangiCalendar() {
   this(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT));
 }
/**
 * Notice:
 *
 * <p>dataSetRow -> dataSetRow row -> row
 *
 * <p>Please notice: dataSetRow can only be used in the column binding. In other cases, only row is
 * allowed to be used.
 *
 * <p>Here simple or complicated test cases can be added easily.
 */
public class ColumnBindingTest extends APITestCase {
  private TimeZone currentTimeZone = TimeZone.getDefault();
  /**
   * Column info
   *
   * <p>COUNTRY,CITY,SALE_DATE,AMOUNT,ORDERED,NULL_COLUMN
   *
   * @throws Exception
   */

  /** */
  @Before
  public void columnBindingSetUp() throws Exception {

    TimeZone.setDefault(TimeZone.getTimeZone("GMT+0"));
  }

  /** @throws Exception */
  @After
  public void columnBindingTearDown() throws Exception {
    TimeZone.setDefault(this.currentTimeZone);
  }

  /*
   * @see org.eclipse.birt.data.engine.api.APITestCase#getDataSourceInfo()
   */
  protected DataSourceInfo getDataSourceInfo() {
    return new DataSourceInfo(
        ConfigText.getString("Binding.TestData.TableName"),
        ConfigText.getString("Binding.TestData.TableSQL"),
        ConfigText.getString("Binding.TestData.TestDataFileName"));
  }

  /**
   * Without any transformation
   *
   * @throws Exception
   */
  @Test
  public void testBasic() throws Exception {
    QueryDefinition queryDefn = newReportQuery();

    // column mapping
    String[] name = new String[] {"testColumn1", "testColumn2", "AMOUNT1"};
    ScriptExpression[] se = new ScriptExpression[name.length];
    se[0] = new ScriptExpression("dataSetRow.COUNTRY");
    se[1] = new ScriptExpression("dataSetRow.CITY");
    se[2] = new ScriptExpression("dataSetRow.AMOUNT");
    for (int i = 0; i < name.length; i++) queryDefn.addBinding(new Binding(name[i], se[i]));

    IResultIterator ri = executeQuery(queryDefn);
    while (ri.next()) {
      String str = "";
      for (int i = 0; i < name.length; i++) {
        str += ri.getValue(name[i]);

        if (i < name.length - 1) str += ", ";
      }
      testPrintln(str);
    }

    checkOutputFile();
  }

  /**
   * Test the consistency of Data Type Info.
   *
   * @throws Exception
   */
  @Test
  public void testBasic1() throws Exception {
    QueryDefinition queryDefn = newReportQuery();

    // column mapping
    String[] name = new String[] {"AMOUNT1", "AMOUNT2"};
    ScriptExpression[] se = new ScriptExpression[name.length];
    se[0] = new ScriptExpression("dataSetRow.AMOUNT");
    se[0].setDataType(DataType.STRING_TYPE);
    se[1] = new ScriptExpression("row.AMOUNT1");
    se[1].setDataType(DataType.UNKNOWN_TYPE);
    for (int i = 0; i < name.length; i++) queryDefn.addBinding(new Binding(name[i], se[i]));

    IResultIterator ri = executeQuery(queryDefn);
    while (ri.next()) {
      assertTrue(ri.getValue("AMOUNT2") instanceof String);
    }
  }

  /** @throws Exception */
  @Test
  public void testBasic2() throws Exception {
    QueryDefinition queryDefn = newReportQuery();

    // column mapping
    String[] name = new String[] {"testColumn1", "testColumn2", "AMOUNT1"};
    ScriptExpression[] se = new ScriptExpression[name.length];
    se[0] = new ScriptExpression("dataSetRow.COUNTRY");
    se[1] = new ScriptExpression("row." + name[0]);
    se[2] = new ScriptExpression("dataSetRow.AMOUNT");
    for (int i = 0; i < name.length; i++) queryDefn.addBinding(new Binding(name[i], se[i]));

    IResultIterator ri = executeQuery(queryDefn);
    while (ri.next()) {
      String str = "";
      for (int i = 0; i < name.length; i++) {
        str += ri.getValue(name[i]);

        if (i < name.length - 1) str += ", ";
      }
      testPrintln(str);
    }

    checkOutputFile();
  }

  /** @throws Exception */
  @Test
  public void testBindingNameWithDoubleQuote() throws Exception {
    QueryDefinition queryDefn = newReportQuery();

    // column mapping
    String[] name = new String[] {"test\"Column1", "test\"Column2", "AMOUNT1"};
    ScriptExpression[] se = new ScriptExpression[name.length];
    se[0] = new ScriptExpression("dataSetRow.COUNTRY");
    se[1] = new ScriptExpression("row[\"test\\\"Column1\"]");
    se[2] = new ScriptExpression("dataSetRow.AMOUNT");
    for (int i = 0; i < name.length; i++) queryDefn.addBinding(new Binding(name[i], se[i]));

    IResultIterator ri = executeQuery(queryDefn);
    while (ri.next()) {
      String str = "";
      for (int i = 0; i < name.length; i++) {
        str += ri.getValue(name[i]);

        if (i < name.length - 1) str += ", ";
      }
      testPrintln(str);
    }

    checkOutputFile();
  }

  /**
   * Filtering on data set, without total
   *
   * @throws Exception
   */
  @Test
  public void testFilterOnDataSet() throws Exception {
    IBaseExpression baseExpr = new ScriptExpression("row.AMOUNT > 100");
    IFilterDefinition filterDefn = new FilterDefinition(baseExpr);
    this.dataSet.addFilter(filterDefn);

    QueryDefinition queryDefn = newReportQuery();

    // column mapping
    String[] name = new String[] {"testColumn1", "testColumn2", "AMOUNT1"};
    ScriptExpression[] se = new ScriptExpression[name.length];
    se[0] = new ScriptExpression("dataSetRow.COUNTRY");
    se[1] = new ScriptExpression("dataSetRow.CITY");
    se[2] = new ScriptExpression("dataSetRow.AMOUNT");
    for (int i = 0; i < name.length; i++) queryDefn.addBinding(new Binding(name[i], se[i]));

    IResultIterator ri = executeQuery(queryDefn);
    while (ri.next()) {
      String str = "";
      for (int i = 0; i < name.length; i++) {
        str += ri.getValue(name[i]);

        if (i < name.length - 1) str += ", ";
      }
      testPrintln(str);
    }

    checkOutputFile();
  }

  /**
   * Filtering on data set, without total
   *
   * @throws Exception
   */
  @Test
  public void testFilterOnDateType() throws Exception {

    FilterDefinition filterDefn =
        new FilterDefinition(
            new ConditionalExpression(
                "row.SALE_DATE",
                ConditionalExpression.OP_BETWEEN,
                "\'2004-05-01 00:00:00\'",
                "\'2004-06-05 00:00:00\'"));
    this.dataSet.addFilter(filterDefn);

    QueryDefinition queryDefn = newReportQuery();

    // column mapping
    String[] name = new String[] {"testColumn1", "testColumn2", "SALE_DATE"};
    ScriptExpression[] se = new ScriptExpression[name.length];
    se[0] = new ScriptExpression("dataSetRow.COUNTRY");
    se[1] = new ScriptExpression("dataSetRow.CITY");
    se[2] = new ScriptExpression("dataSetRow.SALE_DATE");
    for (int i = 0; i < name.length; i++) queryDefn.addBinding(new Binding(name[i], se[i]));

    IResultIterator ri = executeQuery(queryDefn);
    while (ri.next()) {
      String str = "";
      for (int i = 0; i < name.length; i++) {
        str += ri.getValue(name[i]);

        if (i < name.length - 1) str += ", ";
      }
      testPrintln(str);
    }

    checkOutputFile();
  }

  /**
   * TODO: Filtering on data set, with total
   *
   * @throws Exception
   */
  @Test
  public void testFilterOnDataSet2() throws Exception {}

  /**
   * Computed column on data set, without total
   *
   * @throws Exception
   */
  @Test
  public void testComputedOnDataSet() throws Exception {
    IComputedColumn cc = new ComputedColumn("AMOUNT2", "row.AMOUNT*2");
    this.dataSet.addComputedColumn(cc);

    QueryDefinition queryDefn = newReportQuery();

    // column mapping
    String[] name = new String[] {"testColumn1", "testColumn2", "AMOUNT1", "AMOUNT2"};
    ScriptExpression[] se = new ScriptExpression[name.length];
    se[0] = new ScriptExpression("dataSetRow.COUNTRY");
    se[1] = new ScriptExpression("dataSetRow.CITY");
    se[2] = new ScriptExpression("dataSetRow.AMOUNT");
    se[3] = new ScriptExpression("dataSetRow.AMOUNT2");
    for (int i = 0; i < name.length; i++) queryDefn.addBinding(new Binding(name[i], se[i]));

    IResultIterator ri = executeQuery(queryDefn);
    while (ri.next()) {
      String str = "";
      for (int i = 0; i < name.length; i++) {
        str += ri.getValue(name[i]);

        if (i < name.length - 1) str += ", ";
      }
      testPrintln(str);
    }

    checkOutputFile();
  }

  /**
   * TODO: Filtering on data set, with total
   *
   * @throws Exception
   */
  @Test
  public void testComputedOnDataSet2() throws Exception {}

  /**
   * Sort on table
   *
   * @throws Exception
   */
  @Test
  public void testFilterOnTable() throws Exception {
    QueryDefinition queryDefn = newReportQuery();

    // column mapping
    String[] name = new String[] {"testColumn1", "testColumn2", "AMOUNT1"};
    ScriptExpression[] se = new ScriptExpression[name.length];
    se[0] = new ScriptExpression("dataSetRow.COUNTRY");
    se[1] = new ScriptExpression("dataSetRow.CITY");
    se[2] = new ScriptExpression("dataSetRow.AMOUNT");
    for (int i = 0; i < name.length; i++) queryDefn.addBinding(new Binding(name[i], se[i]));

    ScriptExpression filterExpr = new ScriptExpression("row.AMOUNT1>100");
    FilterDefinition filterDefn = new FilterDefinition(filterExpr);
    queryDefn.addFilter(filterDefn);

    IResultIterator ri = executeQuery(queryDefn);
    while (ri.next()) {
      String str = "";
      for (int i = 0; i < name.length; i++) {
        str += ri.getValue(name[i]);

        if (i < name.length - 1) str += ", ";
      }
      testPrintln(str);
    }
  }

  /**
   * Test without data set
   *
   * @throws Exception
   */
  @Test
  public void testNoDataSet() throws Exception {
    String[] name = new String[] {"testColumn1", "testColumn2"};
    int[] dataType = new int[] {DataType.INTEGER_TYPE, DataType.DOUBLE_TYPE};
    ScriptExpression[] se =
        new ScriptExpression[] {
          new ScriptExpression("i=10", dataType[0]), new ScriptExpression("i=20", dataType[1]),
        };

    basicTestNoDataSet(name, dataType, se);

    this.checkOutputFile();
  }

  /**
   * Test without data set, with Java Script Object of NativeDate
   *
   * @throws Exception
   */
  @Test
  public void testNoDataSet2() throws Exception {
    String[] name = new String[] {"testColumn1", "testColumn2"};
    int[] dataType = new int[] {DataType.ANY_TYPE, DataType.ANY_TYPE};
    ScriptExpression[] se =
        new ScriptExpression[] {
          new ScriptExpression("new Date()", dataType[0]),
          new ScriptExpression("row[\"testColumn1\"].getFullYear( )", dataType[1]),
        };

    basicTestNoDataSet(name, dataType, se);
  }

  /**
   * Test without data set, with Java Script Object of NativeDate and DataType.DATE_TYPE
   *
   * @throws Exception
   */
  @Test
  public void testNoDataSet3() throws Exception {
    String[] name = new String[] {"testColumn1"};
    int[] dataType = new int[] {DataType.DATE_TYPE};
    ScriptExpression[] se =
        new ScriptExpression[] {
          new ScriptExpression("new Date()", dataType[0]),
        };

    basicTestNoDataSet(name, dataType, se);
  }

  /**
   * @param name
   * @param dataType
   * @param se
   * @throws BirtException
   */
  private void basicTestNoDataSet(String[] name, int[] dataType, ScriptExpression[] se)
      throws BirtException {
    DataEngine dataEngine =
        new DataEngineImpl(
            DataEngineContext.newInstance(DataEngineContext.DIRECT_PRESENTATION, null, null, null));
    QueryDefinition queryDefn = new QueryDefinition();

    for (int i = 0; i < name.length; i++) queryDefn.addBinding(new Binding(name[i], se[i]));

    IResultIterator ri = dataEngine.prepare(queryDefn).execute(null).getResultIterator();
    if (ri.next()) {
      String str = "";
      for (int i = 0; i < name.length; i++) {
        Object value = ri.getValue(name[i]);
        str += value;

        if (i < name.length - 1) str += ", ";

        if (dataType[i] == DataType.INTEGER_TYPE)
          assertTrue(value.getClass().equals(Integer.class));
        else if (dataType[i] == DataType.DOUBLE_TYPE)
          assertTrue(value.getClass().equals(Double.class));
        else if (dataType[i] == DataType.DATE_TYPE) assertTrue(value.getClass().equals(Date.class));
      }
      testPrintln(str);
    }
  }

  /** @throws Exception */
  @Test
  public void testNoDataSetWithNestedQuery() throws Exception {
    // outer query without data set
    String[] name = new String[] {"testColumn1"};
    IQueryResults queryResult = null;

    {
      int[] dataType = new int[] {DataType.DATE_TYPE};
      ScriptExpression[] se =
          new ScriptExpression[] {
            new ScriptExpression("new Date()", dataType[0]),
          };

      DataEngine myDataEngine =
          new DataEngineImpl(
              DataEngineContext.newInstance(
                  DataEngineContext.DIRECT_PRESENTATION, null, null, null));
      QueryDefinition queryDefn = new QueryDefinition();

      for (int i = 0; i < name.length; i++) queryDefn.addBinding(new Binding(name[i], se[i]));

      IResultIterator ri = myDataEngine.prepare(queryDefn).execute(null).getResultIterator();
      queryResult = ri.getQueryResults();
    }

    // inner query with data set
    QueryDefinition queryDefn2 = this.newReportQuery();
    for (int i = 0; i < name.length; i++)
      queryDefn2.addBinding(new Binding(name[i], new ScriptExpression("row._outer." + name[i])));

    IResultIterator ri2 =
        this.dataEngine.prepare(queryDefn2).execute(queryResult, null).getResultIterator();
    if (ri2.next()) {
      String str = "";
      for (int i = 0; i < name.length; i++) {
        Object value = ri2.getValue(name[i]);
        str += value;

        if (i < name.length - 1) str += ", ";
      }
      testPrintln(str);
    }
    ri2.close();
  }

  /** @throws Exception */
  @Test
  public void testNoDataSetWithSubQuery() throws Exception {
    // outer query without data set
    int[] dataType = new int[] {DataType.DATE_TYPE};
    String[] name = new String[] {"testColumn1"};

    IResultIterator ri2 = null;
    {
      ScriptExpression[] se =
          new ScriptExpression[] {
            new ScriptExpression("new Date()", dataType[0]),
          };

      QueryDefinition queryDefn = new QueryDefinition();
      for (int i = 0; i < name.length; i++) queryDefn.addBinding(new Binding(name[i], se[i]));

      // sub query
      String subQueryName = "TEST";
      SubqueryDefinition subQueryDefn = new SubqueryDefinition(subQueryName, queryDefn);
      for (int i = 0; i < name.length; i++)
        subQueryDefn.addBinding(
            new Binding(name[i], new ScriptExpression("row._outer." + name[i], dataType[i])));
      queryDefn.addSubquery(subQueryDefn);

      DataEngine myDataEngine =
          new DataEngineImpl(
              DataEngineContext.newInstance(
                  DataEngineContext.DIRECT_PRESENTATION, null, null, null));
      IResultIterator ri = myDataEngine.prepare(queryDefn).execute(null).getResultIterator();
      ri.next();
      ri2 = ri.getSecondaryIterator(subQueryName, null);
    }

    if (ri2.next()) {
      String str = "";
      for (int i = 0; i < name.length; i++) {
        Object value = ri2.getValue(name[i]);
        str += value;

        if (i < name.length - 1) str += ", ";

        if (dataType[0] == DataType.DATE_TYPE) assertTrue(value.getClass().equals(Date.class));
      }
      testPrintln(str);
    }
    ri2.close();
  }

  /** @throws Exception */
  @Test
  public void testAutoBinding() throws Exception {
    QueryDefinition queryDefn = newReportQuery(true);
    this.dataSet.addComputedColumn(new ComputedColumn("COUN\"TRY", "row[\"COUNTRY\"]"));

    // column mapping
    String[] name = new String[] {"COUN\"TRY", "CITY", "AMOUNT"};

    IResultIterator ri = executeQuery(queryDefn);
    while (ri.next()) {
      String str = "";
      for (int i = 0; i < name.length; i++) {
        str += ri.getValue(name[i]);

        if (i < name.length - 1) str += ", ";
      }
      testPrintln(str);
    }
    ri.close();
    checkOutputFile();
  }

  /** @throws Exception */
  @Test
  public void testAccessGroupColumn() throws Exception {
    QueryDefinition queryDefn = newReportQuery();

    // column mapping
    String[] name = new String[] {"testColumn1", "testColumn2", "AMOUNT1"};
    ScriptExpression[] se = new ScriptExpression[name.length];
    se[0] = new ScriptExpression("dataSetRow.COUNTRY");
    se[1] = new ScriptExpression("dataSetRow.CITY");
    se[2] = new ScriptExpression("dataSetRow.AMOUNT");
    for (int i = 0; i < name.length; i++) queryDefn.addBinding(new Binding(name[i], se[i]));

    GroupDefinition groupDefn = new GroupDefinition("group1");
    groupDefn.setKeyColumn("testColumn1");
    String name2 = "testColumn3";
    ScriptExpression se2 = new ScriptExpression("Total.sum(dataSetRow.AMOUNT)");
    se2.setGroupName("group1");
    // groupDefn.addResultSetExpression( name2, se2 );
    queryDefn.addBinding(new Binding(name2, se2));

    queryDefn.addGroup(groupDefn);

    IResultIterator ri = executeQuery(queryDefn);
    while (ri.next()) {
      String str = "";
      for (int i = 0; i < name.length; i++) {
        str += ri.getValue(name[i]);
        str += ", ";
      }
      str += ri.getValue(name2);

      testPrintln(str);
    }

    checkOutputFile();
  }

  /** @throws Exception */
  @Test
  public void testSpecialExpression() throws Exception {
    IComputedColumn cc = new ComputedColumn("AMOUNT2", "row.AMOUNT*2");
    this.dataSet.addComputedColumn(cc);

    QueryDefinition queryDefn = newReportQuery();

    // column mapping
    String[] name = new String[] {"testColumn1"};
    ScriptExpression[] se = new ScriptExpression[name.length];
    se[0] = new ScriptExpression("if ( 2<1 ){ true;  }else{ false;}");

    SortDefinition[] sortDefn = new SortDefinition[] {new SortDefinition()};
    sortDefn[0].setExpression("row.testColumn1");
    sortDefn[0].setSortDirection(ISortDefinition.SORT_DESC);

    for (int i = 0; i < name.length; i++) queryDefn.addBinding(new Binding(name[i], se[i]));
    for (int i = 0; i < sortDefn.length; i++) {
      queryDefn.addSort(sortDefn[i]);
    }

    IResultIterator ri = executeQuery(queryDefn);
    while (ri.next()) {
      String str = "";
      for (int i = 0; i < name.length; i++) {
        str += ri.getValue(name[i]);

        if (i < name.length - 1) str += ", ";
      }
      testPrintln(str);
    }

    checkOutputFile();
  }

  /** @throws Exception */
  @Test
  public void testSpecialExpression2() throws Exception {
    QueryDefinition queryDefn = newReportQuery();

    // column mapping
    String[] name = new String[] {"AMOUNT", "testColumn1"};
    ScriptExpression[] se = new ScriptExpression[name.length];
    se[0] = new ScriptExpression("dataSetRow.AMOUNT");
    se[1] =
        new ScriptExpression(
            "if ( row.AMOUNT >200 ){ Total.runningSum(row.AMOUNT);  }else{ row.AMOUNT;}");

    for (int i = 0; i < name.length; i++) queryDefn.addBinding(new Binding(name[i], se[i]));

    IResultIterator ri = executeQuery(queryDefn);
    while (ri.next()) {
      String str = "";
      for (int i = 0; i < name.length; i++) {
        str += ri.getValue(name[i]);

        if (i < name.length - 1) str += ", ";
      }
      testPrintln(str);
    }

    checkOutputFile();
  }

  /** @throws Exception */
  @Test
  public void testSpecialExpression3() throws Exception {
    QueryDefinition queryDefn = newReportQuery();
    // column mapping
    String[] name = new String[] {"AMOUNT", "testColumn1", "testColumn2"};
    ScriptExpression[] se = new ScriptExpression[name.length];
    se[0] = new ScriptExpression("dataSetRow.AMOUNT");
    se[1] =
        new ScriptExpression(
            "var p=dataSetRow.AMOUNT+1;if( p >200 ){\"A large amount!\";  } else{ \"A small amount!\";}");
    se[2] = new ScriptExpression("row[\"testColumn1\"]+dataSetRow.AMOUNT");

    for (int i = 0; i < name.length; i++) queryDefn.addBinding(new Binding(name[i], se[i]));

    IResultIterator ri = executeQuery(queryDefn);
    while (ri.next()) {
      String str = "";
      for (int i = 0; i < name.length; i++) {
        str += ri.getValue(name[i]);

        if (i < name.length - 1) str += ", ";
      }
      testPrintln(str);
    }

    checkOutputFile();
  }

  /** @throws Exception */
  @Test
  public void testInvalidSort() throws Exception {
    for (int i = 0; i < 4; i++) this.testInvalidSort(i);
  }

  /** @throws Exception */
  private void testInvalidSort(int sortIndex) throws Exception {
    QueryDefinition queryDefn = newReportQuery();
    // column mapping
    String[] name = new String[] {"rownum1", "rownum2", "rownum3"};

    ScriptExpression[] se = new ScriptExpression[name.length];
    se[0] = new ScriptExpression("row.__rownum");
    se[1] = new ScriptExpression("row.rownum1");
    se[2] = new ScriptExpression("row[\"rownum2\"]");

    for (int i = 0; i < name.length; i++) queryDefn.addBinding(new Binding(name[i], se[i]));

    SortDefinition[] sort = new SortDefinition[name.length + 1];
    sort[0] = new SortDefinition();
    sort[0].setExpression("row.rownum1");
    sort[1] = new SortDefinition();
    sort[1].setExpression("row.rownum2");
    sort[2] = new SortDefinition();
    sort[2].setExpression("row.rownum3");
    sort[3] = new SortDefinition();
    sort[3].setExpression("row.__rownum");

    queryDefn.addSort(sort[sortIndex]);

    try {
      executeQuery(queryDefn);
      fail("Should not arrive here");
    } catch (DataException e) {
    }
  }

  /** @throws Exception */
  @Test
  public void testInvalidFilter() throws Exception {
    for (int i = 0; i < 4; i++) this.testInvalidFilter(i);
  }

  /** @throws Exception */
  private void testInvalidFilter(int filterIndex) throws Exception {
    QueryDefinition queryDefn = newReportQuery();
    // column mapping
    String[] name = new String[] {"rownum1", "rownum2", "rownum3"};

    ScriptExpression[] se = new ScriptExpression[name.length];
    se[0] = new ScriptExpression("row.__rownum");
    se[1] = new ScriptExpression("row.rownum1");
    se[2] = new ScriptExpression("row[\"rownum2\"]");

    for (int i = 0; i < name.length; i++) queryDefn.addBinding(new Binding(name[i], se[i]));

    FilterDefinition[] filter = new FilterDefinition[name.length + 1];
    filter[0] = new FilterDefinition(new ScriptExpression("row.rownum1 == 1"));
    filter[1] = new FilterDefinition(new ScriptExpression("row.rownum2 == 1"));
    filter[2] = new FilterDefinition(new ScriptExpression("row.rownum3 == 1"));
    filter[3] = new FilterDefinition(new ScriptExpression("row.__rownum == 1"));
    queryDefn.addFilter(filter[filterIndex]);

    try {
      executeQuery(queryDefn);
      fail("Should not arrive here");
    } catch (DataException e) {
    }
  }
  /** @throws Exception */
  @Test
  public void testGroup() throws Exception {
    QueryDefinition queryDefn = newReportQuery();

    // column mapping
    String[] name = new String[] {"testColumn1", "testColumn2", "AMOUNT1"};
    ScriptExpression[] se = new ScriptExpression[name.length];
    se[0] = new ScriptExpression("dataSetRow.COUNTRY");
    se[1] = new ScriptExpression("dataSetRow.CITY");
    se[2] = new ScriptExpression("dataSetRow.AMOUNT");
    for (int i = 0; i < name.length; i++) queryDefn.addBinding(new Binding(name[i], se[i]));

    GroupDefinition groupDefn = new GroupDefinition("group1");
    groupDefn.setKeyColumn("testColumn1");
    String name2 = "testColumn3";
    ScriptExpression se2 = new ScriptExpression("Total.sum(dataSetRow.AMOUNT)");
    se2.setGroupName("group1");
    // groupDefn.addResultSetExpression( name2, new ColumnBindingExpression(se2) );
    queryDefn.addBinding(new Binding(name2, se2));
    queryDefn.addGroup(groupDefn);
    String name3 = "testColumn4";
    ScriptExpression se3 = new ScriptExpression("row[\"testColumn1\"]");
    GroupDefinition groupDefn1 = new GroupDefinition("group2");
    groupDefn1.setKeyColumn("testColumn4");
    se3.setGroupName("group2");
    // groupDefn1.addResultSetExpression( name3, new ColumnBindingExpression(se3) );
    queryDefn.addBinding(new Binding(name3, se3));
    queryDefn.addGroup(groupDefn1);

    IResultIterator ri = executeQuery(queryDefn);
    while (ri.next()) {
      String str = "";
      for (int i = 0; i < name.length; i++) {
        str += ri.getValue(name[i]);
        str += ", ";
      }
      str += ri.getValue(name2);

      testPrintln(str);
    }

    checkOutputFile();
  }

  /** @throws Exception */
  @Test
  public void testInvalidBinding() throws Exception {
    QueryDefinition queryDefn = newReportQuery();

    // column mapping
    String[] name = new String[] {"testColumn1"};
    ScriptExpression[] se = new ScriptExpression[name.length];
    se[0] = new ScriptExpression("dataSetRow.COUNTRY");
    for (int i = 0; i < name.length; i++) queryDefn.addBinding(new Binding(name[i], se[i]));

    IResultIterator ri = executeQuery(queryDefn);
    if (ri.next()) {
      try {
        ri.getValue(name[0]);
      } catch (BirtException e) {
        assertTrue(e.getErrorCode() == ResourceConstants.INVALID_JS_EXPR);
      }
    }
    ri.close();
  }

  /** @throws Exception */
  @Test
  public void testBlankExpression() throws Exception {
    QueryDefinition queryDefn = newReportQuery();

    // column mapping
    String[] name = new String[] {"testColumn1"};
    ScriptExpression[] se = new ScriptExpression[name.length];
    se[0] = new ScriptExpression(null);

    for (int i = 0; i < name.length; i++) queryDefn.addBinding(new Binding(name[i], se[i]));

    DataException error = null;
    try {
      executeQuery(queryDefn);
      fail("Should not arrive here");
    } catch (DataException e) {
      //			assertTrue( e.getErrorCode( ) == ResourceConstants.EXPRESSION_CANNOT_BE_NULL_OR_BLANK );
      error = e;
    }

    assertNotNull(error);
  }

  // ----------------report document test---------------------

  private FileArchiveWriter archiveWriter;
  private FileArchiveReader archiveReader;

  private String[] rowExprName;
  private String[] totalExprName;

  private String queryResultID;
  private List expectedValue;

  private DataEngine myGenDataEngine;
  private DataEngine myPreDataEngine;

  /** @throws Exception */
  @Test
  public void testBasicReportDocument() throws Exception {
    String fileName = getOutputFolder() + "testData";
    DataEngineContext deContext1 = newContext(DataEngineContext.MODE_GENERATION, fileName);
    myGenDataEngine = DataEngine.newDataEngine(deContext1);

    myGenDataEngine.defineDataSource(this.dataSource);
    myGenDataEngine.defineDataSet(this.dataSet);

    this.genBasic();
    this.closeArchiveWriter();

    DataEngineContext deContext2 = newContext(DataEngineContext.MODE_PRESENTATION, fileName);
    myPreDataEngine = DataEngine.newDataEngine(deContext2);

    this.preBasic();
    this.closeArchiveReader();
    this.checkOutputFile();
  }

  /** @throws Exception */
  private void genBasic() throws Exception {
    expectedValue = new ArrayList();

    Context context = Context.enter();
    Scriptable scope = context.initStandardObjects();
    Context.exit();

    // ------------generation----------------
    QueryDefinition qd = newReportQuery();

    // prepare
    IBaseExpression[] rowBeArray = getRowExpr();
    IBinding[] totalBeArray = getAggrBinding();
    prepareExprNameAndQuery(rowBeArray, totalBeArray, qd);

    // generation
    IQueryResults qr = myGenDataEngine.prepare(qd).execute(scope);

    // important step
    queryResultID = qr.getID();

    IResultIterator ri = qr.getResultIterator();
    while (ri.next()) {
      for (int i = 0; i < rowBeArray.length; i++)
        expectedValue.add(ri.getValue(this.rowExprName[i]));

      for (int i = 0; i < totalBeArray.length; i++)
        expectedValue.add(ri.getValue(this.totalExprName[i]));
    }

    ri.close();
    qr.close();
    myGenDataEngine.shutdown();
  }

  /** @throws Exception */
  private void genSerializable() throws Exception {
    Context context = Context.enter();
    Scriptable scope = context.initStandardObjects();
    Context.exit();

    QueryDefinition queryDefn = newReportQuery();

    // column mapping
    String[] name = new String[] {"serializable"};
    ScriptExpression[] se = new ScriptExpression[name.length];
    se[0] = new ScriptExpression("new java.lang.StringBuffer(\"ss\")");
    se[0].setDataType(DataType.JAVA_OBJECT_TYPE);
    for (int i = 0; i < name.length; i++) queryDefn.addBinding(new Binding(name[i], se[i]));

    // generation
    IQueryResults qr = myGenDataEngine.prepare(queryDefn).execute(scope);

    // important step
    queryResultID = qr.getID();

    IResultIterator ri = qr.getResultIterator();
    assertEquals(DataType.JAVA_OBJECT_TYPE, ri.getResultMetaData().getColumnType(1));
    while (ri.next()) {
      assertTrue(ri.getValue("serializable") instanceof StringBuffer);
      assertEquals("ss", ri.getValue("serializable").toString());
    }

    ri.close();
    qr.close();
    myGenDataEngine.shutdown();
  }

  /** @throws Exception */
  private void genUnserializable() throws Exception {
    Context context = Context.enter();
    Scriptable scope = context.initStandardObjects();
    Context.exit();

    QueryDefinition queryDefn = newReportQuery();

    // column mapping
    String[] name = new String[] {"unserializable"};
    ScriptExpression[] se = new ScriptExpression[name.length];
    se[0] = new ScriptExpression("new java.lang.ThreadGroup(\"ss\")");
    se[0].setDataType(DataType.JAVA_OBJECT_TYPE);
    for (int i = 0; i < name.length; i++) queryDefn.addBinding(new Binding(name[i], se[i]));

    // generation
    IQueryResults qr = myGenDataEngine.prepare(queryDefn).execute(scope);

    // important step
    queryResultID = qr.getID();

    try {

      IResultIterator ri = qr.getResultIterator();
      assertEquals(DataType.JAVA_OBJECT_TYPE, ri.getResultMetaData().getColumnType(1));
      while (ri.next()) {
        assertTrue(ri.getValue("unserializable") instanceof ThreadGroup);
      }
      ri.close();
      assertTrue(false);
    } catch (Exception e) {
      // Currently, unserializable objects can't be saved in report doc
      e.printStackTrace();
    } finally {
      qr.close();
      myGenDataEngine.shutdown();
    }
  }

  /** @throws Exception */
  private void preSerializable() throws Exception {
    IQueryResults qr = myPreDataEngine.getQueryResults(queryResultID);

    IResultIterator ri = qr.getResultIterator();
    // Currently, org.eclipse.birt.data.engine.impl.document.ResultIterator#getResultMetaData() has
    // bug:
    // It returns meta data of data set instead of meta data of query
    // assertEquals( DataType.OBJECT_TYPE, ri.getResultMetaData( ).getColumnType( 1 ));
    int rowCount = 0;
    while (ri.next()) {
      assertTrue(ri.getValue("serializable") instanceof StringBuffer);
      assertEquals("ss", ri.getValue("serializable").toString());
      rowCount++;
    }
    assertTrue(rowCount > 0);
    ri.close();
    myPreDataEngine.shutdown();
  }

  /** @throws Exception */
  private void preBasic() throws Exception {
    IQueryResults qr = myPreDataEngine.getQueryResults(queryResultID);
    assert (qr.getResultMetaData() != null);

    IResultIterator ri = qr.getResultIterator();
    assert (ri.getResultMetaData() != null);

    checkResult1(ri);

    ri.close();
    myPreDataEngine.shutdown();
  }

  /** @throws Exception */
  @Test
  public void testDummy1Document() throws Exception {
    String fileName = getOutputFolder() + "testData";
    DataEngineContext deContext1 = newContext(DataEngineContext.MODE_GENERATION, fileName);
    myGenDataEngine = DataEngine.newDataEngine(deContext1);

    myGenDataEngine.defineDataSource(this.dataSource);
    myGenDataEngine.defineDataSet(this.dataSet);

    this.genDummy1();
    this.closeArchiveWriter();

    DataEngineContext deContext2 = newContext(DataEngineContext.MODE_PRESENTATION, fileName);
    myPreDataEngine = DataEngine.newDataEngine(deContext2);

    this.preDummy1();
    this.closeArchiveReader();
  }

  /**
   * Test Java Object data type
   *
   * @throws Exception
   */
  @Test
  public void testObjectTypeBasic() throws Exception {
    QueryDefinition queryDefn = newReportQuery();

    // column mapping
    String[] name =
        new String[] {
          "ObjectType",
        };
    ScriptExpression[] se = new ScriptExpression[name.length];
    se[0] = new ScriptExpression("new java.lang.StringBuffer(\"ss\")");
    se[0].setDataType(DataType.JAVA_OBJECT_TYPE);
    for (int i = 0; i < name.length; i++) queryDefn.addBinding(new Binding(name[i], se[i]));

    IResultIterator ri = executeQuery(queryDefn);
    assertEquals(DataType.JAVA_OBJECT_TYPE, ri.getResultMetaData().getColumnType(1));
    while (ri.next()) {
      assertTrue(ri.getValue("ObjectType") instanceof StringBuffer);
      assertEquals("ss", ri.getValue("ObjectType").toString());
    }
  }

  /** @throws Exception */
  @Test
  public void testSerializableObjectTypeInReportDocument() throws Exception {
    String fileName = getOutputFolder() + "testData";
    DataEngineContext deContext1 = newContext(DataEngineContext.MODE_GENERATION, fileName);
    myGenDataEngine = DataEngine.newDataEngine(deContext1);

    myGenDataEngine.defineDataSource(this.dataSource);
    myGenDataEngine.defineDataSet(this.dataSet);

    genSerializable();
    this.closeArchiveWriter();

    DataEngineContext deContext2 = newContext(DataEngineContext.MODE_PRESENTATION, fileName);
    myPreDataEngine = DataEngine.newDataEngine(deContext2);

    this.preSerializable();
    this.closeArchiveReader();
  }

  /** @throws Exception */
  @Test
  public void testUnserializableObjectTypeInReportDocument() throws Exception {
    String fileName = getOutputFolder() + "testData";
    DataEngineContext deContext1 = newContext(DataEngineContext.MODE_GENERATION, fileName);
    myGenDataEngine = DataEngine.newDataEngine(deContext1);

    myGenDataEngine.defineDataSource(this.dataSource);
    myGenDataEngine.defineDataSet(this.dataSet);

    genUnserializable();

    // this.closeArchiveWriter( );
    //
    //		DataEngineContext deContext2 = newContext( DataEngineContext.MODE_PRESENTATION,
    //				fileName );
    //		myPreDataEngine = DataEngine.newDataEngine( deContext2 );
    //
    //		this.preSerializable( );
    // this.closeArchiveReader( );
  }

  /** @throws Exception */
  private void genDummy1() throws Exception {
    expectedValue = new ArrayList();

    Context context = Context.enter();
    Scriptable scope = context.initStandardObjects();
    Context.exit();

    // ------------generation----------------
    QueryDefinition qd = new QueryDefinition();

    // prepare
    IBaseExpression[] rowBeArray = getDummyRowExpr();
    prepareExprNameAndQuery(rowBeArray, null, qd);

    // generation
    IQueryResults qr = myGenDataEngine.prepare(qd).execute(scope);

    // important step
    queryResultID = qr.getID();

    IResultIterator ri = qr.getResultIterator();
    while (ri.next()) {
      for (int i = 0; i < rowBeArray.length; i++)
        expectedValue.add(ri.getValue(this.rowExprName[i]));
    }

    ri.close();
    qr.close();
    myGenDataEngine.shutdown();
  }

  /** @throws Exception */
  private void preDummy1() throws Exception {
    IQueryResults qr = myPreDataEngine.getQueryResults(queryResultID);
    assert (qr.getResultMetaData() != null);

    IResultIterator ri = qr.getResultIterator();
    assert (ri.getResultMetaData() != null);

    checkResult1(ri);

    ri.close();
    myPreDataEngine.shutdown();
  }

  /** @return row expression array */
  private IBaseExpression[] getDummyRowExpr() {
    // row test
    int num = 1;
    IBaseExpression[] rowBeArray = new IBaseExpression[num];
    rowBeArray[0] = new ScriptExpression("new Date()", DataType.DATE_TYPE);

    this.rowExprName = new String[rowBeArray.length];
    this.rowExprName[0] = "Date";

    return rowBeArray;
  }

  /** @throws Exception */
  @Test
  public void testDummy2Document() throws Exception {
    String fileName = getOutputFolder() + "testData";
    DataEngineContext deContext1 = newContext(DataEngineContext.MODE_GENERATION, fileName);
    myGenDataEngine = DataEngine.newDataEngine(deContext1);

    myGenDataEngine.defineDataSource(this.dataSource);
    myGenDataEngine.defineDataSet(this.dataSet);

    this.genDummy2();
    this.closeArchiveWriter();

    DataEngineContext deContext2 = newContext(DataEngineContext.MODE_PRESENTATION, fileName);
    myPreDataEngine = DataEngine.newDataEngine(deContext2);

    this.preDummy2();
    this.closeArchiveReader();
  }

  private String subName = "subName";

  /** @throws Exception */
  private void genDummy2() throws Exception {
    expectedValue = new ArrayList();

    Context context = Context.enter();
    Scriptable scope = context.initStandardObjects();
    Context.exit();

    // ------------generation----------------
    QueryDefinition qd = new QueryDefinition();

    // prepare
    IBaseExpression[] rowBeArray = getDummyRowExpr();
    prepareExprNameAndQuery(rowBeArray, null, qd);

    // prepare sub query
    SubqueryDefinition subQueryDefn = new SubqueryDefinition(subName, qd);
    qd.addSubquery(subQueryDefn);
    IBaseExpression[] rowBeArray2 = getDummyRowExpr();
    prepareExprNameAndQuery(rowBeArray2, null, subQueryDefn);

    // generation
    IQueryResults qr = myGenDataEngine.prepare(qd).execute(scope);

    // important step
    queryResultID = qr.getID();

    IResultIterator ri = qr.getResultIterator();
    while (ri.next()) {
      for (int i = 0; i < rowBeArray.length; i++)
        expectedValue.add(ri.getValue(this.rowExprName[i]));

      IResultIterator ri2 = ri.getSecondaryIterator(subName, scope);
      while (ri2.next()) {
        for (int i = 0; i < rowBeArray2.length; i++)
          expectedValue.add(ri2.getValue(this.rowExprName[i]));
      }
      ri2.close();
    }

    ri.close();
    qr.close();
    myGenDataEngine.shutdown();
  }

  /** @throws Exception */
  private void preDummy2() throws Exception {
    IQueryResults qr = myPreDataEngine.getQueryResults(queryResultID);
    assert (qr.getResultMetaData() != null);

    IResultIterator ri = qr.getResultIterator();
    assert (ri.getResultMetaData() != null);

    checkResult2(ri);

    ri.close();
    myPreDataEngine.shutdown();
  }

  /**
   * @param type
   * @param fileName
   * @return
   * @throws BirtException
   */
  private DataEngineContext newContext(int type, String fileName) throws BirtException {

    switch (type) {
      case DataEngineContext.MODE_GENERATION:
        {
          try {
            archiveWriter = new FileArchiveWriter(fileName);
            archiveWriter.initialize();
          } catch (IOException e) {
            throw new IllegalArgumentException(e.getMessage());
          }
          return DataEngineContext.newInstance(
              DataEngineContext.MODE_GENERATION, null, null, archiveWriter);
        }
      case DataEngineContext.MODE_PRESENTATION:
        {
          try {
            archiveReader = new FileArchiveReader(fileName);
            archiveReader.open();
          } catch (IOException e) {
            throw new IllegalArgumentException(e.getMessage());
          }
          return DataEngineContext.newInstance(
              DataEngineContext.MODE_PRESENTATION, null, archiveReader, null);
        }
      default:
        throw new IllegalArgumentException("" + type);
    }
  }

  /** @return row expression array */
  private IBaseExpression[] getRowExpr() {
    // row test
    int num = 4;
    IBaseExpression[] rowBeArray = new IBaseExpression[num];
    rowBeArray[0] = new ScriptExpression("dataSetRow.COUNTRY");
    rowBeArray[1] = new ScriptExpression("dataSetRow.CITY");
    rowBeArray[2] = new ScriptExpression("dataSetRow.SALE_DATE");
    rowBeArray[3] = new ScriptExpression("dataSetRow.AMOUNT");

    this.rowExprName = new String[rowBeArray.length];
    this.rowExprName[0] = "COUNTRY_1";
    this.rowExprName[1] = "CITY_1";
    this.rowExprName[2] = "SALE_NAME_1";
    this.rowExprName[3] = "AMOUNT_1";

    return rowBeArray;
  }

  /**
   * @return aggregation expression array
   * @throws DataException
   */
  private IBinding[] getAggrBinding() throws DataException {
    int num2 = 2;
    totalExprName = new String[num2];
    this.totalExprName[0] = "TOTAL_COUNT_1";
    this.totalExprName[1] = "TOTAL_AMOUNT_1";

    IBinding[] totalBeArray = new IBinding[num2];
    totalBeArray[0] = new Binding(this.totalExprName[0]);
    totalBeArray[0].setAggrFunction("COUNT");
    totalBeArray[1] = new Binding(this.totalExprName[1], new ScriptExpression("row.AMOUNT_1"));
    totalBeArray[1].setAggrFunction("SUM");

    return totalBeArray;
  }

  /**
   * Add expression on the row of group
   *
   * @param rowBeArray
   * @param totalBeArray
   * @param qd
   * @throws DataException
   */
  private void prepareExprNameAndQuery(
      IBaseExpression[] rowBeArray, IBinding[] totalBeArray, BaseQueryDefinition qd)
      throws DataException {
    int num = rowBeArray.length;

    for (int i = 0; i < num; i++) qd.addBinding(new Binding(this.rowExprName[i], rowBeArray[i]));

    if (totalBeArray != null) {
      int num2 = totalBeArray.length;
      for (int i = 0; i < num2; i++) qd.addBinding(totalBeArray[i]);
    }
  }

  /**
   * Only check the result of the expectedValue of the result set
   *
   * @param data.it
   * @param ri
   * @throws DataException
   * @throws BirtException
   */
  private void checkResult1(IResultIterator ri) throws BirtException {
    Iterator it = this.expectedValue.iterator();

    while (ri.next()) {
      String str = "";
      for (int i = 0; i < rowExprName.length; i++) {
        Object ob1 = it.next();
        Object ob2 = ri.getValue(this.rowExprName[i]);
        assertEquals(ob1, ob2);
        str += " " + ob2.toString();
      }

      if (totalExprName != null) {
        for (int i = 0; i < totalExprName.length; i++) {
          Object ob1 = it.next();
          Object ob2 = ri.getValue(this.totalExprName[i]);
          assertEquals(ob1, ob2);
          str += " " + ob2.toString();
        }
      }

      this.testPrintln("row result set: " + str);
    }
  }

  /**
   * @param ri
   * @throws BirtException
   */
  private void checkResult2(IResultIterator ri) throws BirtException {
    Iterator it = this.expectedValue.iterator();

    while (ri.next()) {
      String str = "";
      for (int i = 0; i < rowExprName.length; i++) {
        Object ob1 = it.next();
        Object ob2 = ri.getValue(this.rowExprName[i]);
        assertEquals(ob1, ob2);
        str += " " + ob2.toString();
      }

      IResultIterator ri2 = ri.getSecondaryIterator(subName, null);
      while (ri2.next()) {
        for (int i = 0; i < rowExprName.length; i++) {
          Object ob1 = it.next();
          Object ob2 = ri2.getValue(this.rowExprName[i]);
          assertEquals(ob1, ob2);
          str += " " + ob2.toString();
        }
      }

      if (totalExprName != null) {
        for (int i = 0; i < totalExprName.length; i++) {
          Object ob1 = it.next();
          Object ob2 = ri.getValue(this.totalExprName[i]);
          assertEquals(ob1, ob2);
          str += " " + ob2.toString();
        }
      }

      this.testPrintln("row result set: " + str);
    }
  }

  /** @throws DataException */
  private void closeArchiveWriter() throws DataException {
    if (archiveWriter != null)
      try {
        archiveWriter.finish();
      } catch (IOException e) {
        throw new DataException("error", e);
      }
  }

  /** @throws DataException */
  private void closeArchiveReader() throws DataException {
    if (archiveReader != null)
      try {
        archiveReader.close();
      } catch (IOException e) {
        throw new DataException("error", e);
      }
  }
}
 /**
  * Constructs a Persian calendar with the default time zone and locale and sets its time to the
  * specified date-time.
  *
  * @param date the date of this calendar object.
  */
 public PersianCalendar(Date date) {
   super(TimeZone.getDefault(), ULocale.getDefault());
   setTime(date);
 }
 /**
  * Constructs a Persian calendar with the default time zone and the specified locale.
  *
  * @param locale the desired locale.
  */
 public PersianCalendar(ULocale locale) {
   this(TimeZone.getDefault(), locale);
 }
 /** Constructs a Persian calendar with the default time zone and locale. */
 public PersianCalendar() {
   this(TimeZone.getDefault(), ULocale.getDefault());
 }
/** Utilities class to convert report parameter value between object and string. */
public class ReportParameterConverter {

  private String format = null;
  private ULocale uLocale = null;
  private TimeZone timeZone = TimeZone.getDefault();

  private StringFormatter sf = null;
  private DateFormatter df = null;
  private NumberFormatter nf = null;

  /**
   * @param format format to format report parameter, or recover parameter value as object given a
   *     string as report parameter value
   * @param locale the locale to format/parse the parameter value
   */
  public ReportParameterConverter(String format, Locale locale) {
    this(format, ULocale.forLocale(locale));
  }

  /**
   * Constructor.
   *
   * @param format
   * @param uLocale
   */
  public ReportParameterConverter(String format, ULocale uLocale) {
    this(format, uLocale, null);
  }

  /**
   * Constructor.
   *
   * @param format
   * @param uLocale
   * @param timeZone
   */
  public ReportParameterConverter(String format, ULocale uLocale, TimeZone timeZone) {
    this.format = format;
    this.uLocale = uLocale;
    if (timeZone != null) {
      this.timeZone = timeZone;
    }
  }

  /**
   * Get string formatter.
   *
   * @return StringFormatter object
   */
  private StringFormatter getStringFormatter() {
    if (sf == null && uLocale != null) {
      sf = new StringFormatter(uLocale);
      if (format != null) {
        sf.applyPattern(format);
      }
    }
    return sf;
  }

  /**
   * Get number formatter.
   *
   * @return NumberFormatter object
   */
  private NumberFormatter getNumberFormatter() {
    if (nf == null && uLocale != null) {
      nf = new NumberFormatter(uLocale);
      if (format != null) {
        nf.applyPattern(format);
      }
    }
    return nf;
  }

  /**
   * Get date formatter.
   *
   * @return DateFormatter object
   */
  private DateFormatter getDateFormatter() {
    if (df == null && uLocale != null) {
      df = new DateFormatter(uLocale, timeZone);
      if (format != null) {
        df.applyPattern(format);
      }
    }
    return df;
  }

  /**
   * Convert report parameter value object into string.
   *
   * @param reportParameterObj report parameter value object.
   * @return parameter value in string.
   */
  public String format(Object reportParameterObj) {
    String reportParameterValue = null;

    if (reportParameterObj != null && uLocale != null) {
      if (reportParameterObj instanceof String) {
        StringFormatter sf = getStringFormatter();
        if (sf != null) {
          reportParameterValue = sf.format((String) reportParameterObj);
        } else {
          reportParameterValue = reportParameterObj.toString();
        }
      } else if (reportParameterObj instanceof Date) {
        DateFormatter df = getDateFormatter();
        if (df != null) {
          reportParameterValue = df.format((Date) reportParameterObj);
        } else {
          reportParameterValue = reportParameterObj.toString();
        }
      } else if (reportParameterObj instanceof Double) {
        NumberFormatter nf = getNumberFormatter();
        if (nf != null) {
          reportParameterValue = nf.format(((Double) reportParameterObj).doubleValue());
        } else {
          reportParameterValue = reportParameterObj.toString();
        }
      } else if (reportParameterObj instanceof BigDecimal) {
        NumberFormatter nf = getNumberFormatter();
        if (nf != null) {
          reportParameterValue = nf.format((BigDecimal) reportParameterObj);
        } else {
          reportParameterValue = reportParameterObj.toString();
        }
      } else if (reportParameterObj instanceof Boolean) {
        reportParameterValue = ((Boolean) reportParameterObj).toString();
      } else if (reportParameterObj instanceof Number) {
        NumberFormatter nf = getNumberFormatter();
        if (nf != null) {
          reportParameterValue = nf.format(((Number) reportParameterObj));
        } else {
          reportParameterValue = reportParameterObj.toString();
        }
      } else {
        reportParameterValue = (reportParameterObj.toString());
      }
    }

    return reportParameterValue;
  }

  /**
   * Convert report parameter from string into object. Need to be pointed out is it return a Double
   * object when the value type is Float.
   *
   * @param reportParameterValue report parameter value in string.
   * @param parameterValueType report parameter type.
   * @return parameter value object.
   */
  public Object parse(String reportParameterValue, int parameterValueType) {
    Object parameterValueObj = null;

    if (reportParameterValue != null && uLocale != null) {
      switch (parameterValueType) {
        case IScalarParameterDefn.TYPE_STRING:
          {
            StringFormatter sf = getStringFormatter();
            if (sf == null) {
              parameterValueObj = null;
              break;
            }

            try {
              parameterValueObj = sf.parser(reportParameterValue);
            } catch (ParseException e) {
              parameterValueObj = reportParameterValue;
            }
            break;
          }

        case IScalarParameterDefn.TYPE_DATE_TIME:
          {
            parameterValueObj = parseDateTime(reportParameterValue);
            break;
          }

        case IScalarParameterDefn.TYPE_FLOAT:
          {
            NumberFormatter nf = getNumberFormatter();
            if (nf == null) {
              parameterValueObj = null;
              break;
            }

            try {
              Number num = nf.parse(reportParameterValue);

              if (num != null) {
                parameterValueObj = new Double(num.toString());
              }
            } catch (ParseException e) {
              nf.applyPattern("General Number");

              try {
                Number num = nf.parse(reportParameterValue);

                if (num != null) {
                  parameterValueObj = new Double(num.toString());
                }
              } catch (ParseException ex) {
                parameterValueObj = null;
              }
            }

            break;
          }

        case IScalarParameterDefn.TYPE_DECIMAL:
          {
            NumberFormatter nf = getNumberFormatter();
            if (nf == null) {
              parameterValueObj = null;
              break;
            }

            try {
              Number num = nf.parse(reportParameterValue);

              if (num != null) {
                parameterValueObj = new BigDecimal(num.toString());
              }
            } catch (ParseException e) {
              nf.applyPattern("General Number");

              try {
                Number num = nf.parse(reportParameterValue);

                if (num != null) {
                  parameterValueObj = new BigDecimal(num.toString());
                }
              } catch (ParseException ex) {
                parameterValueObj = null;
              }
            }

            break;
          }

        case IScalarParameterDefn.TYPE_BOOLEAN:
          {
            parameterValueObj = Boolean.valueOf(reportParameterValue);
            break;
          }

        case IScalarParameterDefn.TYPE_DATE:
          {
            try {
              parameterValueObj = java.sql.Date.valueOf(reportParameterValue);
            } catch (IllegalArgumentException ie) {
              parameterValueObj = parseDateTime(reportParameterValue);
              if (parameterValueObj != null) {
                parameterValueObj = new java.sql.Date(((Date) parameterValueObj).getTime());
              }
            }
            break;
          }

        case IScalarParameterDefn.TYPE_TIME:
          {
            try {
              parameterValueObj = java.sql.Time.valueOf(reportParameterValue);
            } catch (IllegalArgumentException ie) {
              parameterValueObj = parseDateTime(reportParameterValue);
              if (parameterValueObj != null) {
                parameterValueObj = new java.sql.Time(((Date) parameterValueObj).getTime());
              }
            }
            break;
          }

          // can use class DataTypeUtil to convert
        case IScalarParameterDefn.TYPE_INTEGER:
          {
            NumberFormatter nf = getNumberFormatter();
            if (nf == null) {
              parameterValueObj = null;
              break;
            }

            try {
              Number num = nf.parse(reportParameterValue);

              if (num != null) {
                parameterValueObj = Integer.valueOf(num.intValue());
              }
            } catch (ParseException ex) {
              nf.applyPattern("General Number");

              try {
                Number num = nf.parse(reportParameterValue);

                if (num != null) {
                  parameterValueObj = Integer.valueOf(num.intValue());
                }
              } catch (ParseException pex) {
                try {
                  parameterValueObj = Integer.valueOf(reportParameterValue);
                } catch (NumberFormatException nfe) {
                  parameterValueObj = null;
                }
              }
            }
          }
      }
    }

    return parameterValueObj;
  }

  /**
   * Parse the input string to an object.
   *
   * @param reportParameterValue input string to parse
   * @return an object
   */
  protected Object parseDateTime(String reportParameterValue) {
    DateFormatter df = getDateFormatter();
    if (df == null) {
      return null;
    }

    try {
      return df.parse(reportParameterValue);
    } catch (ParseException e) {
      df = new DateFormatter("Short Date", uLocale);
      try {
        return df.parse(reportParameterValue);
      } catch (ParseException ex) {
        df = new DateFormatter("Medium Time", uLocale);
        try {
          return df.parse(reportParameterValue);
        } catch (ParseException exx) {
          return null;
        }
      }
    }
  }
}
 /**
  * Constructs a default <code>PersianCalendar</code> using the current time in the default time
  * zone with the default <code>FORMAT</code> locale.
  *
  * @see Category#FORMAT
  * @internal
  * @deprecated This API is ICU internal only.
  */
 @Deprecated
 public PersianCalendar() {
   this(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT));
 }
 /**
  * Constructs a <code>PersianCalendar</code> with the given date set in the default time zone with
  * the default <code>FORMAT</code> locale.
  *
  * @param date The date to which the new calendar is set.
  * @see Category#FORMAT
  * @internal
  * @deprecated This API is ICU internal only.
  */
 @Deprecated
 public PersianCalendar(Date date) {
   super(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT));
   this.setTime(date);
 }
 /**
  * Constructs a <code>PersianCalendar</code> based on the current time in the default time zone
  * with the given locale.
  *
  * @param aLocale the given locale.
  * @internal
  * @deprecated This API is ICU internal only.
  */
 @Deprecated
 public PersianCalendar(Locale aLocale) {
   this(TimeZone.getDefault(), aLocale);
 }