/** Generates the get field method. */
  private void generateGetField(JavaWriter out) throws IOException {
    out.println();
    out.println("public Object __caucho_get_field(int index)");
    out.println("{");
    out.pushDepth();

    out.println("switch (index) {");
    out.pushDepth();

    ArrayList<AmberField> fields = _embeddableType.getFields();

    for (int i = 0; i < fields.size(); i++) {
      AmberField prop = fields.get(i);

      if (!(prop instanceof PropertyField)) break;

      out.println("case " + i + ":");

      out.println("  return " + prop.generateSuperGetter("this") + ";");

      out.println();
    }

    out.println("default:");
    out.println("  throw new IllegalStateException(\"invalid index: \" + index);");

    out.popDepth();
    out.println("}");

    out.popDepth();
    out.println("}");
  }
  /** Generates the make method. */
  private void generateMake(JavaWriter out) throws IOException {
    ArrayList<AmberField> fields = _embeddableType.getFields();

    out.println();
    out.println("public static " + getClassName() + " __caucho_make(");

    for (int i = 0; i < fields.size(); i++) {
      AmberField prop = fields.get(i);

      out.print("  " + prop.getJavaTypeName() + " a" + i);

      if (i + 1 < fields.size()) out.println(",");
    }

    out.println(")");

    out.println("{");
    out.pushDepth();

    out.println(getClassName() + " bean = new " + getClassName() + "();");

    for (int i = 0; i < fields.size(); i++) {
      AmberField prop = fields.get(i);

      out.println(prop.generateSuperSetter("bean", "a" + i) + ";");
    }

    out.println("return bean;");

    out.popDepth();
    out.println("}");
  }
  /** Generates the initialization. */
  private void generateInit(JavaWriter out) throws IOException {
    String className = getClassName();
    int p = className.lastIndexOf('.');
    if (p > 0) className = className.substring(p + 1);

    ArrayList<AmberField> fields = _embeddableType.getFields();

    for (Constructor ctor : _embeddableType.getBeanClass().getConstructors()) {
      out.println();
      // XXX: s/b actual access type?
      out.print("public ");

      out.print(className);
      out.print("(");

      Class[] args = ctor.getParameterTypes();
      for (int i = 0; i < args.length; i++) {
        if (i != 0) out.print(", ");

        out.printClass(args[i]);
        out.print(" a" + i);
      }
      out.println(")");
      out.println("{");
      out.pushDepth();

      out.print("super(");
      for (int i = 0; i < args.length; i++) {
        if (i != 0) out.print(", ");

        out.print("a" + i);
      }
      out.println(");");

      for (AmberField field : fields) {
        field.generatePostConstructor(out);
      }

      out.popDepth();
      out.println("}");
    }
  }
  /** Generates the load. */
  private void generateLoad(JavaWriter out) throws IOException {
    out.println();
    out.println("public int __caucho_load(com.caucho.amber.manager.AmberConnection aConn,");
    out.println("                         java.sql.ResultSet rs,");
    out.println("                         int index)");
    out.println("  throws java.sql.SQLException");
    out.println("{");
    out.pushDepth();

    if (_embeddableType.isIdClass()) {
      out.println("return 0;");
    } else {
      _embeddableType.generateLoad(out, "rs", "index", 0, -1);

      out.println("return index;");
    }

    out.popDepth();
    out.println("}");
  }
  /** Introspects. */
  private EmbeddableType introspectEmbeddableType(Class type) throws ConfigException, SQLException {
    getInternalEmbeddableConfig(type, _annotationCfg);
    Embeddable embeddableAnn = (Embeddable) _annotationCfg.getAnnotation();
    EmbeddableConfig embeddableConfig = _annotationCfg.getEmbeddableConfig();

    /*
    if (_annotationCfg.isNull())
      return null;
    */

    String typeName = type.getName();
    EmbeddableType embeddableType = _persistenceUnit.createEmbeddable(typeName, type);

    _configManager.addType(type, new EmbeddableConfig(type.getName(), this, embeddableType));

    try {
      boolean isField = isField(type, embeddableConfig);

      if (isField) embeddableType.setFieldAccess(true);

      // XXX: jpa/0u21
      Embeddable ann = (Embeddable) type.getAnnotation(javax.persistence.Embeddable.class);

      if (ann == null) {
        isField = true;
        embeddableType.setIdClass(true);

        _persistenceUnit.getAmberContainer().addEmbeddable(typeName, embeddableType);
      }

      embeddableType.setInstanceClassName(type.getName() + "__ResinExt");
      embeddableType.setEnhanced(true);

      if (isField)
        introspectFields(_persistenceUnit, embeddableType, null, type, embeddableConfig, true);
      else introspectMethods(_persistenceUnit, embeddableType, null, type, embeddableConfig);

    } catch (ConfigException e) {
      if (embeddableType != null) embeddableType.setConfigException(e);

      throw e;
    } catch (RuntimeException e) {
      if (embeddableType != null) embeddableType.setConfigException(e);

      throw e;
    }

    return embeddableType;
  }
  /** Generates the make method. */
  private void generateMakeFromLoad(JavaWriter out) throws IOException {
    ArrayList<AmberField> fields = _embeddableType.getFields();

    out.println();
    out.println("public static " + getClassName() + " __caucho_make(");
    out.println("  com.caucho.amber.manager.AmberConnection aConn,");
    out.println("  java.sql.ResultSet rs,");
    out.println("  int index)");
    out.println("  throws java.sql.SQLException");

    out.println("{");
    out.pushDepth();

    out.println(getClassName() + " bean = new " + getClassName() + "();");

    out.println("bean.__caucho_load(aConn, rs, index);");

    out.println("return bean;");

    out.popDepth();
    out.println("}");
  }