private boolean hasFileName() {
   for (PropertyDeclaration property : model.getDeclaredProperties()) {
     if (CsvFieldTrait.getKind(property, Kind.VALUE) == Kind.FILE_NAME) {
       return true;
     }
   }
   return false;
 }
 private MethodDeclaration createGetConfiguration() {
   List<Statement> statements = Lists.create();
   List<Expression> arguments = Lists.create();
   arguments.add(
       new TypeBuilder(f, context.resolve(Charset.class))
           .method("forName", Models.toLiteral(f, conf.getCharsetName()))
           .toExpression());
   if (conf.isEnableHeader()) {
     SimpleName headers = f.newSimpleName("headers");
     statements.add(
         new TypeBuilder(f, context.resolve(ArrayList.class))
             .parameterize(context.resolve(String.class))
             .newObject()
             .toLocalVariableDeclaration(
                 new TypeBuilder(f, context.resolve(List.class))
                     .parameterize(context.resolve(String.class))
                     .toType(),
                 headers));
     for (PropertyDeclaration property : model.getDeclaredProperties()) {
       if (isValueField(property)) {
         String fieldName = CsvFieldTrait.getFieldName(property);
         statements.add(
             new ExpressionBuilder(f, headers)
                 .method("add", Models.toLiteral(f, fieldName))
                 .toStatement());
       }
     }
     arguments.add(headers);
   } else {
     arguments.add(
         new TypeBuilder(f, context.resolve(CsvConfiguration.class))
             .field("DEFAULT_HEADER_CELLS")
             .toExpression());
   }
   arguments.add(Models.toLiteral(f, conf.getTrueFormat()));
   arguments.add(Models.toLiteral(f, conf.getFalseFormat()));
   arguments.add(Models.toLiteral(f, conf.getDateFormat()));
   arguments.add(Models.toLiteral(f, conf.getDateTimeFormat()));
   statements.add(
       new TypeBuilder(f, context.resolve(CsvConfiguration.class))
           .newObject(arguments)
           .toReturnStatement());
   return f.newMethodDeclaration(
       new JavadocBuilder(f)
           .text("Returns this CSV format configuration.")
           .returns()
           .text("CSV format configuration")
           .toJavadoc(),
       new AttributeBuilder(f).Protected().toAttributes(),
       context.resolve(CsvConfiguration.class),
       f.newSimpleName(METHOD_CONFIG),
       Collections.<FormalParameterDeclaration>emptyList(),
       statements);
 }
    private ClassDeclaration createReaderClass() {
      SimpleName parser = f.newSimpleName("parser");
      List<TypeBodyDeclaration> members = Lists.create();
      members.add(createPrivateField(CsvParser.class, parser));
      List<ExpressionStatement> constructorStatements = Lists.create();
      constructorStatements.add(mapField(parser));
      if (hasFileName()) {
        members.add(createPrivateField(StringOption.class, f.newSimpleName(FIELD_PATH_NAME)));
        constructorStatements.add(
            new ExpressionBuilder(f, f.newSimpleName(FIELD_PATH_NAME))
                .assignFrom(
                    new TypeBuilder(f, context.resolve(StringOption.class))
                        .newObject(
                            new ExpressionBuilder(f, parser).method("getPath").toExpression())
                        .toExpression())
                .toStatement());
      }
      members.add(
          f.newConstructorDeclaration(
              null,
              new AttributeBuilder(f).toAttributes(),
              f.newSimpleName(NAME_READER),
              Arrays.asList(
                  f.newFormalParameterDeclaration(context.resolve(CsvParser.class), parser)),
              constructorStatements));

      SimpleName object = f.newSimpleName("object");
      List<Statement> statements = Lists.create();
      statements.add(
          f.newIfStatement(
              new ExpressionBuilder(f, parser)
                  .method("next")
                  .apply(InfixOperator.EQUALS, Models.toLiteral(f, false))
                  .toExpression(),
              f.newBlock(
                  new ExpressionBuilder(f, Models.toLiteral(f, false)).toReturnStatement())));
      for (PropertyDeclaration property : model.getDeclaredProperties()) {
        switch (CsvFieldTrait.getKind(property, Kind.VALUE)) {
          case VALUE:
            statements.add(
                new ExpressionBuilder(f, parser)
                    .method(
                        "fill",
                        new ExpressionBuilder(f, object)
                            .method(context.getOptionGetterName(property))
                            .toExpression())
                    .toStatement());
            break;
          case FILE_NAME:
            statements.add(
                new ExpressionBuilder(f, object)
                    .method(context.getOptionSetterName(property), f.newSimpleName(FIELD_PATH_NAME))
                    .toStatement());
            break;
          case LINE_NUMBER:
            statements.add(
                new ExpressionBuilder(f, object)
                    .method(
                        context.getValueSetterName(property),
                        new ExpressionBuilder(f, parser)
                            .method("getCurrentLineNumber")
                            .toExpression())
                    .toStatement());
            break;
          case RECORD_NUMBER:
            statements.add(
                new ExpressionBuilder(f, object)
                    .method(
                        context.getValueSetterName(property),
                        new ExpressionBuilder(f, parser)
                            .method("getCurrentRecordNumber")
                            .toExpression())
                    .toStatement());
            break;
          default:
            // ignored
            break;
        }
      }
      statements.add(new ExpressionBuilder(f, parser).method("endRecord").toStatement());
      statements.add(new ExpressionBuilder(f, Models.toLiteral(f, true)).toReturnStatement());
      members.add(
          f.newMethodDeclaration(
              null,
              new AttributeBuilder(f)
                  .annotation(context.resolve(Override.class))
                  .Public()
                  .toAttributes(),
              Collections.<TypeParameterDeclaration>emptyList(),
              context.resolve(boolean.class),
              f.newSimpleName("readTo"),
              Arrays.asList(
                  f.newFormalParameterDeclaration(context.resolve(model.getSymbol()), object)),
              0,
              Arrays.asList(context.resolve(IOException.class)),
              f.newBlock(statements)));

      return f.newClassDeclaration(
          null,
          new AttributeBuilder(f).Private().Static().Final().toAttributes(),
          f.newSimpleName(NAME_READER),
          null,
          Arrays.asList(
              f.newParameterizedType(
                  context.resolve(DataModelReader.class), context.resolve(model.getSymbol()))),
          members);
    }
 static boolean isValueField(PropertyDeclaration property) {
   assert property != null;
   return CsvFieldTrait.getKind(property, Kind.VALUE) == Kind.VALUE;
 }