/**
   * TODO v0.8 implement array mutation @Test public void testMutatingGeneration() { Object[]
   * MUTATED_ALICE = new Object[] { "Alice", 24 };
   *
   * <p>// define descriptor ArrayTypeDescriptor descriptor = createPersonDescriptor();
   * descriptor.setGenerator(PersonAttrArrayGenerator.class.getName());
   * descriptor.getElement(1).getLocalType(false).setScript("p[1] + 1");
   *
   * <p>// create generator Generator<Object[]> generator =
   * ArrayGeneratorFactory.createArrayGenerator( "p", descriptor, Uniqueness.NONE, context);
   * generator.init(context);
   *
   * <p>// validate for (int i = 0; i < 10; i++) assertEqualArrays(MUTATED_ALICE,
   * GeneratorUtil.generateNonNull(generator)); }
   */
  @Test
  public void testUniqueArrayGeneration() {
    ArrayTypeDescriptor arrayTypeDescriptor = createArrayType("MyArray");

    // create descriptor
    context.set("gen0", new SequenceTestGenerator<Integer>(1, 2));
    ArrayElementDescriptor e0 = createArrayElement(0, "int");
    ((SimpleTypeDescriptor) e0.getLocalType(false)).setGenerator("gen0");
    arrayTypeDescriptor.addElement(e0);

    context.set("gen1", new SequenceTestGenerator<Integer>(3, 4));
    ArrayElementDescriptor e1 = createArrayElement(1, "int");
    ((SimpleTypeDescriptor) e1.getLocalType(false)).setGenerator("gen1");
    arrayTypeDescriptor.addElement(e1);

    InstanceDescriptor arrayInstDescriptor = createInstance("array", arrayTypeDescriptor);
    arrayInstDescriptor.setUnique(true);

    // create generator
    Generator<Object[]> generator =
        (Generator<Object[]>)
            InstanceGeneratorFactory.createSingleInstanceGenerator(
                arrayInstDescriptor, Uniqueness.NONE, context);
    generator.init(context);

    // test generator
    assertArray(INT13, GeneratorUtil.generateNonNull(generator));
    assertArray(INT14, GeneratorUtil.generateNonNull(generator));
    assertArray(INT23, GeneratorUtil.generateNonNull(generator));
    assertArray(INT24, GeneratorUtil.generateNonNull(generator));
    assertUnavailable(generator);
  }
  @Test
  public void testUniqueValuesArrayGeneration() {
    ArrayElementDescriptor e0 = createArrayElement(0, "int");
    ((SimpleTypeDescriptor) e0.getLocalType(false)).setValues("1,2");

    ArrayElementDescriptor e1 = createArrayElement(1, "int");
    ((SimpleTypeDescriptor) e1.getLocalType(false)).setValues("3,4");

    ArrayTypeDescriptor arrayTypeDescriptor = createArrayType("MyArray");
    arrayTypeDescriptor.addElement(e0);
    arrayTypeDescriptor.addElement(e1);

    InstanceDescriptor arrayInstDescriptor = createInstance("array", arrayTypeDescriptor);
    arrayInstDescriptor.setUnique(true);

    Generator<Object[]> generator =
        (Generator<Object[]>)
            InstanceGeneratorFactory.createSingleInstanceGenerator(
                arrayInstDescriptor, Uniqueness.NONE, context);
    generator.init(context);
    for (int i = 0; i < 4; i++) {
      Object[] product = GeneratorUtil.generateNonNull(generator);
      assertTrue(
          Arrays.equals(INT13, product)
              || Arrays.equals(INT14, product)
              || Arrays.equals(INT23, product)
              || Arrays.equals(INT24, product));
    }
    assertUnavailable(generator);
  }
 @Test
 public void testSyntheticGeneration() {
   // given an array descriptor
   ArrayTypeDescriptor arrayDescriptor = createArrayType("");
   ArrayElementDescriptor e1 = createArrayElement(0, "string");
   ((SimpleTypeDescriptor) e1.getLocalType(false)).setValues("'Alice', 'Bob'");
   arrayDescriptor.addElement(e1);
   ArrayElementDescriptor e2 = createArrayElement(1, "int");
   ((SimpleTypeDescriptor) e2.getLocalType(false)).setValues("23,34");
   arrayDescriptor.addElement(e2);
   // when creating a generator for the descriptor
   Generator<Object[]> generator =
       (Generator<Object[]>)
           arrayTypeGeneratorFactory.createGenerator(
               arrayDescriptor, "testSyntheticGeneration", false, Uniqueness.NONE, context);
   // it is expected to generate as specified
   generator.init(context);
   for (int i = 0; i < 10; i++) {
     Object[] product = GeneratorUtil.generateNonNull(generator);
     assertNotNull(product);
     assertTrue(
         "Expected 'Alice' or 'Bob', but was: " + product[0],
         "Alice".equals(product[0]) || "Bob".equals(product[0]));
     assertTrue((Integer) product[1] == 23 || (Integer) product[1] == 34);
   }
 }
 protected ArrayElementDescriptor getElementOfTypeOrParents(
     ArrayTypeDescriptor arrayType, int index) {
   ArrayTypeDescriptor tmp = arrayType;
   ArrayElementDescriptor result;
   while ((result = tmp.getElement(index)) == null && tmp.getParent() != null)
     tmp = tmp.getParent();
   return result;
 }
 private ArrayTypeDescriptor createPersonDescriptor() {
   ArrayTypeDescriptor arrayDescriptor = createArrayType("personType");
   ArrayElementDescriptor e1 = createArrayElement(0, "string");
   arrayDescriptor.addElement(e1);
   ArrayElementDescriptor e2 = createArrayElement(1, "int");
   arrayDescriptor.addElement(e2);
   return arrayDescriptor;
 }
 @Test(expected = ConfigurationError.class)
 public void testIllegalSourceType() {
   ArrayTypeDescriptor descriptor = createArrayType("");
   descriptor.setSource("illegalSource");
   context.set("illegalSource", new File("txt.txt"));
   Generator<Object[]> generator =
       (Generator<Object[]>)
           arrayTypeGeneratorFactory.createGenerator(
               descriptor, "testIllegalSourceType", false, Uniqueness.NONE, context);
   generator.init(context);
 }
 @Test
 public void testGenerator() {
   ArrayTypeDescriptor descriptor = createArrayType("testGenerator");
   descriptor.setGenerator(PersonAttrArrayGenerator.class.getName());
   Generator<Object[]> generator =
       (Generator<Object[]>)
           arrayTypeGeneratorFactory.createGenerator(
               descriptor, "testGenerator", false, Uniqueness.NONE, context);
   generator.init(context);
   for (int i = 0; i < 10; i++)
     assertEqualArrays(PersonAttrArrayGenerator.ALICE, GeneratorUtil.generateNonNull(generator));
 }
 @Test
 public void testXlsSource() {
   ArrayTypeDescriptor parent = createPersonDescriptor();
   ArrayTypeDescriptor descriptor = createArrayType("testXlsSource", parent);
   descriptor.setSource("org/databene/benerator/factory/person.ent.xls");
   Generator<Object[]> generator =
       (Generator<Object[]>)
           arrayTypeGeneratorFactory.createGenerator(
               descriptor, "testXlsSource", false, Uniqueness.NONE, context);
   context.set("otto_age", 89);
   generator.init(context);
   expectGeneratedSequence(generator, ALICE, OTTO).withCeasedAvailability();
 }
 @Test
 public void testGeneratorSource() {
   context.set("myGen", new PersonAttrArrayGenerator());
   ArrayTypeDescriptor parent = createPersonDescriptor();
   ArrayTypeDescriptor descriptor = createArrayType("testGeneratorSource", parent);
   descriptor.setSource("myGen");
   Generator<Object[]> generator =
       (Generator<Object[]>)
           arrayTypeGeneratorFactory.createGenerator(
               descriptor, "testGeneratorSource", false, Uniqueness.NONE, context);
   generator.init(context);
   for (int i = 0; i < 10; i++) assertEqualArrays(ALICE, GeneratorUtil.generateNonNull(generator));
 }
 @SuppressWarnings("rawtypes")
 private Generator<?>[] createSyntheticElementGenerators(
     ArrayTypeDescriptor arrayType, Uniqueness uniqueness, BeneratorContext context) {
   Generator[] result = new Generator[arrayType.getElementCount()];
   for (int i = 0; i < arrayType.getElementCount(); i++) {
     ArrayElementDescriptor element = getElementOfTypeOrParents(arrayType, i);
     if (element.getMode() != Mode.ignored) {
       Generator<?> generator =
           InstanceGeneratorFactory.createSingleInstanceGenerator(element, uniqueness, context);
       result[i] = generator;
     }
   }
   return result;
 }
 @Test
 public void testCsvSource() {
   ArrayTypeDescriptor parent = createPersonDescriptor();
   ArrayTypeDescriptor descriptor = createArrayType("testCsvSource", parent);
   descriptor.setSource("org/databene/benerator/factory/person.ent.csv");
   Generator<Object[]> generator =
       (Generator<Object[]>)
           arrayTypeGeneratorFactory.createGenerator(
               descriptor, "testCsvSource", false, Uniqueness.NONE, context);
   context.set("ottos_age", 89);
   generator.init(context);
   assertEqualArrays(ALICE, GeneratorUtil.generateNonNull(generator));
   assertEqualArrays(OTTO, GeneratorUtil.generateNonNull(generator));
   assertUnavailable(generator);
 }
 @Test
 public void testEntitySource() {
   ArrayTypeDescriptor descriptor = createArrayType("testEntitySourceType");
   descriptor.setSource(PersonSource.class.getName());
   Generator<Object[]> generator =
       (Generator<Object[]>)
           arrayTypeGeneratorFactory.createGenerator(
               descriptor, "testEntitySource", false, Uniqueness.NONE, context);
   generator.init(context);
   for (int i = 0; i < 2; i++) {
     Object[] product = GeneratorUtil.generateNonNull(generator);
     assertTrue(
         "Found: " + ArrayFormat.format(product),
         Arrays.equals(ALICE, product) || Arrays.equals(BOB, product));
   }
   assertUnavailable(generator);
 }
 @Override
 protected Generator<?> createHeuristicGenerator(
     ArrayTypeDescriptor descriptor,
     String instanceName,
     Uniqueness uniqueness,
     BeneratorContext context) {
   return new BlankArrayGenerator(descriptor.getElementCount());
 }
 @Test
 public void testCsvDataset() {
   ArrayTypeDescriptor parent = createPersonDescriptor();
   ArrayTypeDescriptor descriptor = createArrayType("testCsvDataset", parent);
   descriptor.setSource("org/databene/benerator/factory/dataset_{0}.csv");
   descriptor.setNesting("org/databene/benerator/factory/testnesting");
   descriptor.setDataset("DACH");
   Generator<Object[]> generator =
       (Generator<Object[]>)
           arrayTypeGeneratorFactory.createGenerator(
               descriptor, "testCsvDataset", false, Uniqueness.SIMPLE, context);
   Generator<String> g =
       WrapperFactory.applyConverter(
           generator, new ArrayElementExtractor<String>(String.class, 0));
   generator.init(context);
   expectUniquelyGeneratedSet(g, "de", "at", "ch");
   assertUnavailable(generator);
 }
 @Override
 protected Generator<Object[]> createSourceGenerator(
     ArrayTypeDescriptor descriptor, Uniqueness uniqueness, BeneratorContext context) {
   // if no sourceObject is specified, there's nothing to do
   String sourceName = descriptor.getSource();
   if (sourceName == null) return null;
   // create sourceObject generator
   Generator<Object[]> generator = null;
   Object contextSourceObject = context.get(sourceName);
   if (contextSourceObject != null)
     generator =
         createSourceGeneratorFromObject(descriptor, context, generator, contextSourceObject);
   else {
     String lcSourceName = sourceName.toLowerCase();
     if (lcSourceName.endsWith(".csv"))
       generator = createCSVSourceGenerator(descriptor, context, sourceName);
     else if (lcSourceName.endsWith(".xls"))
       generator = createXLSSourceGenerator(descriptor, context, sourceName);
     else {
       try {
         BeanSpec sourceBeanSpec = DatabeneScriptParser.resolveBeanSpec(sourceName, context);
         Object sourceObject = sourceBeanSpec.getBean();
         if (!sourceBeanSpec.isReference() && sourceObject instanceof ContextAware)
           ((ContextAware) sourceObject).setContext(context);
         generator = createSourceGeneratorFromObject(descriptor, context, generator, sourceObject);
         if (sourceBeanSpec.isReference()) generator = WrapperFactory.preventClosing(generator);
         return generator;
       } catch (Exception e) {
         throw new UnsupportedOperationException("Unknown source type: " + sourceName);
       }
     }
   }
   if (descriptor.getFilter() != null) {
     Expression<Boolean> filter =
         new ScriptExpression<Boolean>(ScriptUtil.parseScriptText(descriptor.getFilter()));
     generator = new FilteringGenerator<Object[]>(generator, filter);
   }
   Distribution distribution =
       FactoryUtil.getDistribution(descriptor.getDistribution(), uniqueness, false, context);
   if (distribution != null)
     generator =
         new DistributingGenerator<Object[]>(generator, distribution, uniqueness.isUnique());
   return generator;
 }
  @Test
  public void testDatabaseSource() throws Exception {
    // prepare DB
    DBSystem db =
        new DBSystem(
            "db",
            HSQLUtil.getInMemoryURL("benerator"),
            HSQLUtil.DRIVER,
            "sa",
            null,
            context.getDataModel());
    context.set("db", db);
    try {
      db.execute(
          "create table agft_person ("
              + "  id   int         NOT NULL,"
              + "  name varchar(30) NOT NULL,"
              + "  age  int         NOT NULL"
              + ")");
      db.execute("insert into agft_person (id, name, age) values (1, 'Alice', 23)");
      db.execute("insert into agft_person (id, name, age) values (2, 'Otto', 89)");

      // prepare descriptor
      ArrayTypeDescriptor parent = createPersonDescriptor();
      ArrayTypeDescriptor descriptor = createArrayType("testDatabaseSource", parent);
      descriptor.setSource("db");
      descriptor.setSelector("select name, age from agft_person");
      Generator<Object[]> generator =
          (Generator<Object[]>)
              arrayTypeGeneratorFactory.createGenerator(
                  descriptor, "testDatabaseSource", false, Uniqueness.NONE, context);
      generator.init(context);

      // verify results
      assertEqualArrays(ALICE, GeneratorUtil.generateNonNull(generator));
      Object[] p2 = GeneratorUtil.generateNonNull(generator);
      assertEqualArrays(OTTO, p2);
      assertUnavailable(generator);

    } finally {
      db.execute("drop table agft_person if exists");
      db.close();
    }
  }
 @SuppressWarnings({"unchecked", "rawtypes"})
 private static Generator<Object[]> createSourceGeneratorFromObject(
     ArrayTypeDescriptor descriptor,
     BeneratorContext context,
     Generator<Object[]> generator,
     Object sourceObject) {
   if (sourceObject instanceof StorageSystem) {
     StorageSystem storage = (StorageSystem) sourceObject;
     String selector = descriptor.getSelector();
     String subSelector = descriptor.getSubSelector();
     if (!StringUtil.isEmpty(subSelector))
       generator =
           WrapperFactory.applyHeadCycler(
               new DataSourceGenerator(storage.query(subSelector, false, context)));
     else generator = new DataSourceGenerator(storage.query(selector, false, context));
   } else if (sourceObject instanceof EntitySource) {
     DataSourceGenerator<Entity> entityGenerator =
         new DataSourceGenerator<Entity>((EntitySource) sourceObject);
     generator = WrapperFactory.applyConverter(entityGenerator, new Entity2ArrayConverter());
   } else if (sourceObject instanceof Generator) {
     generator = (Generator<Object[]>) sourceObject;
   } else throw new ConfigurationError("Source type not supported: " + sourceObject.getClass());
   return generator;
 }
 private Generator<Object[]> createXLSSourceGenerator(
     ArrayTypeDescriptor arrayType, BeneratorContext context, String sourceName) {
   logger.debug("createXLSSourceGenerator({})", arrayType);
   boolean rowBased = (arrayType.isRowBased() != null ? arrayType.isRowBased() : true);
   String emptyMarker = arrayType.getEmptyMarker();
   String nullMarker = arrayType.getNullMarker();
   boolean formatted = isFormatted(arrayType);
   DataSourceProvider<Object[]> factory =
       new XLSArraySourceProvider(
           formatted, new ScriptConverterForObjects(context), emptyMarker, nullMarker, rowBased);
   Generator<Object[]> generator =
       SourceFactory.createRawSourceGenerator(
           arrayType.getNesting(),
           arrayType.getDataset(),
           sourceName,
           factory,
           Object[].class,
           context);
   generator = WrapperFactory.applyConverter(generator, new ArrayElementTypeConverter(arrayType));
   return generator;
 }
 private Generator<Object[]> createCSVSourceGenerator(
     ArrayTypeDescriptor arrayType, BeneratorContext context, String sourceName) {
   logger.debug("createCSVSourceGenerator({})", arrayType);
   String encoding = arrayType.getEncoding();
   if (encoding == null) encoding = context.getDefaultEncoding();
   char separator = DescriptorUtil.getSeparator(arrayType, context);
   boolean rowBased = (arrayType.isRowBased() != null ? arrayType.isRowBased() : true);
   DataSourceProvider<Object[]> factory =
       new CSVArraySourceProvider(
           arrayType.getName(),
           new ScriptConverterForStrings(context),
           rowBased,
           separator,
           encoding);
   Generator<Object[]> generator =
       SourceFactory.createRawSourceGenerator(
           arrayType.getNesting(),
           arrayType.getDataset(),
           sourceName,
           factory,
           Object[].class,
           context);
   return WrapperFactory.applyConverter(generator, new ArrayElementTypeConverter(arrayType));
 }