@Override
 protected void fillSeries(TsInformation info, DataSet dataSet) throws IOException {
   sleep(info.type);
   switch (dataTypeParam.get(dataSet.getDataSource())) {
     case NORMAL:
       if (info.type.needsData()) {
         Ts ts = normalData.get(indexParam.get(dataSet));
         support.fillSeries(info, OptionalTsData.present(0, 0, ts.getTsData()), false);
         info.type = TsInformationType.All;
       }
       break;
     case FAILING_META:
       throw new IOException("Cannot load dataset");
     case FAILING_DATA:
       if (info.type.needsData()) {
         throw new IOException("Cannot load dataset");
       }
       break;
     case UPDATING:
       if (info.type.needsData()) {
         Ts ts = dataBuilder.build().get(0);
         support.fillSeries(info, OptionalTsData.present(0, 0, ts.getTsData()), false);
         info.type = TsInformationType.All;
       }
       break;
     default:
       throw new IOException("???");
   }
 }
 @Override
 protected void fillCollection(TsCollectionInformation info, DataSource dataSource)
     throws IOException {
   sleep(info.type);
   switch (dataTypeParam.get(dataSource)) {
     case NORMAL:
       DataSet.Builder builder = DataSet.builder(dataSource, DataSet.Kind.SERIES);
       for (int i = 0; i < normalData.getCount(); i++) {
         indexParam.set(builder, i);
         TsInformation tsInfo = newTsInformation(builder.build(), info.type);
         if (info.type.needsData()) {
           support.fillSeries(
               tsInfo, OptionalTsData.present(0, 0, normalData.get(i).getTsData()), false);
           info.type = TsInformationType.All; // FIXME: TsInformationType.Data fails ???
         }
         info.items.add(tsInfo);
       }
       break;
     case FAILING_META:
       throw new IOException("Cannot load datasource");
     case FAILING_DATA:
       if (info.type.needsData()) {
         throw new IOException("Cannot load datasource");
       }
       DataSet.Builder b2 = DataSet.builder(dataSource, DataSet.Kind.SERIES);
       for (int i = 0; i < normalData.getCount(); i++) {
         indexParam.set(b2, i);
         TsInformation tsInfo = newTsInformation(b2.build(), info.type);
         info.items.add(tsInfo);
       }
       break;
     case UPDATING:
       DataSet.Builder b3 = DataSet.builder(dataSource, DataSet.Kind.SERIES);
       TsCollection data = dataBuilder.build();
       for (int i = 0; i < data.getCount(); i++) {
         indexParam.set(b3, i);
         TsInformation tsInfo = newTsInformation(b3.build(), info.type);
         if (info.type.needsData()) {
           support.fillSeries(
               tsInfo, OptionalTsData.present(0, 0, data.get(i).getTsData()), false);
           info.type = TsInformationType.All;
         }
         info.items.add(tsInfo);
       }
       break;
     default:
       throw new IOException("???");
   }
 }
  public FakeTsProvider() {
    super(LoggerFactory.getLogger(FakeTsProvider.class), "Fake", TsAsyncMode.Once);

    dataBuilder = new DemoUtils.RandomTsCollectionBuilder();
    normalData = dataBuilder.build();

    DataSource.Builder builder = DataSource.builder(providerName, "");
    for (DataType o : DataType.values()) {
      dataTypeParam.set(builder, o);
      support.open(builder.build());
    }

    dataTypeParam.set(builder, DataType.UPDATING);
    final TsMoniker updatingMoniker = toMoniker(builder.build());

    this.service =
        new AbstractExecutionThreadService() {

          @Override
          protected Executor executor() {
            return Executors.newSingleThreadExecutor(
                new ThreadFactoryBuilder()
                    .setDaemon(true)
                    .setPriority(Thread.MIN_PRIORITY)
                    .build());
          }

          @Override
          protected void run() throws Exception {
            while (isRunning()) {
              queryTsCollection(updatingMoniker, TsInformationType.All);
              TimeUnit.SECONDS.sleep(3);
            }
          }
        }.startAsync();
  }