private void build() {
    ClassWriter cw = new ClassWriter(0);
    final ClassLoader cl = getClass().getClassLoader();
    for (SVDBItemType t : SVDBItemType.values()) {
      Class cls = null;
      for (String pkg : fTargetPkgList) {
        try {
          cls = cl.loadClass(pkg + ".SVDB" + t.name());
        } catch (Exception e) {
        }

        if (cls != null) {
          break;
        }
      }

      if (cls != null) {
        // Found a class to process
        fTypeClassMap.put(t, cls);
      } else {
        System.out.println("Error: Failed to find item " + t.name());
      }
    }

    //		long start = System.currentTimeMillis();
    build_boilerplate(cw);

    for (SVDBItemType t : fTypeClassMap.keySet()) {
      Class cls = fTypeClassMap.get(t);
      buildItemAccessor(cw, t, cls);
    }

    for (Class c : fClassList) {
      buildObjectAccessor(cw, c);
    }

    cw.visitEnd();

    JITClassLoader jit_cl = new JITClassLoader(cl, cw.toByteArray());
    try {
      fDelegateCls =
          (Class<JITPersistenceDelegateBase>)
              jit_cl.loadClass(fTargetPkg + ".SVDBPersistenceDelegate");
    } catch (Exception e) {
      e.printStackTrace();
    }

    /*
    long end = System.currentTimeMillis();

    System.out.println("Class-build time: " + (end-start));
    System.out.println("Size: " + cw.toByteArray().length);
     */
  }
  private void buildItemAccessor(ClassWriter cw, SVDBItemType t, Class cls) {
    MethodVisitor mv;

    if (fDebugEn) {
      debug("--> buildAccessor t=" + t.name() + " cls=" + cls.getName());
    }

    // Constructor
    String item_name = t.name();
    String tgt_clsname = getClassName(cls);

    // Read method
    //
    // 0 - this
    // 1 - parent
    // 2 - object
    mv =
        cw.visitMethod(
            ACC_PRIVATE,
            "read" + item_name,
            "(L" + fChildItem + ";)L" + tgt_clsname + ";",
            null,
            new String[] {fDBFormatException});
    mv.visitCode();
    mv.visitTypeInsn(NEW, tgt_clsname); // Create a new class instance
    mv.visitInsn(DUP); // Duplicate handle. One will be consumed by the init call
    mv.visitMethodInsn(INVOKESPECIAL, tgt_clsname, "<init>", "()V");
    //		mv.visitInsn(DUP);					// Duplicate. One will be consumed by store to obj-var
    mv.visitVarInsn(ASTORE, READ_OBJ_VAR); // Store handle to obj-var
    //		mv.visitVarInsn(ALOAD, THIS_VAR);
    //		mv.visitVarInsn(ALOAD, READ_OBJ_VAR);
    //		mv.visitMethodInsn(INVOKESPECIAL, tgt_clsname, "<init>", "()V");
    //		mv.visit
    //		mv.visitInsn(ACONST_NULL);
    //		mv.visitVarInsn(ASTORE, READ_OBJ_VAR); // Initialize return
    visit(false, tgt_clsname, mv, cls);
    mv.visitVarInsn(ALOAD, READ_OBJ_VAR); // Setup for return of var0
    mv.visitInsn(ARETURN);
    mv.visitMaxs(3, 3);
    mv.visitEnd();

    // Write method
    //
    // 0 - this
    // 1 - object
    mv =
        cw.visitMethod(
            ACC_PRIVATE,
            "write" + item_name,
            // "(L" + tgt_clsname + ";)V",
            "(L" + tgt_clsname + ";)V",
            null,
            new String[] {fDBWriteException});
    mv.visitCode();
    visit(true, tgt_clsname, mv, cls);
    mv.visitInsn(RETURN);
    mv.visitMaxs(3, 3);
    mv.visitEnd();

    if (fDebugEn) {
      debug("<-- buildAccessor t=" + t + " cls=" + cls.getName());
    }
  }
  private void buildItemDispatchMethods(ClassWriter cw) {
    String classname = "SVDBPersistenceDelegate";
    String full_classname = transform_cls(fTargetPkg) + "/" + classname;

    Label labels[] = new Label[SVDBItemType.values().length];
    int indexes[] = new int[SVDBItemType.values().length];
    Label dflt, endcase;

    for (int i = 0; i < SVDBItemType.values().length; i++) {
      indexes[i] = i;
    }

    // writeItem Dispatch method
    MethodVisitor mv =
        cw.visitMethod(
            ACC_PUBLIC,
            "writeSVDBItem",
            "(L" + getClassName(ISVDBItemBase.class) + ";)V",
            null,
            new String[] {fDBWriteException});
    for (int i = 0; i < SVDBItemType.values().length; i++) {
      labels[i] = new Label();
    }
    dflt = new Label();
    endcase = new Label();

    // Retrieve the object type
    mv.visitVarInsn(ALOAD, WRITE_OBJ_VAR);
    mv.visitMethodInsn(
        INVOKEINTERFACE,
        getClassName(ISVDBItemBase.class),
        "getType",
        "()L" + getClassName(SVDBItemType.class) + ";");
    mv.visitMethodInsn(INVOKEVIRTUAL, getClassName(SVDBItemType.class), "ordinal", "()I");
    mv.visitLookupSwitchInsn(dflt, indexes, labels);
    for (SVDBItemType t : SVDBItemType.values()) {
      Class c = fTypeClassMap.get(t);
      mv.visitLabel(labels[t.ordinal()]);

      mv.visitVarInsn(ALOAD, THIS_VAR);
      mv.visitVarInsn(ALOAD, WRITE_OBJ_VAR);
      mv.visitTypeInsn(CHECKCAST, getClassName(c));
      mv.visitMethodInsn(
          INVOKESPECIAL, full_classname, "write" + t.name(), "(L" + getClassName(c) + ";)V");
      mv.visitJumpInsn(GOTO, endcase);
    }
    mv.visitLabel(dflt);
    mv.visitLabel(endcase);
    mv.visitInsn(RETURN);
    mv.visitMaxs(16, 16);
    mv.visitEnd();

    // readItem dispatch method
    mv =
        cw.visitMethod(
            ACC_PUBLIC,
            "readSVDBItem",
            "(L"
                + getClassName(SVDBItemType.class)
                + ";L"
                + getClassName(ISVDBChildItem.class)
                + ";)L"
                + getClassName(ISVDBItemBase.class)
                + ";",
            null,
            new String[] {fDBWriteException});
    for (int i = 0; i < SVDBItemType.values().length; i++) {
      labels[i] = new Label();
    }
    dflt = new Label();
    endcase = new Label();

    mv.visitVarInsn(ALOAD, 1); // object type
    mv.visitMethodInsn(INVOKEVIRTUAL, getClassName(SVDBItemType.class), "ordinal", "()I");
    mv.visitLookupSwitchInsn(dflt, indexes, labels);
    for (SVDBItemType t : SVDBItemType.values()) {
      Class c = fTypeClassMap.get(t);
      mv.visitLabel(labels[t.ordinal()]);

      mv.visitVarInsn(ALOAD, THIS_VAR);
      mv.visitVarInsn(ALOAD, 2); // parent
      mv.visitMethodInsn(
          INVOKESPECIAL,
          full_classname,
          "read" + t.name(),
          "(L" + getClassName(ISVDBChildItem.class) + ";)" + "L" + getClassName(c) + ";");
      mv.visitJumpInsn(GOTO, endcase);
    }
    mv.visitLabel(dflt);
    mv.visitInsn(ACONST_NULL);
    mv.visitLabel(endcase);
    mv.visitInsn(ARETURN);
    mv.visitMaxs(16, 16);
    mv.visitEnd();
  }